1- import { useEffect , useState } from 'react' ;
1+ import { useEffect , useMemo , useState } from 'react' ;
22import Link from 'next/link' ;
33import { useRouter } from 'next/router' ;
44
5- const Breadcrumb = ( ) => {
5+ const Breadcrumb = ( { items = null } ) => {
66 const router = useRouter ( ) ;
77 const { pathname, query, isReady } = router ;
88 const [ hasMounted , setHasMounted ] = useState ( false ) ;
99 const [ cardName , setCardName ] = useState ( null ) ;
10+ const hasCustomItems = Array . isArray ( items ) && items . length > 0 ;
1011
1112 // Ensure client-only rendering
1213 useEffect ( ( ) => {
@@ -15,6 +16,10 @@ const Breadcrumb = () => {
1516
1617 // Fetch the card's human-readable name if we're on a details page
1718 useEffect ( ( ) => {
19+ if ( hasCustomItems ) {
20+ return undefined ;
21+ }
22+
1823 if ( query . card ) {
1924 fetch ( `/api/Yugioh/card/${ encodeURIComponent ( query . card ) } ` )
2025 . then ( ( res ) => res . json ( ) )
@@ -23,78 +28,96 @@ const Breadcrumb = () => {
2328 } )
2429 . catch ( ( err ) => console . error ( 'Breadcrumb: failed to fetch card name' , err ) ) ;
2530 }
26- } , [ query . card ] ) ;
31+ return undefined ;
32+ } , [ hasCustomItems , query . card ] ) ;
2733
2834 // Fall back to the card name passed in the query if no id lookup is available
2935 useEffect ( ( ) => {
36+ if ( hasCustomItems ) {
37+ return ;
38+ }
39+
3040 if ( ! query . card && query . card_name ) {
3141 const nameValue = Array . isArray ( query . card_name ) ? query . card_name [ 0 ] : query . card_name ;
3242 setCardName ( nameValue || null ) ;
3343 }
34- } , [ query . card , query . card_name ] ) ;
35-
36- if ( ! isReady || ! hasMounted ) return null ;
37-
38- const crumbs = [ ] ;
39-
40- // 1. Home
41- crumbs . push ( { label : 'Home' , href : '/yugioh' } ) ;
44+ } , [ hasCustomItems , query . card , query . card_name ] ) ;
45+
46+ const crumbs = useMemo ( ( ) => {
47+ if ( hasCustomItems ) {
48+ return items
49+ . filter ( Boolean )
50+ . map ( ( item ) => ( {
51+ label : item ?. label ?? '' ,
52+ href : item ?. href ?? null ,
53+ } ) )
54+ . filter ( ( item ) => item . label ) ;
55+ }
4256
43- // 2. Set Index
44- crumbs . push ( { label : 'Set Index' , href : '/yugioh/sets/set-index' } ) ;
57+ const autoCrumbs = [ ] ;
4558
46- // 3. Sets Starting With: [LETTER]
47- if ( query . letter && pathname . includes ( '/yugioh/sets' ) ) {
48- crumbs . push ( {
49- label : `Sets Starting With: ${ String ( query . letter ) . toUpperCase ( ) } ` ,
50- href : `/yugioh/sets/${ encodeURIComponent ( query . letter ) } ` ,
51- } ) ;
52- }
59+ // 1. Home
60+ autoCrumbs . push ( { label : 'Home' , href : '/yugioh' } ) ;
5361
54- // 4. Cards In Set: [SET NAME]
62+ // 2. Set Index
63+ autoCrumbs . push ( { label : 'Set Index' , href : '/yugioh/sets/set-index' } ) ;
5564
56- // 5. Context-specific parent
57- if ( pathname . includes ( '/card-details' ) ) {
58- if ( query . source === 'set' ) {
59- crumbs . push ( {
60- label : `Cards In Set: ${ query . set_name } ` ,
61- href : `/yugioh/sets/${ encodeURIComponent ( query . letter ) } /${ encodeURIComponent ( query . set_name ) } `
62- } ) ;
63- } else if ( query . source === 'collection' ) {
64- crumbs . push ( {
65- label : `Cards In Set: ${ query . set_name } ` ,
66- href : `/yugioh/sets/${ encodeURIComponent ( query . letter ) } /${ encodeURIComponent ( query . set_name ) } `
67- } ) ;
68- crumbs . push ( {
69- label : 'My Collection' ,
70- href : '/yugioh/my-collection'
65+ // 3. Sets Starting With: [LETTER]
66+ if ( query . letter && pathname . includes ( '/yugioh/sets' ) ) {
67+ autoCrumbs . push ( {
68+ label : `Sets Starting With: ${ String ( query . letter ) . toUpperCase ( ) } ` ,
69+ href : `/yugioh/sets/${ encodeURIComponent ( query . letter ) } ` ,
7170 } ) ;
7271 }
7372
74- // 6. Card Details
75- const fallbackCardName =
76- cardName ||
77- ( Array . isArray ( query . card_name ) ? query . card_name [ 0 ] : query . card_name ) ||
78- ( Array . isArray ( query . card ) ? query . card [ 0 ] : query . card ) ;
73+ // 4. Cards In Set: [SET NAME]
74+
75+ // 5. Context-specific parent
76+ if ( pathname . includes ( '/card-details' ) ) {
77+ if ( query . source === 'set' ) {
78+ autoCrumbs . push ( {
79+ label : `Cards In Set: ${ query . set_name } ` ,
80+ href : `/yugioh/sets/${ encodeURIComponent ( query . letter ) } /${ encodeURIComponent ( query . set_name ) } ` ,
81+ } ) ;
82+ } else if ( query . source === 'collection' ) {
83+ autoCrumbs . push ( {
84+ label : `Cards In Set: ${ query . set_name } ` ,
85+ href : `/yugioh/sets/${ encodeURIComponent ( query . letter ) } /${ encodeURIComponent ( query . set_name ) } ` ,
86+ } ) ;
87+ autoCrumbs . push ( {
88+ label : 'My Collection' ,
89+ href : '/yugioh/my-collection' ,
90+ } ) ;
91+ }
92+
93+ // 6. Card Details
94+ const fallbackCardName =
95+ cardName ||
96+ ( Array . isArray ( query . card_name ) ? query . card_name [ 0 ] : query . card_name ) ||
97+ ( Array . isArray ( query . card ) ? query . card [ 0 ] : query . card ) ;
98+
99+ autoCrumbs . push ( {
100+ label : `Card Details: ${ fallbackCardName || 'Unknown Card' } ` ,
101+ href : null ,
102+ } ) ;
103+ }
79104
80- crumbs . push ( {
81- label : `Card Details: ${ fallbackCardName || 'Unknown Card' } ` ,
82- href : null
83- } ) ;
84- }
105+ return autoCrumbs ;
106+ } , [ cardName , hasCustomItems , items , pathname , query . card , query . card_name , query . letter , query . set_name , query . source ] ) ;
85107
108+ if ( ! isReady || ! hasMounted ) return null ;
86109
87110 return (
88111 < nav
89- className = "flex flex-wrap whitespace-break-spaces bg-transparent backdrop glass text-shadow rounded-sm w-full "
112+ className = "mx-auto w-full max-w-7xl px-4 pt-4 sm:px-6 lg:px-8 "
90113 aria-label = "Breadcrumb"
91114 >
92- < ol className = "mx-auto sm:mx-0 sm:float-start flex flex-wrap w-fit space-x-4 px-4 sm:px-6 lg:px-8 " >
115+ < ol className = "flex flex-wrap items-center gap-2 rounded-2xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white/80 shadow-2xl backdrop-blur " >
93116 { crumbs . map ( ( crumb , idx ) => (
94- < li key = { idx } className = "flex flex-wrap items-center" >
117+ < li key = { ` ${ crumb . label } - ${ idx } ` } className = "flex min-w-0 items-center gap-2 " >
95118 { idx > 0 && (
96119 < svg
97- className = "h-5 w-5 flex-shrink-0 text-white text-shadow backdrop "
120+ className = "h-4 w-4 flex-shrink-0 text-white/40 "
98121 viewBox = "0 0 24 44"
99122 fill = "currentColor"
100123 aria-hidden = "true"
@@ -103,13 +126,13 @@ const Breadcrumb = () => {
103126 </ svg >
104127 ) }
105128 { crumb . href ? (
106- < span className = "ml-4 p-2 text-sm font-black text-white text-shadow hover:text-gray-300 " >
107- < Link href = { crumb . href } passHref >
129+ < span className = "min-w-0 text-sm font-semibold text-white transition hover:text-indigo-200 " >
130+ < Link href = { crumb . href } >
108131 { crumb . label }
109132 </ Link >
110133 </ span >
111134 ) : (
112- < span className = "ml-4 p-2 text-sm font-black text-white text-shadow " >
135+ < span className = "min-w-0 text-sm font-semibold text-white" >
113136 { crumb . label }
114137 </ span >
115138 ) }
0 commit comments