|
1 | | -import Image from "next/image"; |
| 1 | +import Image from 'next/image'; |
2 | 2 | import Link from 'next/link'; |
3 | 3 | import { useRouter } from 'next/router'; |
4 | 4 |
|
5 | | -const LOCAL_IMAGE_BASE_PATH = "/images/yugiohImages"; |
6 | | -const FALLBACK_IMAGE = "/images/backgrounds/yugioh/background.svg"; |
| 5 | +const LOCAL_IMAGE_BASE_PATH = '/images/yugiohImages'; |
| 6 | +const FALLBACK_IMAGE = '/images/backgrounds/yugioh/background.svg'; |
7 | 7 |
|
8 | | -const buildImagePath = ( cardId ) => `${ LOCAL_IMAGE_BASE_PATH }/${ String( cardId ) }.jpg`; |
| 8 | +const buildImagePath = ( cardId ) => LOCAL_IMAGE_BASE_PATH + '/' + String( cardId ) + '.jpg'; |
| 9 | + |
| 10 | +const getPrimaryCardImage = ( card ) => |
| 11 | + Array.isArray( card?.card_images ) |
| 12 | + ? card.card_images.find( ( image ) => image?.id || image?.image_url || image?.image_url_cropped || image?.image_url_small ) |
| 13 | + : null; |
| 14 | + |
| 15 | +const getCardImageSrc = ( card ) => { |
| 16 | + const primaryCardImage = getPrimaryCardImage( card ); |
| 17 | + const localImageId = |
| 18 | + card?.cardImageId ?? |
| 19 | + card?.cardDetailId ?? |
| 20 | + card?.cardId ?? |
| 21 | + card?.id ?? |
| 22 | + primaryCardImage?.id ?? |
| 23 | + null; |
| 24 | + |
| 25 | + const localImageSrc = localImageId ? buildImagePath( localImageId ) : null; |
| 26 | + const remoteImageSrc = |
| 27 | + card?.remoteImageUrl || |
| 28 | + card?.image_url || |
| 29 | + primaryCardImage?.image_url || |
| 30 | + primaryCardImage?.image_url_cropped || |
| 31 | + primaryCardImage?.image_url_small || |
| 32 | + null; |
| 33 | + |
| 34 | + return localImageSrc || remoteImageSrc || FALLBACK_IMAGE; |
| 35 | +}; |
9 | 36 |
|
10 | 37 | const Card = ( { cardData } ) => { |
11 | 38 | const router = useRouter(); |
12 | 39 | const { letter, setName, rarity } = router.query; |
13 | 40 |
|
14 | | - const cardId = cardData?.id; |
15 | | - const productName = cardData?.productName ?? "Yu-Gi-Oh! Card"; |
16 | | - const imageSrc = cardId ? buildImagePath( cardId ) : FALLBACK_IMAGE; |
| 41 | + const primaryCardImage = getPrimaryCardImage( cardData ); |
| 42 | + const cardIdentity = |
| 43 | + cardData?.cardId ?? |
| 44 | + cardData?.cardImageId ?? |
| 45 | + cardData?.cardDetailId ?? |
| 46 | + cardData?.id ?? |
| 47 | + primaryCardImage?.id ?? |
| 48 | + null; |
| 49 | + const cardName = cardData?.productName ?? cardData?.name ?? 'Yu-Gi-Oh! Card'; |
| 50 | + const setNameValue = cardData?.setName ?? cardData?.set ?? setName ?? ''; |
| 51 | + const setCode = cardData?.number ?? cardData?.set_code ?? ''; |
| 52 | + const edition = cardData?.printing ?? cardData?.edition ?? ''; |
| 53 | + const cardRarity = cardData?.rarity ?? rarity ?? ''; |
| 54 | + const imageSrc = getCardImageSrc( cardData ); |
| 55 | + const detailQuery = { |
| 56 | + letter: letter ?? '', |
| 57 | + source: 'set', |
| 58 | + }; |
| 59 | + |
| 60 | + if ( cardIdentity ) { |
| 61 | + detailQuery.card = String( cardIdentity ); |
| 62 | + } |
| 63 | + |
| 64 | + if ( cardName ) { |
| 65 | + detailQuery.card_name = cardName; |
| 66 | + } |
| 67 | + |
| 68 | + if ( setNameValue ) { |
| 69 | + detailQuery.set_name = setNameValue; |
| 70 | + } |
| 71 | + |
| 72 | + if ( setCode ) { |
| 73 | + detailQuery.set_code = setCode; |
| 74 | + } |
| 75 | + |
| 76 | + if ( cardRarity ) { |
| 77 | + detailQuery.rarity = cardRarity; |
| 78 | + detailQuery.set_rarity = cardRarity; |
| 79 | + } |
| 80 | + |
| 81 | + if ( edition ) { |
| 82 | + detailQuery.edition = edition; |
| 83 | + } |
17 | 84 |
|
18 | 85 | return ( |
19 | 86 | <Link |
20 | | - className="group/card block w-full [perspective:1500px]" |
| 87 | + className='group/card block w-full [perspective:1500px]' |
21 | 88 | href={ { |
22 | | - pathname: "/yugioh/sets/[letter]/cards/card-details", |
23 | | - query: { |
24 | | - card: cardId, |
25 | | - letter: letter ?? "", |
26 | | - set_name: setName ?? "", |
27 | | - set_rarity: rarity ?? "", |
28 | | - source: "set", |
29 | | - }, |
| 89 | + pathname: '/yugioh/sets/[letter]/cards/card-details', |
| 90 | + query: detailQuery, |
30 | 91 | } } |
31 | 92 | prefetch={ false } |
32 | | - aria-label={ `View details for ${ productName }` } |
| 93 | + aria-label={ 'View details for ' + cardName } |
33 | 94 | > |
34 | | - <div className="relative mx-auto aspect-[260/360] w-full max-w-[16rem] overflow-hidden rounded-[6px] border border-white/10 bg-black/40 shadow-lg transition duration-300 [transform-style:preserve-3d] [contain:layout_paint_style] group-hover/card:border-indigo-400/60"> |
| 95 | + <div className='relative mx-auto aspect-[260/360] w-full max-w-[16rem] overflow-hidden rounded-[6px] border border-white/10 bg-black/40 shadow-lg transition duration-300 [transform-style:preserve-3d] [contain:layout_paint_style] group-hover/card:border-indigo-400/60'> |
35 | 96 | <Image |
36 | | - as="image" |
37 | | - unoptimized="true" |
38 | | - className="h-full w-full object-cover object-top lg:object-scale-down" |
| 97 | + as='image' |
| 98 | + unoptimized={ true } |
| 99 | + className='h-full w-full object-cover object-top lg:object-scale-down' |
39 | 100 | src={ imageSrc } |
40 | | - alt={ `Card Image - ${ productName }` } |
| 101 | + alt={ 'Card Image - ' + cardName } |
41 | 102 | width={ 1600 } |
42 | 103 | height={ 500 } |
43 | 104 | priority={ true } |
44 | 105 | draggable={ false } |
45 | 106 | /> |
46 | 107 | <div |
47 | | - aria-hidden="true" |
48 | | - className="absolute -inset-px rounded-[6px] bg-[linear-gradient(180deg,rgba(2,6,23,0.42),rgba(2,6,23,0.56)),linear-gradient(40deg,rgba(99,102,241,0.28),rgba(2,6,23,0.18))] opacity-95 transition-opacity duration-300 group-hover/card:opacity-100" |
| 108 | + aria-hidden='true' |
| 109 | + className='absolute -inset-px rounded-[6px] bg-[linear-gradient(180deg,rgba(2,6,23,0.42),rgba(2,6,23,0.56)),linear-gradient(40deg,rgba(99,102,241,0.28),rgba(2,6,23,0.18))] opacity-95 transition-opacity duration-300 group-hover/card:opacity-100' |
49 | 110 | /> |
50 | | - <span className="absolute bottom-4 right-4 z-10 flex min-h-11 min-w-11 items-center justify-center rounded-[4px] border border-white/30 bg-black/75 px-4 py-2 text-center text-sm font-semibold uppercase leading-tight tracking-[0.08em] text-white shadow-lg transition duration-300 group-hover/card:border-indigo-400 group-hover/card:bg-indigo-500/20 group-hover/card:text-indigo-100"> |
| 111 | + <span className='absolute bottom-4 right-4 z-10 flex min-h-11 min-w-11 items-center justify-center rounded-[4px] border border-white/30 bg-black/75 px-4 py-2 text-center text-sm font-semibold uppercase leading-tight tracking-[0.08em] text-white shadow-lg transition duration-300 group-hover/card:border-indigo-400 group-hover/card:bg-indigo-500/20 group-hover/card:text-indigo-100'> |
51 | 112 | Details |
52 | 113 | </span> |
53 | 114 | </div> |
|
0 commit comments