// ===== Page: Beli Tiket (Multi-step flow) ===== function PageTiket() { const [step, setStep] = useState(1); const [date, setDate] = useState(() => { const d = new Date(); d.setDate(d.getDate() + 2); return d.toISOString().split("T")[0]; }); const [qtys, setQtys] = useState({}); const [buyer, setBuyer] = useState({ nama: "", email: "", phone: "" }); const [pay, setPay] = useState("qris"); const [toast, setToast] = useState(null); const [code] = useState(() => "BZ-" + Math.floor(100000 + Math.random() * 900000)); const total = TICKETS.reduce((sum, t) => sum + (qtys[t.nama] || 0) * t.harga, 0); const totalQty = Object.values(qtys).reduce((a, b) => a + (b || 0), 0); const canNext = () => { if (step === 1) return totalQty > 0 && date; if (step === 2) return buyer.nama && buyer.email && buyer.phone; return true; }; return ( <>
1 ? "done" : "")}> {step > 1 ? : "1"} Pilih Tiket
2 ? "done" : "")}> {step > 2 ? : "2"} Data Pengunjung
3 ? "done" : "")}> {step > 3 ? : "3"} Pembayaran
4 Selesai
{step === 1 && } {step === 2 && } {step === 3 && } {step === 4 && }
{toast && setToast(null)} />} ); } function StepPilih({ qtys, setQtys, date, setDate }) { return (

Pilih tanggal & tiket

Tiket berlaku 14 hari ke depan. Anda bisa reschedule H-1.

setDate(e.target.value)} />
{TICKETS.map(t => (
{t.featured && PALING HEMAT}
{t.cat === "weekday" ? "Weekday" : t.cat === "weekend" ? "Weekend" : "Bundle"}

{t.nama}

{t.desc}

    {t.fitur.map((f, i) => (
  • {f}
  • ))}
{rupiah(t.harga)}
{t.asli && (
{rupiah(t.asli)}
)}
per {t.cat === "bundle" ? "paket" : "orang"}
setQtys({ ...qtys, [t.nama]: v })} />
))}
); } function StepData({ buyer, setBuyer }) { return (

Data pengunjung utama

Tiket dan QR code akan dikirim ke email yang Anda isi.

setBuyer({ ...buyer, nama: e.target.value })} />
setBuyer({ ...buyer, email: e.target.value })} />
setBuyer({ ...buyer, phone: e.target.value })} />
Data ini hanya digunakan untuk pengiriman tiket dan konfirmasi kunjungan. Kami tidak membagikan ke pihak ketiga.
); } function StepBayar({ pay, setPay, total }) { const methods = [ { id: "qris", label: "QRIS", desc: "Scan dengan aplikasi e-wallet apa saja", ic: "qrcode" }, { id: "va", label: "Virtual Account", desc: "BCA, BNI, Mandiri, BRI", ic: "building-columns" }, { id: "card", label: "Kartu Kredit/Debit", desc: "Visa, Mastercard, JCB", ic: "credit-card" }, { id: "ewallet", label: "E-Wallet", desc: "GoPay, OVO, DANA, ShopeePay", ic: "wallet" } ]; return (

Metode pembayaran

Pembayaran diproses melalui gateway tersertifikasi PCI-DSS.

{methods.map(m => ( ))}
{pay === "qris" && (
Scan QR untuk membayar {rupiah(total)}
)}
); } function StepSelesai({ code, date, qtys, buyer, total }) { return (

Pesanan berhasil!

Tiket telah dikirim ke {buyer.email}.
Scan QR di bawah ini di gate utama BatamZoo.

KODE PESANAN
{code}
{formatDate(date)} · {Object.values(qtys).reduce((a, b) => a + (b || 0), 0)} tiket · {rupiah(total)}
Kembali ke Beranda
); } function formatDate(iso) { const d = new Date(iso); return d.toLocaleDateString("id-ID", { weekday: "long", day: "numeric", month: "long", year: "numeric" }); } Object.assign(window, { PageTiket });