'use client';
import React, { useState, useEffect } from 'react';
import { BookOpen, Menu, X, Heart, ShieldCheck, Landmark, MapPin, Phone, ExternalLink, Download, Copy, Check, CalendarDays, Trees, Building2, Shield, Grid2X2, Droplets, FileText, Clock3, LockKeyhole, Wallet, Image as ImageIcon, AlertCircle, Loader2, ChevronDown, CheckCircle2, Banknote, Eye } from 'lucide-react';
import Admin from './admin';
export const rupiah = (n: number = 0) => new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', maximumFractionDigits: 0 }).format(n).replace(/\u00a0/g, ' ');
export const tanggal = (s?: string) => s ? new Intl.DateTimeFormat('id-ID', { dateStyle: 'long', timeZone: 'Asia/Jakarta' }).format(new Date(s.length === 10 ? s + 'T12:00:00+07:00' : s)) : 'Belum tersedia';
export const statusLabel: Record<string, string> = { waiting_payment: 'Menunggu pembayaran', waiting_verification: 'Menunggu verifikasi', verified: 'Terverifikasi', rejected: 'Ditolak', expired: 'Kedaluwarsa', refunded: 'Dikembalikan' };
export async function api(path: string, body?: any): Promise<any> { const res = await fetch('/api/' + path, { method: body !== undefined ? 'POST' : 'GET', headers: body !== undefined ? { 'Content-Type': 'application/json', 'x-alhabibah': '1' } : undefined, body: body !== undefined ? JSON.stringify(body) : undefined }); const value: any = await res.json(); if (!res.ok)
    throw new Error(value.error || 'Layanan belum dapat diakses. Silakan coba lagi.'); return value; }
