/** * 계절별 축제. * * ★ 왜 계절로 묶나 — 지역 축제는 날짜보다 '언제쯤'이 먼저다. 손님은 "가을에 뭐 있나"를 묻지 * "10월 3일에 뭐 있나"를 묻지 않는다. 그리고 정적 페이지는 몇 달 산다 — 날짜로 줄 세우면 * 구운 다음 날부터 지난 목록이 된다. * ★ **전 계절을 HTML 에 굽고 화면에서만 접는다.** 접힌 계절이 HTML 에 없으면 검색·AI 가 * 나머지를 못 읽는다(items 규칙과 같다). * ★ 링크는 검색으로 보낸다 — 축제 공식 페이지 주소를 우리가 지어내지 않는다. */ import {useState} from 'react'; import {ArrowUpRight, MapPin} from 'lucide-react'; import {useSite} from '@/lib/site-context'; import {sectionName} from '@/lib/derive'; const SEASONS = ['봄', '여름', '가을', '겨울'] as const; type Season = (typeof SEASONS)[number] | '전체'; /** '3월' → 봄. 월을 못 읽으면 어느 계절로도 넣지 않는다(지어내지 않는다). */ function seasonOf(month?: string): (typeof SEASONS)[number] | null { const n = Number((month ?? '').replace(/[^0-9]/g, '')); if (!Number.isFinite(n) || n < 1 || n > 12) return null; if (n >= 3 && n <= 5) return '봄'; if (n >= 6 && n <= 8) return '여름'; if (n >= 9 && n <= 11) return '가을'; return '겨울'; } export function FestivalSection() { const payload = useSite(); const festivals = payload.local.festivals ?? []; const [active, setActive] = useState('전체'); const region = payload.place.addressLocality ?? payload.place.addressRegion ?? ''; if (festivals.length === 0) return null; const grouped = SEASONS.map((season) => ({ season, items: festivals.filter((f) => seasonOf(f.month) === season), })).filter((group) => group.items.length > 0); const unknown = festivals.filter((f) => seasonOf(f.month) === null); return (