o2o-site-AEO/solution/site/src/layouts/coral/Faq.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

38 lines
1.2 KiB
TypeScript

import {SourceType} from '@o2o/shared';
import {useSite} from '@site/lib/site-context';
import {faqList} from '@site/lib/derive';
const FIRST = 6;
export function Faq() {
const payload = useSite();
const faqs = faqList(payload);
if (faqs.length === 0) return null;
const verified = !faqs.some((faq) => faq.sourceType === SourceType.TEMPLATE);
const item = (faq: (typeof faqs)[number]) => (
<details key={faq.faqId}>
<summary>{faq.question}</summary>
<p>{faq.answer}</p>
</details>
);
return (
<section className="sec" id="faq" aria-labelledby="faq-heading">
<p className="kicker">Q &amp; A</p>
<h2 id="faq-heading">
자주 묻는 질문 <span className="sub">{faqs.length}</span>
</h2>
{verified && <p className="lead small">아래 답변은 모두 사업자가 확인한 내용입니다.</p>}
<div className="faq">
{faqs.slice(0, FIRST).map(item)}
{faqs.length > FIRST && (
<details className="rest">
<summary className="more">{faqs.length - FIRST}개 더 보기</summary>
{faqs.slice(FIRST).map(item)}
</details>
)}
</div>
</section>
);
}