diff --git a/solution/frontend/src/features/builder/canvas/variants/itinerary/ItineraryTickets.tsx b/solution/frontend/src/features/builder/canvas/variants/itinerary/ItineraryTickets.tsx index eb6159f..94b03c5 100644 --- a/solution/frontend/src/features/builder/canvas/variants/itinerary/ItineraryTickets.tsx +++ b/solution/frontend/src/features/builder/canvas/variants/itinerary/ItineraryTickets.tsx @@ -18,6 +18,7 @@ import { type PlannedStop, } from '@o2o/shared'; import {useLocalGuide} from '@/hooks/useLocalGuide'; +import {useBuilderStore} from '@/stores/builder'; import {SectionBody, SectionFrame, Rail} from '../../primitives'; import type {SectionRenderProps} from '../../types'; import { @@ -36,6 +37,7 @@ export function ItineraryTickets(props: SectionRenderProps) { const {section, isSelected, onSelect} = props; const parsed = parseSectionData(section.type, section.data); const guide = useLocalGuide(); + const placeName = useBuilderStore((s) => s.storeName); // 사장님이 적은 것이 언제나 이긴다 — 서버가 만든 건 비었을 때의 기본값이다. const items = parsed.items.length > 0 ? parsed.items : guide.itineraries; const live = currentSeasons(); @@ -105,6 +107,13 @@ export function ItineraryTickets(props: SectionRenderProps) { {itineraryDays(item).map((entry, dayIndex) => (
+ {/* ★ 출발지 — 첫날에만. 일정 데이터에는 없다(프롬프트가 정거장으로 + 못 넣게 막는다) — 빌더가 이미 아는 상호명을 그 자리에서 얹는다. */} + {dayIndex === 0 && placeName && ( +

+ {placeName}에서 출발 · {entry.day.from} +

+ )} {entry.label && (

{entry.label} diff --git a/solution/site/src/sections/items/ItinerarySection.tsx b/solution/site/src/sections/items/ItinerarySection.tsx index 09dc593..b675333 100644 --- a/solution/site/src/sections/items/ItinerarySection.tsx +++ b/solution/site/src/sections/items/ItinerarySection.tsx @@ -51,12 +51,15 @@ function DayCard({ startTime, stops, first, + placeName, }: { item: ItineraryItem; badge: string; startTime?: string; stops: PlannerStop[]; first: boolean; + /** 업소 상호명 — 출발지 표시용. 일정 데이터에는 없다(프롬프트가 정거장으로 못 넣게 막는다). */ + placeName: string; }) { const day = planDay({name: item.name, startTime, stops}); @@ -102,6 +105,9 @@ function DayCard({ {/* ★ why·audience 는 첫 장만 — 다 채우면 같은 문구가 이틀·사흘 반복된다. */} {first && item.audience &&

{item.audience}

} {first && item.why &&

{item.why}

} + {/* ★ 출발지 — 첫 장만(위 audience·why 와 같은 규칙). day.from 은 planDay 가 계산한 + 출발 시각(item.startTime)이라 시간표의 첫 줄과 정확히 이어진다. */} + {first &&

{placeName}에서 출발 · {day.from}

}
planned.stop)} /> @@ -231,6 +237,7 @@ export function ItinerarySection() { key={active} tab={tab} items={items.filter((item) => (item.duration?.trim() || NO_DURATION) === tab)} + placeName={payload.place.name} /> ))} @@ -254,7 +261,15 @@ export function ItinerarySection() { * ★ `audience`("차 없이 오는 손님")는 카드에만 둔다. 줄에도 적으면 같은 문구가 위아래로 * 두 번 나오고, 코스가 하나일 때는 줄이 아예 없어서 그 문구만 사라진다. */ -function DurationRail({tab, items}: {tab: string; items: ItineraryItem[]}) { +function DurationRail({ + tab, + items, + placeName, +}: { + tab: string; + items: ItineraryItem[]; + placeName: string; +}) { /** 코스별 시작 위치와 길이. 레일 인덱스 ↔ 코스를 잇는 유일한 표다. */ const courses = useMemo(() => { let cursor = 0; @@ -311,6 +326,7 @@ function DurationRail({tab, items}: {tab: string; items: ItineraryItem[]}) { startTime={day.startTime} stops={day.stops} first={dayIndex === 0} + placeName={placeName} /> )), )}