|
1 | | -import type { LucideIcon } from "lucide-react"; |
2 | | -import { |
3 | | - Apple, |
4 | | - Beef, |
5 | | - Carrot, |
6 | | - ChevronRight, |
7 | | - CookingPot, |
8 | | - Drumstick, |
9 | | - Fish, |
10 | | - MapPin, |
11 | | - Navigation, |
12 | | -} from "lucide-react"; |
| 1 | +import { ChevronRight, MapPin, Navigation } from "lucide-react"; |
13 | 2 | import Link from "next/link"; |
14 | 3 |
|
15 | | -import type { Market, MarketSpecialtyIcon } from "@/src/types/market"; |
| 4 | +import { |
| 5 | + DEFAULT_PRODUCT_ICON, |
| 6 | + PRODUCT_ICONS, |
| 7 | +} from "@/src/constants/marketProductIcons"; |
| 8 | +import type { MarketSearchItem } from "@/src/types/market/marketSearch"; |
16 | 9 |
|
17 | 10 | interface MarketItemProps { |
18 | | - market: Market; |
| 11 | + market: MarketSearchItem; |
19 | 12 | } |
20 | 13 |
|
21 | | -const specialtyIcons: Record<MarketSpecialtyIcon, LucideIcon> = { |
22 | | - seafood: Fish, |
23 | | - "fried-chicken": Drumstick, |
24 | | - vegetable: Carrot, |
25 | | - meat: Beef, |
26 | | - fruit: Apple, |
27 | | - food: CookingPot, |
28 | | -}; |
| 14 | +function isToday(date: string) { |
| 15 | + const today = new Date(); |
| 16 | + const year = today.getFullYear(); |
| 17 | + const month = String(today.getMonth() + 1).padStart(2, "0"); |
| 18 | + const day = String(today.getDate()).padStart(2, "0"); |
| 19 | + |
| 20 | + return date === `${year}-${month}-${day}`; |
| 21 | +} |
29 | 22 |
|
30 | 23 | export default function MarketItem({ market }: MarketItemProps) { |
31 | | - const marketDayText = market.marketDays.join(", "); |
| 24 | + const marketDayText = |
| 25 | + market.open_day_numbers.length > 0 |
| 26 | + ? `${market.open_day_numbers.join("·")}일 장` |
| 27 | + : "상설장"; |
| 28 | + const isMarketDayToday = |
| 29 | + market.open_day_numbers.length > 0 && isToday(market.next_open_date); |
32 | 30 |
|
33 | 31 | return ( |
34 | 32 | <li className="min-w-full"> |
35 | 33 | <article className="group overflow-hidden rounded-3xl bg-white"> |
36 | 34 | <div className="bg-light-gray relative aspect-2/1 min-h-40"> |
37 | | - {market.isOpenToday && ( |
| 35 | + {isMarketDayToday && ( |
38 | 36 | <span className="bg-green absolute top-4 left-4 rounded-full px-3 py-1 text-sm font-bold text-white shadow-sm"> |
39 | 37 | 오늘 장날 (Today) |
40 | 38 | </span> |
41 | 39 | )} |
42 | 40 | </div> |
43 | 41 |
|
44 | 42 | <div className="flex flex-col gap-2 p-4"> |
45 | | - <div className="flex items-center justify-between"> |
46 | | - <h3 className="text-green text-lg font-bold">{market.name}</h3> |
| 43 | + <div className="flex items-start justify-between gap-3"> |
| 44 | + <h3 className="text-green line-clamp-2 min-w-0 flex-1 text-lg font-bold"> |
| 45 | + {market.name} |
| 46 | + </h3> |
47 | 47 |
|
48 | | - <span className="border-light-brown/20 bg-light-brown/10 text-light-brown rounded-full border px-2 py-0.5 text-xs font-bold"> |
49 | | - {marketDayText}일 주기 |
| 48 | + <span className="border-light-brown/20 bg-light-brown/10 text-light-brown shrink-0 rounded-full border px-2 py-0.5 text-xs font-bold"> |
| 49 | + {marketDayText} |
50 | 50 | </span> |
51 | 51 | </div> |
52 | 52 |
|
53 | | - <div className="flex items-center gap-1"> |
| 53 | + <div className="flex items-start gap-1"> |
54 | 54 | <MapPin className="h-4 w-4" strokeWidth={2} aria-hidden="true" /> |
55 | 55 |
|
56 | | - <p className="text-xs font-semibold">{market.address}</p> |
| 56 | + <p className="text-xs font-semibold"> |
| 57 | + {market.road_address?.trim() || "주소 정보 알 수 없음"} |
| 58 | + </p> |
57 | 59 | </div> |
58 | 60 |
|
59 | 61 | <ul |
60 | 62 | className="mt-2 flex flex-wrap items-center gap-2" |
61 | 63 | aria-label={`${market.name} 대표 상품`} |
62 | 64 | > |
63 | | - {market.specialties.map((specialty) => { |
64 | | - const SpecialtyIcon = specialtyIcons[specialty.icon]; |
| 65 | + {market.products.map((product) => { |
| 66 | + const ProductIcon = |
| 67 | + PRODUCT_ICONS[product] ?? DEFAULT_PRODUCT_ICON; |
65 | 68 |
|
66 | 69 | return ( |
67 | 70 | <li |
68 | | - key={`${market.id}-${specialty.label}`} |
| 71 | + key={`${market.market_id}-${product}`} |
69 | 72 | className="flex items-center gap-1 text-xs font-semibold" |
70 | 73 | > |
71 | | - <SpecialtyIcon |
| 74 | + <ProductIcon |
72 | 75 | className="text-green h-4 w-4" |
73 | 76 | strokeWidth={2} |
74 | 77 | aria-hidden="true" |
75 | 78 | /> |
76 | 79 |
|
77 | | - <span>{specialty.label}</span> |
| 80 | + <span>{product}</span> |
78 | 81 | </li> |
79 | 82 | ); |
80 | 83 | })} |
81 | 84 | </ul> |
82 | 85 |
|
83 | 86 | <div className="border-deep-gray text-green mt-2 border-t py-3 font-bold"> |
84 | 87 | <Link |
85 | | - href={`/markets/${market.id}`} |
| 88 | + href={`/markets/${market.market_id}`} |
86 | 89 | className="flex items-center justify-between text-xs" |
87 | 90 | aria-label={`${market.name} 상세보기`} |
88 | 91 | > |
89 | 92 | <span className="flex items-center gap-1"> |
90 | | - <Navigation |
91 | | - className="h-4 w-4" |
92 | | - strokeWidth={2} |
93 | | - aria-hidden="true" |
94 | | - /> |
95 | | - {market.distanceKm.toFixed(1)}km 인근 |
| 93 | + {market.distance_km !== null && ( |
| 94 | + <> |
| 95 | + <Navigation |
| 96 | + className="h-4 w-4" |
| 97 | + strokeWidth={2} |
| 98 | + aria-hidden="true" |
| 99 | + /> |
| 100 | + {market.distance_km.toFixed(1)}km 인근 |
| 101 | + </> |
| 102 | + )} |
96 | 103 | </span> |
97 | 104 |
|
98 | 105 | <span className="flex items-center"> |
|
0 commit comments