"use client"; /** * 컨펌 게이트 카드 — PLAYREEL_JOURNEY.md §2 의 공통 구조. * [eyebrow] n/5 · 이름 [title] [why] [body] [actions] [cost] * 게이트별 본문은 아래 5개 컴포넌트. 편집값은 `edits` 로 부모에게 올려 approve 시 함께 보낸다. */ import { useState } from "react"; import { GATE_META, type AnalysisReview, type ClipReview, type FetchReview, type FinalReview, type GateKey, type GateReview, type NarrationReview, } from "@/lib/playreel"; // ── 공통 셸 ────────────────────────────────────────────────────────── export function GateShell({ gate, children, onApprove, onBack, busy, error, approveLabel }: { gate: GateKey; children: React.ReactNode; onApprove: () => void; onBack?: () => void; busy: boolean; error: string | null; approveLabel?: string; }) { const g = GATE_META[gate]; return (
확인 {g.step} / 5 · {g.name}
{g.why}
{children}다음 단계 · {g.next} · {g.eta} {g.credits > 0 && <> · {g.credits}크레딧>}
{error &&{error}
}{children}
); } const two = { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: "var(--spacing-page-md)", alignItems: "start" } as const; // ── ① 수집 확인 ─────────────────────────────────────────────────────── export function FetchGate({ data, onChange }: { data: FetchReview; onChange: (edits: { sections: string[]; meta: FetchReview["meta"] }) => void }) { const [sections, setSections] = useState(data.sections); const [meta, setMeta] = useState(data.meta); const emit = (s = sections, m = meta) => onChange({ sections: s.filter((x) => x.selected).map((x) => x.id), meta: m }); return (공연 정보
{([["title", "공연명"], ["date_text", "일시"], ["place", "장소"]] as const).map(([k, label]) => (캐스트 · {meta.cast.join(", ")}
영상에 넣을 상세페이지 부분
포스터
{/* eslint-disable-next-line @next/next/no-img-element */}움직일 요소
카메라는 움직이지 않습니다. 빛·안개·천 같은 요소만 살아납니다.
원본 그대로 고정
생성된 화면 위에 원본 픽셀을 다시 덮습니다. 제목은 한 픽셀도 바뀌지 않습니다.
생성 모델
Kling 3.0 pro · 8초 · 14크레딧
{data.ip_risk &&포스터에 QR이 없어 엔딩 밴드 QR은 상품 페이지 링크로 자동 생성합니다.
}요소 분석 (5% 격자)
{/* eslint-disable-next-line @next/next/no-img-element */}나레이션 8문장
{lines.map((l, i) => (목소리
{data.voice.name}
{data.voice.sample_url ? :샘플 준비 중
}예상 길이
{data.est_seconds.toFixed(1)}초
목표 28~31초{!lenOk && " — 문장을 줄이거나 늘려주세요"}
생성 클립 8초
}제목 훼손 검사
{data.gate_passed ? "통과" : "실패"} · 제목대 편차 {data.title_mae.toFixed(2)}
기준 4.0 이하. 원본 제목과 픽셀 단위로 비교한 값입니다.
{data.gate_reason &&{data.gate_reason}
}5시점 프레임
{/* eslint-disable-next-line @next/next/no-img-element */}완성본 {data.duration.toFixed(1)}초
}자동 확인 항목
{data.checks.map((c) => (
proof 시트
{/* eslint-disable-next-line @next/next/no-img-element */}승인하면 v{data.version}으로 고정됩니다.