Files
GNX-WEB/gnx-react/components/shared/OptimizedImage.tsx
Iliyan Angelov 76c857b4f5 update
2025-10-10 21:54:39 +03:00

208 lines
4.8 KiB
TypeScript

'use client';
import Image from 'next/image';
import { useState } from 'react';
interface OptimizedImageProps {
src: string;
alt: string;
width?: number;
height?: number;
className?: string;
priority?: boolean;
fill?: boolean;
sizes?: string;
quality?: number;
style?: React.CSSProperties;
objectFit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
loading?: 'lazy' | 'eager';
}
/**
* OptimizedImage Component
*
* An enterprise-grade optimized image component that provides:
* - Automatic lazy loading
* - Responsive images with srcset
* - WebP/AVIF format support
* - Blur placeholder while loading
* - Error handling with fallback
* - Performance optimization
*
* @example
* <OptimizedImage
* src="/images/hero.jpg"
* alt="Hero banner showcasing our services"
* width={1200}
* height={600}
* priority={true}
* />
*/
export default function OptimizedImage({
src,
alt,
width,
height,
className = '',
priority = false,
fill = false,
sizes,
quality = 85,
style,
objectFit = 'cover',
loading,
}: OptimizedImageProps) {
const [imgSrc, setImgSrc] = useState(src);
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
// Fallback image for errors
const fallbackImage = '/images/placeholder.png';
// Handle image load
const handleLoad = () => {
setIsLoading(false);
};
// Handle image error
const handleError = () => {
setHasError(true);
setIsLoading(false);
if (imgSrc !== fallbackImage) {
setImgSrc(fallbackImage);
}
};
// SEO-friendly alt text validation
const seoAlt = alt || 'GNX Soft - Enterprise Software Solutions';
// Validate alt text for SEO
if (process.env.NODE_ENV === 'development' && !alt) {
console.warn(
`OptimizedImage: Missing alt text for image "${src}". Alt text is crucial for SEO and accessibility.`
);
}
// Common image props
const imageProps = {
src: imgSrc,
alt: seoAlt,
className: `${className} ${isLoading ? 'image-loading' : 'image-loaded'}`,
onLoad: handleLoad,
onError: handleError,
quality,
loading: loading || (priority ? 'eager' : 'lazy'),
style: {
...style,
objectFit: objectFit as any,
},
};
// Use fill layout for responsive images
if (fill) {
return (
<div className={`optimized-image-wrapper ${hasError ? 'has-error' : ''}`}>
<Image
{...imageProps}
fill
sizes={sizes || '100vw'}
priority={priority}
/>
<style jsx>{`
.optimized-image-wrapper {
position: relative;
overflow: hidden;
}
.optimized-image-wrapper.has-error {
background: #f3f4f6;
}
:global(.image-loading) {
filter: blur(10px);
transform: scale(1.1);
transition: filter 0.3s ease, transform 0.3s ease;
}
:global(.image-loaded) {
filter: blur(0);
transform: scale(1);
}
`}</style>
</div>
);
}
// Standard layout with explicit dimensions
return (
<div className={`optimized-image-container ${hasError ? 'has-error' : ''}`}>
<Image
{...imageProps}
width={width}
height={height}
sizes={sizes}
priority={priority}
/>
<style jsx>{`
.optimized-image-container {
position: relative;
display: inline-block;
}
.optimized-image-container.has-error {
background: #f3f4f6;
border-radius: 4px;
}
:global(.image-loading) {
filter: blur(10px);
transform: scale(1.05);
transition: filter 0.4s ease, transform 0.4s ease;
}
:global(.image-loaded) {
filter: blur(0);
transform: scale(1);
}
`}</style>
</div>
);
}
/**
* Usage Examples:
*
* 1. Hero Image (Priority Loading):
* <OptimizedImage
* src="/images/hero.jpg"
* alt="Enterprise software development solutions"
* width={1920}
* height={1080}
* priority={true}
* sizes="100vw"
* />
*
* 2. Service Card Image (Lazy Loading):
* <OptimizedImage
* src="/images/service/custom-software.jpg"
* alt="Custom software development service icon"
* width={400}
* height={300}
* sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
* />
*
* 3. Background Image (Fill):
* <OptimizedImage
* src="/images/background.jpg"
* alt="Technology background pattern"
* fill={true}
* sizes="100vw"
* objectFit="cover"
* />
*
* 4. Logo (High Priority):
* <OptimizedImage
* src="/images/logo.png"
* alt="GNX Soft company logo"
* width={200}
* height={50}
* priority={true}
* quality={100}
* />
*/