/** * 여행 스케줄 — 발행본. 칸 하나가 시간대 하나다. * ★ 승차권(course)과 축이 다르다 — 저쪽은 '어디를 도는가'(순번), 여기는 '몇 시에 무엇을'(시각). */ import type {ScheduleItem} from '@o2o/shared'; import {useSite} from '@/lib/site-context'; import {sectionItems, sectionName} from '@/lib/derive'; import {ITEM_ACCENT, ITEM_BORDER, ITEM_CARD, ITEM_INK, ITEM_INVERSE, ITEM_INVERSE_INK, ItemSection, Rail, SourceLine} from './common'; /** "09:30" → 9시 30분. 형식이 어긋나면 원문 그대로 — 지어내지 않는다. */ function splitTime(time: string): {head: string; tail?: string} { const match = /^(\d{1,2}):(\d{2})$/.exec(time.trim()); if (!match) return {head: time.trim()}; return {head: match[1].padStart(2, '0'), tail: match[2]}; } export function ScheduleSection() { const payload = useSite(); const parsed = sectionItems(payload, 'schedule'); if (parsed.items.length === 0) return null; return (
{parsed.items.map((schedule, scheduleIndex) => { const slots = schedule.slots ?? []; const span = slots.length > 1 ? `${slots[0]?.time ?? ''}–${slots[slots.length - 1]?.time ?? ''}` : undefined; return (

{schedule.name}

{[schedule.audience, schedule.season, span, `${slots.length}칸`].filter(Boolean).join(' · ')}
{slots.map((slot, index) => { const {head, tail} = splitTime(slot.time ?? ''); return (
{/* 플립보드 — 가운데 접힘선이 이 판을 시계로 만든다 */} {/* 플립보드는 템플릿의 어두운 면이다. 위의 글자는 밝은 면 색을 그대로 쓴다. */}
{head} {tail && :{tail}}

{slot.title}

{slot.place && (

{slot.place}

)} {slot.note &&

{slot.note}

}
{slot.minutes ? `${slot.minutes}분 머묾` : '머무는 시간 미정'} {slot.searchQuery && 지도 검색 · {slot.searchQuery}}
); })}
); })}
); }