export const mediaSrc = (id: string) => '/api/media/' + id;
const icons: Record<string, React.ComponentType<any>> = { land: Trees, building: Building2, shield: Shield, field: Grid2X2, water: Droplets };
export function Notice({ children, kind = 'info' }: {
    children: React.ReactNode;
    kind?: string;
}) { return <div className={'notice ' + kind} role={kind === 'error' ? 'alert' : 'status'}><AlertCircle size={19}/><div>{children}</div></div>; }
export function Empty({ title, children, icon: Icon = FileText }: {
    title: string;
    children?: React.ReactNode;
    icon?: any;
}) { return <div className="empty"><div className="empty-icon"><Icon size={28}/></div><h3>{title}</h3><p>{children}</p></div>; }
function ProgressBar({ value, target }: {
    value: number;
    target: number;
}) { const percent = target ? value / target * 100 : 0; return <div className="progress-track" role="progressbar" aria-valuenow={Math.min(100, Math.round(percent))} aria-valuemin={0} aria-valuemax={100} aria-label="Pencapaian dana"><div style={{ width: Math.min(100, Math.max(0, percent)) + '%' }}/></div>; }
function Logo({ site }: {
    site: any;
}) { return <a className="brand" href="/" aria-label="Beranda Donasi Al-Habibah">{site.logoMedia ? <img src={mediaSrc(site.logoMedia)} alt="Logo Al-Habibah"/> : <span className="brand-mark"><BookOpen size={25} strokeWidth={1.5}/></span>}<span><strong>{site.name}</strong><small>{site.foundation}</small></span></a>; }
function Header({ site, path }: {
    site: any;
    path: string;
}) { const [open, setOpen] = useState(false); const links = [['Beranda', '/'], ['Program', '/program'], ['Progres Pembangunan', '/progres'], ['Laporan', '/laporan'], ['Tentang', '/tentang']]; return <header className="site-header"><div className="wrap header-inner"><Logo site={site}/><nav className={open ? 'nav-links open' : 'nav-links'} aria-label="Navigasi utama">{links.map(([label, href]) => <a key={href} className={(path === href || href !== '/' && path.startsWith(href)) ? 'active' : ''} href={href}>{label}</a>)}<a className="btn small nav-donate" href="/donasi"><Heart size={16}/>Donasi Sekarang</a></nav><button className="menu-button" aria-label={open ? 'Tutup navigasi' : 'Buka navigasi'} aria-expanded={open} onClick={() => setOpen(!open)}>{open ? <X /> : <Menu />}</button></div></header>; }
function Footer({ site }: {
    site: any;
}) { return <footer><div className="wrap"><div className="footer-grid"><div><Logo site={site}/><p>{site.footer}</p><p className="muted">{site.pesantrenName}<br />{site.schoolName}</p></div><div><h4>Jelajahi</h4><a href="/program">Program pembangunan</a><a href="/progres">Progres pembangunan</a><a href="/laporan">Laporan penggunaan dana</a><a href="/tentang">Tentang Al-Habibah</a></div><div><h4>Hubungi pengelola</h4><p className="icon-line"><MapPin size={18}/>{site.address}</p><a className="icon-line" href={`https://wa.me/${site.whatsapp}`} target="_blank" rel="noreferrer"><Phone size={17}/>WhatsApp pengelola</a><a className="icon-line" href={site.website} target="_blank" rel="noreferrer"><ExternalLink size={17}/>Website sekolah</a></div></div><div className="footer-bottom"><span>© {new Date().getFullYear()} {site.foundation}</span><div><a href="/privasi">Kebijakan privasi</a><a href="/ketentuan">Ketentuan donasi</a><a href="/admin">Admin</a></div></div></div></footer>; }
function ProgramCard({ p, data, index }: {
    p: any;
    data: any;
    index: number;
}) { const Icon = icons[p.icon] || Building2; const m = data.media.find((m: any) => m.id === p.cover); return <article className="program-card"><a href={'/program/' + p.slug} className={'program-image tone-' + index} aria-label={p.title}>{p.cover ? <img src={mediaSrc(p.cover)} alt={m?.alt || p.title} loading="lazy" decoding="async"/> : <><Icon size={40} strokeWidth={1.1}/><span>Dokumentasi belum tersedia</span></>}<span className="program-number">0{index + 1}</span></a><div className="program-content"><span className="eyebrow">{p.subtitle}</span><h3><a href={'/program/' + p.slug}>{p.title}</a></h3><p>{p.benefit}</p><div className="fund-row"><strong>{rupiah(p.receipts)}</strong><span>terverifikasi</span></div><ProgressBar value={p.receipts} target={p.target}/><div className="fund-goal"><span>Target {rupiah(p.target)}</span><span>{Math.round(p.receipts / p.target * 100)}%</span></div><a className="btn outline full" href={p.open && p.state !== 'archived' ? '/donasi?program=' + p.id : '/program/' + p.slug}>{p.open && p.state !== 'archived' ? 'Dukung program ini' : 'Lihat program'}</a></div></article>; }
function SectionTitle({ eyebrow, title, description, href, label }: {
    eyebrow: string;
    title: string;
    description?: string;
    href?: string;
    label?: string;
}) { return <div className="section-title"><div><span className="eyebrow">{eyebrow}</span><h2>{title}</h2>{description && <p>{description}</p>}</div>{href && <a className="text-link" href={href}>{label}<ExternalLink size={16}/></a>}</div>; }
function Faq({ data }: {
    data: any;
}) { return <section className="section wrap" id="faq"><div className="faq-grid"><div><span className="eyebrow">Kami siap membantu</span><h2>{data.site.faqTitle}</h2><p>Informasi untuk membuat Anda lebih yakin saat berdonasi.</p><a className="text-link" href={`https://wa.me/${data.site.whatsapp}`} target="_blank" rel="noreferrer"><Phone size={16}/>Hubungi pengelola</a></div><div className="faq-list">{data.faqs.map((f: any) => <details key={f.id}><summary>{f.question}<ChevronDown size={18}/></summary><p>{f.answer}</p></details>)}</div></div></section>; }
function ProgressList({ data, limit }: {
    data: any;
    limit?: number;
}) { const list = limit ? data.progress.slice(0, limit) : data.progress; return list.length ? <div className="timeline">{list.map((p: any) => <article className="timeline-item" key={p.id}><div className="timeline-date"><CalendarDays size={19}/><strong>{tanggal(p.activityDate)}</strong><small>Tanggal kegiatan</small></div><div className="timeline-content"><span className="eyebrow">{data.programs.find((x: any) => x.id === p.programId)?.title || 'Pembangunan Al-Habibah'}</span><h3>{p.title}</h3><p className="preline">{p.description}</p>{p.physicalPercent !== null && p.physicalPercent !== undefined && <div className="physical"><strong>Progres fisik: {p.physicalPercent}%</strong><p>Dasar penilaian: {p.physicalBasis}</p><small>Angka ini menunjukkan pekerjaan fisik, terpisah dari pencapaian dana.</small></div>}<Gallery ids={p.media || []} data={data}/>{(p.before || p.after) && <div className="before-after">{[['Sebelum', p.before], ['Sesudah', p.after]].filter(x => x[1]).map(([l, id]) => <figure key={l}><img src={mediaSrc(id)} alt={`${l}: ${p.title}`} loading="lazy" decoding="async"/><figcaption>{l}</figcaption></figure>)}</div>}<small className="muted">Dipublikasikan {tanggal(p.publishedAt)}</small></div></article>)}</div> : <Empty title="Pembaruan pembangunan belum diterbitkan" icon={CalendarDays}>Pengelola akan membagikan tanggal kegiatan, dokumentasi asli, dan uraian pekerjaan di sini.</Empty>; }
function Gallery({ ids, data }: {
    ids: string[];
    data: any;
}) { const [view, setView] = useState<any>(null); return <>{ids.length > 0 && <div className="gallery-grid">{ids.map(id => { const m = data.media.find((x: any) => x.id === id); if (!m)
    return null; return <figure key={id}>{m.mime === 'video/mp4' ? <video controls src={mediaSrc(id)} preload="metadata" aria-label={m.alt || m.caption}/> : m.mime.startsWith('image/') ? <button onClick={() => setView(m)} aria-label={'Perbesar ' + (m.alt || m.name)}><img src={mediaSrc(id)} alt={m.alt || m.caption || m.name} loading="lazy" decoding="async"/></button> : <a href={mediaSrc(id)} target="_blank" rel="noreferrer"><FileText /> Baca dokumen</a>}{m.caption && <figcaption>{m.caption}</figcaption>}</figure>; })}</div>}{view && <div className="modal-backdrop" onClick={() => setView(null)}><div className="image-view" role="dialog" aria-modal="true" aria-label="Dokumentasi pembangunan"><button className="icon-button" onClick={() => setView(null)} aria-label="Tutup foto"><X /></button><img src={mediaSrc(view.id)} alt={view.alt || view.caption}/><p>{view.caption}</p></div></div>}</>; }
