11'use client'
22
3- import { useState , useEffect , useRef } from 'react'
3+ import { useState } from 'react'
44import Image from 'next/image'
5- import { getHeadshotPath , didHeadshotFail , getFallbackHeadshot } from '@/utils/dataLoader'
5+ import { getHeadshotPath } from '@/utils/dataLoader'
66import { IconDevProfile } from '@/components/Icons'
77
88interface PlayerHeadshotProps {
@@ -22,77 +22,32 @@ export default function PlayerHeadshot({
2222} : PlayerHeadshotProps ) {
2323 const [ hasError , setHasError ] = useState ( false )
2424 const [ isLoaded , setIsLoaded ] = useState ( false )
25- const [ isInView , setIsInView ] = useState ( priority )
26- const imgRef = useRef < HTMLDivElement > ( null )
2725
2826 const headshotPath = getHeadshotPath ( playerName , position )
2927
30- // Check if already known to have failed
31- useEffect ( ( ) => {
32- if ( didHeadshotFail ( headshotPath ) ) {
33- setHasError ( true )
34- }
35- } , [ headshotPath ] )
36-
37- // Intersection observer for lazy loading
38- useEffect ( ( ) => {
39- if ( priority || isInView ) return
40-
41- const observer = new IntersectionObserver (
42- ( entries ) => {
43- if ( entries [ 0 ] . isIntersecting ) {
44- setIsInView ( true )
45- observer . disconnect ( )
46- }
47- } ,
48- {
49- rootMargin : '100px' , // Start loading 100px before in view
50- }
51- )
52-
53- if ( imgRef . current ) {
54- observer . observe ( imgRef . current )
55- }
56-
57- return ( ) => observer . disconnect ( )
58- } , [ priority , isInView ] )
59-
60- const handleError = ( ) => {
61- setHasError ( true )
62- }
63-
64- const handleLoad = ( ) => {
65- setIsLoaded ( true )
66- }
67-
6828 return (
6929 < div
70- ref = { imgRef }
7130 className = { `relative overflow-hidden rounded-full bg-[var(--bg-secondary)] ${ className } ` }
7231 style = { { width : size , height : size } }
7332 >
74- { /* Skeleton loading state */ }
7533 { ! isLoaded && ! hasError && (
7634 < div className = "absolute inset-0 skeleton" />
7735 ) }
7836
79- { /* Actual image - only render when in view */ }
80- { isInView && ! hasError && (
37+ { ! hasError && (
8138 < Image
8239 src = { headshotPath }
8340 alt = { `${ playerName } headshot` }
8441 width = { size }
8542 height = { size }
86- className = { `object-cover transition-opacity duration-300 ${ isLoaded ? 'opacity-100' : 'opacity-0'
87- } `}
88- onError = { handleError }
89- onLoad = { handleLoad }
43+ className = { `object-cover transition-opacity duration-300 ${ isLoaded ? 'opacity-100' : 'opacity-0' } ` }
44+ onError = { ( ) => setHasError ( true ) }
45+ onLoad = { ( ) => setIsLoaded ( true ) }
9046 loading = { priority ? 'eager' : 'lazy' }
9147 unoptimized
9248 />
9349 ) }
9450
95- { /* Fallback icon on error */ }
9651 { hasError && (
9752 < div className = "absolute inset-0 flex items-center justify-center bg-[var(--bg-secondary)] text-[var(--text-muted)]" >
9853 < IconDevProfile size = { size * 0.6 } />
0 commit comments