o2o-site-AEO/solution/site/src/layouts/graphic/Booking.tsx
Mina Choi 013cdcfc9f [feat] solution/site,shared: 숙박 템플릿 8종 추가 — 라운드·시네마·빅타이포·부티크·일러스트·코랄·미니멀·솔숲
사장님이 고를 수 있는 숙박 템플릿이 고택 하나뿐이었다. 모두 stay2 콘텐츠(날씨·미니 블로그·
지역 이야기·객실·축제·일정·후기·엽서·노래)를 그대로 싣고 모양만 다르다.

- layouts/<id>/: 템플릿별 Frame·섹션·CSS. 데스크톱은 넓은 배치(1024px 이상), 모바일 우선
- layouts/kit/kit.css: 탭 전환·시트·예약 폼·접기 등 공통 구조
- shared templates.json · builder.ts · catalog.ts: 템플릿·LayoutId 등록
- seo/head.ts: 템플릿별 한글 웹폰트 — 서로 겹치지 않게 배정
- paper Frame·Intro: 같은 탭을 다시 눌러도 맨 위로, 미니 블로그를 글 여러 개로
- docs/TEMPLATES.md · TEMPLATE_DESIGN.md: 목록과 화면 규칙(간격·접기·✓ 표시·글꼴)

eslint·tsc 통과, vitest 123 passed, 템플릿 9개 굽기 성공 · 간격 검사 0건
2026-09-30 13:45:10 +09:00

62 lines
1.9 KiB
TypeScript

import {PlaceCategory} from '@o2o/shared';
import {useSite} from '@site/lib/site-context';
import {bookingActionLabel, bookingLinks, stayBookingView} from '@site/lib/derive';
import {BOOK_EVENT} from '../paper/Rooms';
import {Fire} from './Art';
export function Booking() {
const payload = useSite();
const links = bookingLinks(payload);
const stay = payload.place.category === PlaceCategory.LODGING ? stayBookingView(payload) : null;
const phone = payload.place.phone;
const book = () => window.dispatchEvent(new Event(BOOK_EVENT));
const box = (full: boolean) => (
<div className="book">
<Fire side="left" />
<Fire side="right" delay=".2s" />
<h2 id={full ? 'booking-heading' : 'booking-home-heading'} className="disp">
이용안내 및 예약
</h2>
<p>요금과 예약 방법을 안내합니다.</p>
<div className="btns">
{stay && (
<button type="button" className="btn disp" onClick={book}>
예약하기
</button>
)}
{(full ? links : links.slice(0, 1)).map((link) => (
<a key={link.url} className="btn btn--line" href={link.url} target="_blank" rel="noopener noreferrer">
{bookingActionLabel(link)}
</a>
))}
{full && phone && (
<a className="btn btn--line" href={`tel:${phone}`}>
{phone}
</a>
)}
{!full && (
<a className="btn btn--line" href="#/stay">
이용안내 보기
</a>
)}
</div>
</div>
);
return (
<>
<div data-pg="home">
<section className="sec sec--box" aria-labelledby="booking-home-heading">
{box(false)}
</section>
</div>
<div data-pg="stay">
<section className="sec sec--box" id="booking" aria-labelledby="booking-heading">
{box(true)}
</section>
</div>
</>
);
}