function FinanceSummary({ data }: {
    data: any;
}) { const f = data.finance; return <div className="finance-cards">{[['Penerimaan bruto', f.receipts, Landmark], ['Pengeluaran', f.expenses, Wallet], ['Biaya & pengembalian', f.fees + f.refunds, Banknote], ['Saldo dana', f.balance, ShieldCheck]].map(([l, v, Icon]: any) => <div key={l}><Icon size={23}/><span>{l}</span><strong>{rupiah(v)}</strong></div>)}</div>; }
function Home({ data }: {
    data: any;
}) { const s = data.site; const sections: Record<string, React.ReactNode> = { stats: <div className="wrap stats-section"><div><span>Total target pembangunan</span><strong>{rupiah(data.target)}</strong><small>{data.programs.filter((p:any)=>p.main).length} kebutuhan dalam rencana anggaran</small></div><div><span>Penerimaan terverifikasi</span><strong>{rupiah(data.finance.receipts)}</strong><small>Penerimaan bruto, setelah verifikasi bank</small></div><div><span>Donasi terverifikasi</span><strong>{data.finance.count}<em>donasi</em></strong><small>{data.finance.count ? 'Terima kasih atas kepercayaan Anda' : 'Belum ada donasi terverifikasi'}</small></div></div>, story: <section className="section wrap"><div className="story-grid"><div><span className="eyebrow">Pendidikan yang kita perjuangkan</span><h2>{s.storyTitle}</h2></div><div><p className="lead">{s.story}</p><p>{s.pesantrenName} dan {s.schoolName} berada di bawah pengelolaan {s.foundation}.</p><a className="text-link" href="/tentang">Kenali Al-Habibah<ExternalLink size={16}/></a></div></div></section>, programs: <section className="section soft"><div className="wrap"><SectionTitle eyebrow="Pilih kebaikan yang ingin Anda dukung" title={s.programsTitle} description="Bersama menyediakan fasilitas pendidikan yang layak." href="/program" label="Lihat semua program"/><div className="program-grid">{data.programs.filter((p: any) => p.state !== 'archived').map((p: any, i: number) => <ProgramCard key={p.id} p={p} data={data} index={i}/>)}</div></div></section>, progress: <section className="section wrap"><SectionTitle eyebrow="Langkah demi langkah" title={s.progressTitle} description="Dokumentasi pekerjaan yang diterbitkan pengelola." href="/progres" label="Lihat progres pembangunan"/><ProgressList data={data} limit={2}/></section>, finance: <section className="section finance-section"><div className="wrap"><SectionTitle eyebrow="Terbuka dalam setiap amanah" title={s.financeTitle} href="/laporan" label="Buka laporan"/><FinanceSummary data={data}/><p className="finance-note"><ShieldCheck size={17}/>Penerimaan bruto hanya mencakup pembayaran terverifikasi. Biaya, pengembalian dana, dan pengeluaran dicatat terpisah.</p></div></section>, faq: <Faq data={data}/> }; return <><section className={'hero ' + (s.heroMedia ? 'with-photo' : '')} style={s.heroMedia ? { backgroundImage: `linear-gradient(90deg,rgba(13,48,39,.95),rgba(13,48,39,.65)),url(${mediaSrc(s.heroMedia)})` } : undefined}><div className="wrap hero-grid"><div className="hero-copy"><span className="hero-kicker"><span />{s.heroKicker}</span><h1>{s.title}</h1><p>{s.description}</p><div className="hero-actions"><a className="btn gold" href={s.primaryHref}><Heart size={18}/>{s.primaryLabel}</a><a className="btn ghost" href={s.secondaryHref}>{s.secondaryLabel}</a></div><div className="hero-trust"><ShieldCheck size={21}/><span>Dikelola oleh <strong>{s.foundation}</strong></span></div></div><div className="campaign-card"><div className="campaign-top"><span className="eyebrow">Bersama, selangkah lebih dekat</span><BookOpen size={28}/></div><h3 className="preline">{s.campaignTitle}</h3><div className="campaign-amount"><span>Dana terverifikasi</span><strong>{rupiah(data.finance.receipts)}</strong></div><ProgressBar value={data.finance.receipts} target={data.target}/><div className="campaign-target"><span>dari target {rupiah(data.target)}</span><strong>{data.target?Math.round(data.finance.receipts / data.target * 100):0}%</strong></div><div className="campaign-programs"><div><Trees size={18}/><span>{data.programs.find((p:any)=>p.icon==='land')?.title||'Pengadaan tanah'}</span><b>{data.programs.find((p:any)=>p.icon==='land')?.area?new Intl.NumberFormat('id-ID').format(data.programs.find((p:any)=>p.icon==='land').area)+' m²':'Belum diisi'}</b></div><div><Building2 size={18}/><span>Fasilitas pendidikan</span><b>{data.programs.length} program</b></div></div><a className="btn full" href="/donasi">{s.campaignLabel}</a><small>Nominal bebas. Tidak perlu membuat akun.</small></div></div></section>{(s.sectionOrder || ['stats', 'story', 'programs', 'progress', 'finance', 'faq']).map((key: string) => <React.Fragment key={key}>{sections[key]}</React.Fragment>)}<section className="closing"><div className="wrap"><span className="eyebrow">Bagian kecil Anda, manfaat yang berlanjut</span><h2>{s.closingTitle}</h2><p>{s.closingText}</p><a className="btn gold" href="/donasi"><Heart size={17}/>Donasi Sekarang</a></div></section></>; }
function PageHeading({ eyebrow, title, children }: {
    eyebrow: string;
    title: string;
    children?: React.ReactNode;
}) { return <div className="page-heading"><div className="wrap"><span className="eyebrow">{eyebrow}</span><h1>{title}</h1>{children && <p>{children}</p>}</div></div>; }
function Programs({ data }: {
    data: any;
}) { return <><PageHeading eyebrow="Donasi pembangunan" title={data.site.programsPageTitle}>Seluruh nominal dicatat sesuai tujuan yang Anda pilih. Anda bebas menentukan kontribusi.</PageHeading><section className="section wrap"><div className="program-grid">{data.programs.map((p: any, i: number) => <ProgramCard key={p.id} p={p} data={data} index={i}/>)}</div><Notice>{data.site.allocationPolicy}</Notice></section></>; }
function ProgramDetail({ p, data }: {
    p: any;
    data: any;
}) { const updates = { ...data, progress: data.progress.filter((x: any) => x.programId === p.id) }; return <><PageHeading eyebrow="Program pembangunan" title={p.title}>{p.subtitle}</PageHeading><section className="section wrap detail-grid"><article>{p.cover && <img className="detail-cover" src={mediaSrc(p.cover)} alt={data.media.find((m: any) => m.id === p.cover)?.alt || p.title}/>}<span className="eyebrow">Tentang program</span><h2>Manfaat yang ingin diwujudkan.</h2><p className="lead preline">{p.description}</p><p>{p.benefit}</p>{p.illustration && <Notice>{p.illustration}</Notice>}<h3 className="spaced">Rencana anggaran</h3><div className="table-scroll"><table><thead><tr><th>Kebutuhan</th><th className="right">Anggaran</th></tr></thead><tbody>{p.budget.map((b: any, i: number) => <tr key={i}><td>{b.name}</td><td className="right">{rupiah(b.amount)}</td></tr>)}<tr><th>Total target program</th><th className="right">{rupiah(p.target)}</th></tr></tbody></table></div><h3 className="spaced">Dokumentasi program</h3>{p.media?.length ? <Gallery ids={p.media} data={data}/> : <Empty title="Dokumentasi belum tersedia" icon={ImageIcon}>Foto asli akan ditampilkan setelah diterbitkan pengelola.</Empty>}<h3 className="spaced">Progres pekerjaan</h3><ProgressList data={updates}/><h3 className="spaced">Ketentuan penyaluran dana</h3><p>{p.policy || data.site.allocationPolicy}</p></article><aside className="donation-side"><span className="eyebrow">Dukung kebutuhan ini</span><h3>{p.title}</h3><div className="campaign-amount"><span>Penerimaan terverifikasi</span><strong>{rupiah(p.receipts)}</strong></div><ProgressBar value={p.receipts} target={p.target}/><div className="fund-goal"><span>Target {rupiah(p.target)}</span><span>{Math.round(p.receipts / p.target * 100)}%</span></div>{p.open && p.state !== 'archived' ? <a className="btn full" href={'/donasi?program=' + p.id}><Heart size={17}/>Donasi ke program ini</a> : <Notice>Program ini sedang tidak menerima donasi. Riwayat tetap tersimpan.</Notice>}<small>Nominal bebas. Progres dana terpisah dari progres fisik.</small></aside></section></>; }
function ProgressPage({ data }: {
    data: any;
}) { const [program, setProgram] = useState(''); const filtered = { ...data, progress: data.progress.filter((p: any) => !program || p.programId === program) }; return <><PageHeading eyebrow="Dokumentasi & pekerjaan" title={data.site.progressPageTitle}>Pembaruan berdasarkan kegiatan yang dicatat dan diterbitkan oleh pengelola.</PageHeading><section className="section wrap"><div className="filter-row"><label htmlFor="programFilter">Program</label><select id="programFilter" value={program} onChange={e => setProgram(e.target.value)}><option value="">Semua program</option>{data.programs.map((p: any) => <option key={p.id} value={p.id}>{p.title}</option>)}</select><span className="muted">{filtered.progress.length} pembaruan diterbitkan</span></div><Notice>Persentase pekerjaan fisik menggunakan dasar penilaian pengelola. Pencapaian dana dihitung dari pembayaran terverifikasi.</Notice><ProgressList data={filtered}/></section></>; }
function Reports({ data: initial }: {
    data: any;
}) { const [data, setData] = useState(initial), [from, setFrom] = useState(''), [to, setTo] = useState(''), [program, setProgram] = useState('all'), [busy, setBusy] = useState(false), [error, setError] = useState(''); async function filter(e: React.FormEvent) { e.preventDefault(); setBusy(true); setError(''); try {
    const query = new URLSearchParams();
    if (from)
        query.set('from', from);
    if (to)
        query.set('to', to);
    if (program !== 'all')
        query.set('program', program);
    setData(await api('public?' + query));
}
catch (err) {
    setError((err as Error).message);
}
finally {
    setBusy(false);
} } return <><PageHeading eyebrow="Transparansi penggunaan dana" title={data.site.reportsPageTitle}>Penerimaan terverifikasi, penggunaan dana, serta laporan yang disetujui untuk publik.</PageHeading><section className="section wrap"><form className="report-filter" onSubmit={filter}><label>Mulai periode<input type="date" value={from} onChange={e => setFrom(e.target.value)}/></label><label>Akhir periode<input type="date" min={from || undefined} value={to} onChange={e => setTo(e.target.value)}/></label><label>Cakupan<select value={program} onChange={e => setProgram(e.target.value)}><option value="all">Seluruh kampanye</option><option value="">Dana prioritas</option>{initial.programs.map((p: any) => <option key={p.id} value={p.id}>{p.title}</option>)}</select></label><button className="btn" disabled={busy}>{busy ? 'Memuat…' : 'Tampilkan laporan'}</button></form>{error && <Notice kind="error">{error}</Notice>}<FinanceSummary data={data}/><div className="report-note"><p><strong>Penerimaan ditampilkan bruto.</strong> Biaya transaksi dan pengembalian dana dicatat terpisah. Donasi offline masuk setelah pemeriksaan dan verifikasi.</p><p>Saldo awal: {rupiah(data.finance.opening)}. Alokasi masuk: {rupiah(data.finance.allocIn)}. Alokasi keluar: {rupiah(data.finance.allocOut)}. Saldo akhir: {rupiah(data.finance.balance)}.</p><p>Angka ini mencakup dana kampanye sesuai filter. Angka ini bukan keseluruhan saldo rekening yayasan.</p></div><SectionTitle eyebrow="Dokumen yang disetujui" title="Laporan publik"/>{data.reports.length ? <div className="report-list">{data.reports.map((r: any) => <article className="report-item" key={r.id}><FileText size={27}/><div><h3>{r.title}</h3><p>{tanggal(r.from)} sampai {tanggal(r.to)}</p><p>{r.summary}</p>{r.totals && <small>Penerimaan {rupiah(r.totals.receipts)} · Saldo {rupiah(r.totals.balance)} · Disetujui {tanggal(r.approvedAt)}</small>}</div>{r.documentMedia && <a className="btn outline" href={mediaSrc(r.documentMedia)} target="_blank" rel="noreferrer"><Download size={17}/>Baca / unduh PDF</a>}</article>)}</div> : <Empty title="Laporan publik belum diterbitkan">Dokumen laporan akan tersedia setelah diperiksa dan disetujui pengelola.</Empty>}<h3 className="spaced">Dana menurut program</h3><div className="table-scroll"><table><thead><tr><th>Program</th><th className="right">Penerimaan bruto</th><th className="right">Saldo saat ini</th></tr></thead><tbody><tr><td>Kebutuhan Pembangunan Prioritas</td><td className="right">{rupiah(initial.priority.receipts)}</td><td className="right">{rupiah(initial.priority.balance)}</td></tr>{initial.programs.map((p: any) => <tr key={p.id}><td>{p.title}</td><td className="right">{rupiah(p.receipts)}</td><td className="right">{rupiah(p.balance)}</td></tr>)}</tbody></table></div><p className="muted">Tabel program menampilkan seluruh pencatatan hingga saat ini. Ringkasan di atas mengikuti periode yang Anda pilih.</p></section></>; }
function About({ data }: {
    data: any;
}) { const s = data.site; return <><PageHeading eyebrow="Mengenal pengelola" title={s.aboutPageTitle}>{s.pesantrenName} dan {s.schoolName}.</PageHeading><section className="section wrap about-grid"><article><span className="eyebrow">Yayasan Bina Pelajar Cirebon</span><h2>Pendidikan dan kegiatan Qur’ani.</h2><p className="lead preline">{s.profile}</p>{s.vision && <><h3 className="spaced">Visi</h3><p>{s.vision}</p></>}{s.board?.length > 0 && <><h3 className="spaced">Pengurus</h3>{s.board.map((b: any, i: number) => <p key={i}><strong>{b.name}</strong><br />{b.position}</p>)}</>}<h3 className="spaced">Proposal pembangunan</h3>{s.proposalMedia ? <div className="proposal-view"><iframe src={mediaSrc(s.proposalMedia)} title="Proposal pembangunan Al-Habibah"/><a className="btn outline" href={mediaSrc(s.proposalMedia)} target="_blank" rel="noreferrer"><Download size={17}/>Baca / unduh proposal PDF</a></div> : <Empty title="Proposal PDF belum diunggah">Rincian target yang tersedia mengikuti data awal yang diberikan. Dokumen sumber akan diterbitkan setelah diunggah dan diperiksa pengelola.</Empty>}{s.officialDocuments?.length > 0 && <><h3 className="spaced">Dokumen resmi yang dipublikasikan</h3><Gallery ids={s.officialDocuments} data={data}/></>}<h3 className="spaced">Donasi pembangunan dan wakaf tanah</h3><p>{s.wakafExplanation}</p></article><aside className="contact-card"><MapPin size={29}/><h3>Datang & kenali kami.</h3><p>{s.address}</p><a className="btn full" href={`https://wa.me/${s.whatsapp}`} target="_blank" rel="noreferrer"><Phone size={16}/>WhatsApp pengelola</a><a className="btn outline full" href={s.website} target="_blank" rel="noreferrer"><ExternalLink size={16}/>Website sekolah</a>{s.mapUrl && <a className="text-link" href={s.mapUrl} target="_blank" rel="noreferrer">Lihat lokasi terkonfirmasi<ExternalLink size={16}/></a>}</aside></section></>; }
function DonationForm({ data }: {
    data: any;
}) {
    const [amount, setAmount] = useState(''), [program, setProgram] = useState(''), [name, setName] = useState(''), [contact, setContact] = useState(''), [message, setMessage] = useState(''), [publishName, setPublishName] = useState(false), [publishMessage, setPublishMessage] = useState(false), [terms, setTerms] = useState(false), [busy, setBusy] = useState(false), [error, setError] = useState('');
    useEffect(() => { const p = new URLSearchParams(window.location.search).get('program'); if (p && data.programs.some((x: any) => x.id === p && x.open && x.state !== 'archived'))
        setProgram(p); }, [data]);
    async function submit(e: React.FormEvent) { e.preventDefault(); setError(''); const value = Number(amount); if (!Number.isSafeInteger(value) || value <= 0 || value > 1000000000000) {
        setError('Masukkan nominal rupiah bulat positif, maksimal Rp1.000.000.000.000.');
        return;
    } if (!terms) {
        setError('Baca dan setujui ketentuan donasi terlebih dahulu.');
        return;
    } setBusy(true); try {
        const r = await api('donations', { amount: value, programId: program || null, name, contact, message, publishName, publishMessage });
        window.location.assign('/status/' + r.token);
    }
    catch (err) {
        setError((err as Error).message);
        setBusy(false);
    } }
    const selected = data.programs.find((p: any) => p.id === program);
    return <><PageHeading eyebrow="Setiap kontribusi berarti" title={data.site.donationPageTitle}>Pilih tujuan dan nominal donasi sesuai kemampuan. Tidak perlu membuat akun.</PageHeading><section className="section wrap donate-grid"><form id="donasi-form" className="donation-form" onSubmit={submit}><div className="step-title"><span>1</span><h3>Tentukan donasi Anda</h3></div><label htmlFor="nominal">Nominal donasi</label><div className="quick-amounts">{[10000, 25000, 50000, 100000, 250000].map(n => <button key={n} type="button" className={Number(amount) === n ? 'selected' : ''} onClick={() => setAmount(String(n))}>{rupiah(n)}</button>)}</div><label className="custom-amount">Nominal sendiri<div><span>Rp</span><input id="nominal" type="text" inputMode="numeric" pattern="[0-9]+" placeholder="Masukkan nominal pilihan Anda" value={amount} onChange={e => setAmount(e.target.value.replace(/[^0-9]/g, ''))} required/></div></label><p className="field-help">Nominal di atas hanya pilihan cepat. Anda bebas menentukan jumlah donasi.</p><p className="field-help">Rupiah bulat positif. Batas aplikasi Rp1 sampai Rp1.000.000.000.000. Biaya transfer yang dikenakan bank pengirim mengikuti layanan bank Anda.</p><label htmlFor="tujuan">Tujuan donasi<select id="tujuan" value={program} onChange={e => setProgram(e.target.value)}><option value="">Kebutuhan Pembangunan Prioritas</option>{data.programs.filter((p: any) => p.open && p.state !== 'archived').map((p: any) => <option key={p.id} value={p.id}>{p.title}</option>)}</select></label><div className="step-title"><span>2</span><h3>Informasi donatur</h3></div><label>Nama <span className="optional">opsional</span><input autoComplete="name" value={name} onChange={e => setName(e.target.value)} maxLength={120} placeholder="Kosongkan untuk Hamba Allah"/></label><label className="checkbox"><input type="checkbox" checked={!publishName} onChange={e => setPublishName(!e.target.checked)}/><span>Sembunyikan nama saya dari publik</span></label>{publishName && <p className="field-help">Saya menyetujui nama saya ditampilkan pada informasi donasi publik setelah pembayaran diverifikasi.</p>}<label>WhatsApp atau email <span className="optional">opsional</span><input value={contact} onChange={e => setContact(e.target.value)} maxLength={200} placeholder="Untuk bukti penerimaan atau konfirmasi"/></label><p className="field-help"><LockKeyhole size={14}/> Kontak Anda hanya dapat diakses pengelola yang berwenang.</p><label>Pesan atau doa <span className="optional">opsional</span><textarea rows={3} value={message} onChange={e => setMessage(e.target.value)} maxLength={2000} placeholder="Pesan ini privat secara default"/></label><label className="checkbox"><input type="checkbox" checked={publishMessage} onChange={e => setPublishMessage(e.target.checked)}/><span>Saya mengizinkan pesan ditampilkan setelah diperiksa pengelola.</span></label><div className="step-title"><span>3</span><h3>Metode pembayaran</h3></div><div className="payment-method"><Landmark size={26}/><div><strong>Transfer Bank Syariah Indonesia</strong><span>{data.paymentReady ? 'Transfer manual, diperiksa pengelola' : 'Menunggu konfirmasi rekening pengelola'}</span></div><span className="tag">{data.paymentReady ? 'Tersedia' : 'Belum aktif'}</span></div><p className="field-help">QRIS dan virtual account belum diaktifkan.</p>{!data.paymentReady && <Notice>Pengelola perlu memeriksa dokumen rekening sebelum instruksi pembayaran dapat ditampilkan. Formulir donasi akan dapat dilanjutkan setelah pemeriksaan selesai.</Notice>}<label className="checkbox terms"><input type="checkbox" checked={terms} onChange={e => setTerms(e.target.checked)} required/><span>Saya memahami <a href="/ketentuan" target="_blank">ketentuan donasi</a> dan <a href="/privasi" target="_blank">kebijakan privasi</a>. Donasi saya mengikuti tujuan yang dipilih.</span></label>{error && <Notice kind="error">{error}</Notice>}<button className="btn full large" disabled={busy || !data.paymentReady}>{busy ? <Loader2 className="spin" size={18}/> : <Heart size={18}/>} {busy ? 'Membuat instruksi…' : 'Lanjutkan ke instruksi pembayaran'}</button><small className="secure-note"><ShieldCheck size={16}/>Total penerimaan bertambah setelah verifikasi bank.</small></form><aside><div className="donation-side"><span className="eyebrow">Ringkasan donasi</span><h3>{selected?.title || 'Kebutuhan Pembangunan Prioritas'}</h3><div className="summary-line"><span>Nominal donasi</span><strong>{rupiah(Number(amount) || 0)}</strong></div><div className="summary-line"><span>Biaya dari website</span><strong>Rp0</strong></div><div className="summary-total"><span>Total transfer</span><strong>{rupiah(Number(amount) || 0)}</strong></div><p className="field-help">Biaya dari bank pengirim, jika ada, ditanggung sesuai ketentuan bank. Website tidak menambahkan kode nominal.</p><div className="side-note"><ShieldCheck size={22}/><p>Donasi Anda tercatat sesuai peruntukan. Dana program khusus tidak dialihkan otomatis.</p></div></div><div className="help-card"><h4>Butuh bantuan?</h4><p>Pengelola siap membantu proses donasi Anda.</p><a className="text-link" href={`https://wa.me/${data.site.whatsapp}`} target="_blank" rel="noreferrer"><Phone size={16}/>Hubungi via WhatsApp</a></div></aside></section></>;
}
function DonationStatus({ token, data }: {
    token: string;
    data: any;
}) {
    const [d, setD] = useState<any>(null), [error, setError] = useState(''), [busy, setBusy] = useState(false), [file, setFile] = useState<File | null>(null), [copied, setCopied] = useState(false), [success, setSuccess] = useState('');
    async function load() { try {
        setD(await api('donation/' + token));
        setError('');
    }
    catch (err) {
        setError((err as Error).message);
    } }
    useEffect(() => { load(); }, [token]);
    async function send(e: React.FormEvent) { e.preventDefault(); if (!file) {
        setError('Pilih bukti JPG, PNG, atau PDF terlebih dahulu.');
        return;
    } if (file.size > 5242880) {
        setError('Ukuran bukti maksimal 5 MB.');
        return;
    } setBusy(true); setError(''); try {
        const form = new FormData();
        form.set('file', file);
        const r = await fetch('/api/donation/' + token, { method: 'POST', headers: { 'x-alhabibah': '1' }, body: form });
        const value: any = await r.json();
        if (!r.ok)
            throw new Error(value.error);
        await load();
        setSuccess('Bukti tersimpan secara privat. Pembayaran Anda menunggu pemeriksaan penerimaan bank.');
        setFile(null);
    }
    catch (err) {
        setError((err as Error).message);
    }
    finally {
        setBusy(false);
    } }
    return <><PageHeading eyebrow="Status donasi Anda" title="Terima kasih atas niat baik Anda.">Simpan tautan halaman ini untuk memantau status. Tautan ini bersifat privat.</PageHeading><section className="section wrap status-wrap">{error && <Notice kind="error">{error}</Notice>}{!d && !error ? <Empty title="Memuat status donasi…" icon={Loader2}/> : d && <><div className="status-card"><div className="status-header">{d.status === 'verified' ? <CheckCircle2 size={30}/> : <Clock3 size={30}/>}<div><span className={'tag ' + d.status}>{statusLabel[d.status]}</span><h3>{rupiah(d.amount)}</h3><p>{d.program}</p></div></div><dl className="status-facts"><div><dt>Nomor transaksi</dt><dd className="mono">{d.id}</dd></div><div><dt>Dibuat</dt><dd>{tanggal(d.createdAt)}</dd></div><div><dt>Batas instruksi</dt><dd>{tanggal(d.expiresAt)}</dd></div><div><dt>Nama pada bukti</dt><dd>{d.name}</dd></div></dl>{d.reason && <Notice>{d.reason}</Notice>}{['verified', 'refunded'].includes(d.status) ? <><Notice kind="success">{d.status === 'verified' ? 'Penerimaan telah diverifikasi pengelola. Bukti penerimaan tersedia.' : 'Transaksi memiliki catatan pengembalian dana.'}</Notice><div className="receipt print-area"><h3>Bukti penerimaan Donasi Pembangunan</h3><p>{d.receipt?.foundation}</p><p>Nomor: {d.id}<br />Nama: {d.receipt?.name}<br />Nominal: {rupiah(d.receipt?.amount)}<br />Tujuan: {d.receipt?.program}<br />Diverifikasi: {tanggal(d.receipt?.verifiedAt)}</p><p>Bukti ini mengikuti informasi saat penerimaan diverifikasi. Bukti ini bukan sertifikat wakaf.</p></div><button className="btn outline" onClick={() => window.print()}><Download size={16}/>Cetak / simpan bukti sebagai PDF</button></> : <><Notice>Instruksi pembayaran dan unggahan bukti belum menyatakan pembayaran berhasil. Pengelola akan memeriksa penerimaan bank.</Notice>{d.bank ? <div className="bank-instructions"><Landmark size={24}/><h3>{d.bank.bank}</h3><span>Rekening atas nama {d.bank.holder}</span><div className="bank-number"><strong>{d.bank.number}</strong><button className="btn outline small" onClick={async () => { try {
        await navigator.clipboard.writeText(d.bank.number);
        setCopied(true);
    }
    catch {
        setError('Salin nomor rekening secara manual.');
    } }}>{copied ? <Check size={15}/> : <Copy size={15}/>} {copied ? 'Tersalin' : 'Salin'}</button></div><p>Transfer {rupiah(d.amount)} sesuai ringkasan. Periksa nama penerima sebelum melanjutkan. Setelah transfer, unggah bukti di bawah.</p>{d.status === 'expired' && <p>Instruksi telah kedaluwarsa. Jika Anda sudah membayar, tetap unggah bukti untuk rekonsiliasi pengelola.</p>}</div> : <Notice>Rekening belum dapat ditampilkan. Hubungi pengelola untuk pemeriksaan.</Notice>}<form onSubmit={send} className="proof-form"><label htmlFor="proof">Bukti transfer<input id="proof" type="file" accept="image/jpeg,image/png,application/pdf" onChange={e => setFile(e.target.files?.[0] || null)}/></label><p className="field-help">JPG, PNG, atau PDF, maksimal 5 MB. Bukti tersimpan privat.</p><button className="btn" disabled={busy}>{busy ? 'Mengunggah…' : 'Saya Sudah Transfer, Kirim Bukti'}</button></form>{success && <Notice kind="success">{success}</Notice>}</>}{d.proofs.length > 0 && <div className="proof-list"><h4>Bukti yang telah dikirim</h4>{d.proofs.map((p: any) => <p key={p.id}><Check size={16}/>{p.name} · {tanggal(p.created_at)}</p>)}</div>}<div className="status-actions"><button className="btn outline" onClick={load}>Perbarui status</button><a className="btn outline" target="_blank" rel="noreferrer" href={`https://wa.me/${data.site.whatsapp}?text=${encodeURIComponent(`Assalamu’alaikum. Saya ingin konfirmasi donasi ${d.id}, nominal ${rupiah(d.amount)}, program ${d.program}. Mohon diperiksa penerimaannya. Status saat ini: ${statusLabel[d.status]}.`)}`}><Phone size={16}/>Konfirmasi via WhatsApp</a></div><p className="field-help">WhatsApp akan membuka pesan siap kirim. Anda yang mengirimkannya.</p></div></>}</section></>;
}
export default function Site({ initial, path }: {
    initial: any;
    path: string;
}) {
    const [data, setData] = useState(initial), [retrying, setRetrying] = useState(false);
    if (path === '/admin' || path.startsWith('/admin/'))
        return <Admin publicData={initial}/>;
    if (!data)
        return <main className="wrap service-error"><BookOpen size={44}/><h1>Donasi Al-Habibah</h1><Notice kind="error">Informasi belum dapat dimuat. Silakan coba kembali. Angka penerimaan tidak ditampilkan selama layanan data tidak tersedia.</Notice><button className="btn" disabled={retrying} onClick={async () => { setRetrying(true); try {
            setData(await api('public'));
        }
        catch { }
        finally {
            setRetrying(false);
        } }}>{retrying ? 'Memuat…' : 'Coba lagi'}</button></main>;
    let page: React.ReactNode;
    const slug = path.split('/')[2];
    if (path === '/')
        page = <Home data={data}/>;
    else if (path === '/program')
        page = <Programs data={data}/>;
    else if (path.startsWith('/program/')) {
        const p = data.programs.find((p: any) => p.slug === slug);
        page = p ? <ProgramDetail p={p} data={data}/> : null;
    }
    else if (path === '/progres')
        page = <ProgressPage data={data}/>;
    else if (path === '/laporan')
        page = <Reports data={data}/>;
    else if (path === '/tentang')
        page = <About data={data}/>;
    else if (path === '/donasi')
        page = <DonationForm data={data}/>;
    else if (path.startsWith('/status/'))
        page = <DonationStatus token={slug} data={data}/>;
    else if (path === '/privasi' || path === '/ketentuan')
        page = <><PageHeading eyebrow="Informasi untuk donatur" title={path === '/privasi' ? 'Kebijakan privasi' : 'Ketentuan donasi'}/><section className="section wrap narrow"><p className="lead preline">{path === '/privasi' ? data.site.privacy : data.site.terms}</p><p>Hubungi <a className="text-link" href={`https://wa.me/${data.site.whatsapp}`}>pengelola Al-Habibah</a> untuk informasi atau permintaan koreksi.</p></section></>;
    if (!page)
        page = <div className="section wrap"><Empty title="Halaman tidak ditemukan">Periksa kembali alamat halaman atau kembali ke beranda.</Empty><a className="btn" href="/">Kembali ke beranda</a></div>;
    return <><a className="skip-link" href="#main">Lewati navigasi</a><Header site={data.site} path={path}/><main id="main">{page}</main><Footer site={data.site}/>{!path.startsWith('/status/') && <div className="mobile-donate"><a className="btn full" href={path==='/donasi'?'#donasi-form':'/donasi'}><Heart size={17}/>Donasi Sekarang</a></div>}</>;
}
