1"use client"
2
3import { useRouter } from "next/navigation"
4import { Check } from "@phosphor-icons/react"
5
6import { BoothPanel } from "@/features/booth/BoothPanel"
7import { Button } from "@/components/ui/button"
8import { LAYOUTS, type LayoutId } from "@/lib/layouts"
9import { cn } from "@/lib/utils"
10import { useBoothStore } from "@/stores/booth"
11
12/* FR-02: pilih layout menentukan jumlah foto dan rasio crop di langkah kamera. */
13const DESCRIPTIONS: Record<LayoutId, string> = {
14 "strip-4": "Empat pose, strip klasik 2 x 6 inci.",
15 "strip-3": "Tiga pose, slot lebih tinggi untuk badan penuh.",
16 "grid-2x2": "Empat pose, lembar 4R penuh.",
17}
18
19const CHOICES: LayoutId[] = ["strip-4", "strip-3", "grid-2x2"]
20
21export default function LayoutStepPage() {
22 const router = useRouter()
23 const layoutId = useBoothStore((state) => state.layoutId)
24 const setLayout = useBoothStore((state) => state.setLayout)
25
26 return (
27 <BoothPanel
28 title="Pilih Layout"
29 backHref="/"
30 center={
31 <fieldset className="flex flex-col gap-4">
32 <legend className="sr-only">Pilih layout</legend>
33 <div className="flex flex-wrap gap-4">
34 {CHOICES.map((id) => {
35 const layout = LAYOUTS[id]
36 const selected = layoutId === id
37
38 return (
39 <label
40 key={id}
41 className={cn(
42 "relative flex flex-1 cursor-pointer flex-col gap-3 rounded-card border-2 border-ink bg-paper p-4",
43 "basis-[min(100%,260px)] focus-within:outline-3 focus-within:outline-offset-3 focus-within:outline-violet",
44 selected && "ring-selected"
45 )}
46 >
47 <input
48 type="radio"
49 name="layout"
50 value={id}
51 checked={selected}
52 onChange={() => setLayout(id)}
53 aria-labelledby={`layout-${id}-nama`}
54 aria-describedby={`layout-${id}-catatan`}
55 className="absolute inset-0 size-full cursor-pointer opacity-0"
56 />
57
58 <div
59 className={cn(
60 "grid gap-1.5 self-start rounded-thumb border-2 border-ink bg-cream p-2",
61 layout.columns === 2 ? "grid-cols-2" : "grid-cols-1"
62 )}
63 >
64 {layout.slotRects.map((rect, index) => (
65 <div
66 key={index}
67 className="w-14 rounded-sm border-2 border-ink bg-violet-soft"
68 style={{ aspectRatio: `${rect.width} / ${rect.height}` }}
69 />
70 ))}
71 </div>
72
73 <span id={`layout-${id}-nama`} className="title text-ink">
74 {layout.label}
75 </span>
76 <span
77 id={`layout-${id}-catatan`}
78 className="text-[15px] leading-[1.4] text-muted"
79 >
80 {DESCRIPTIONS[id]}
81 </span>
82 <span className="font-mono text-xs font-bold tracking-[0.06em] text-muted uppercase">
83 {`Ekspor ${layout.canvas.width} x ${layout.canvas.height} px`}
84 </span>
85
86 {selected ? (
87 <span className="absolute top-3 right-3 flex size-6 items-center justify-center rounded-full border-2 border-ink bg-violet text-paper">
88 <Check weight="bold" className="size-3.5" aria-hidden />
89 </span>
90 ) : null}
91 </label>
92 )
93 })}
94 </div>
95 </fieldset>
96 }
97 right={
98 <>
99 <div className="flex flex-col gap-2 rounded-panel border-3 border-ink bg-cream p-5">
100 <span className="font-mono text-xs font-bold tracking-[0.06em] uppercase">
101 Layout dipilih
102 </span>
103 <span className="title text-ink">
104 {layoutId ? LAYOUTS[layoutId].label : "Belum dipilih"}
105 </span>
106 {layoutId ? (
107 <span className="text-[15px] leading-[1.4] text-muted">
108 {`${LAYOUTS[layoutId].shotCount} foto, ekspor ${LAYOUTS[layoutId].canvas.width} x ${LAYOUTS[layoutId].canvas.height} px.`}
109 </span>
110 ) : (
111 <span className="text-[15px] leading-[1.4] text-muted">
112 Pilih layout dulu.
113 </span>
114 )}
115 </div>
116 <Button
117 size="lg"
118 disabled={layoutId === null}
119 className="w-full"
120 onClick={() => router.push("/booth/capture")}
121 >
122 Mulai Foto
123 </Button>
124 </>
125 }
126 />
127 )
128}
129