/* ════════════════════════════════════════════════ Halaman Donasi — campaign + progress + rekening + form ════════════════════════════════════════════════ */ const NOMINALS = [50000, 100000, 250000, 500000, 1000000, 2500000]; const rpShort = (n) => n >= 1000000 ? (n / 1000000).toFixed(n % 1000000 ? 1 : 0) + ' jt' : n >= 1000 ? (n / 1000) + ' rb' : n; function DonasiPage({ navigate }) { const [campaigns, setCampaigns] = useState([]); const [rekening, setRekening] = useState([]); const [settings, setSettings] = useState({}); const [stats, setStats] = useState({ total_masuk: 0, total_donatur: 0, total_campaign: 0 }); const [loading, setLoading] = useState(true); const [nominal, setNominal] = useState(250000); const [custom, setCustom] = useState(''); const [modal, setModal] = useState(null); // { campaign, amount } useEffect(() => { const f = window.__openDonasiForm; if (f) { window.__openDonasiForm = false; setTimeout(() => setModal({ campaign: (f && f.id) ? f : null, amount: 250000 }), 120); } }, []); useEffect(() => { Promise.all([ api.get('donations.php?action=list_campaigns'), api.get('donations.php?action=list_rekening'), api.get('donations.php?action=public_stats'), api.get('donations.php?action=get_settings'), ]).then(([c, r, s, st]) => { if (c.ok && c.campaigns) setCampaigns(c.campaigns); if (r.ok && r.rekening) setRekening(r.rekening); if (s.ok) setStats({ total_masuk: s.total_masuk || 0, total_donatur: s.total_donatur || 0, total_campaign: s.kampanye_aktif ?? s.total_campaign ?? 0 }); if (st.ok && st.settings) setSettings(st.settings); }).finally(() => setLoading(false)); }, []); const finalNominal = custom ? (parseInt(custom) || 0) : nominal; return (
{/* Statistik */}
{[[fmtRpShort(stats.total_masuk), 'Terkumpul'], [stats.total_donatur, 'Donatur'], [stats.total_campaign, 'Program Donasi']].map(([n, l]) => (
{n}
{l}
))}
{/* QUICK DONATE */}
Donasi Cepat
{NOMINALS.map(n => { const active = nominal === n && !custom; return ; })}
setCustom(e.target.value.replace(/\D/g, ''))} placeholder="Nominal lain (Rp)" inputMode="numeric" style={{ flex: 1, minWidth: 160, padding: '13px 16px', borderRadius: 12, border: '1.5px solid var(--border)', fontSize: 14.5, fontFamily: 'inherit', background: 'var(--surface)', color: 'var(--ink-deep)' }} />
{/* CAMPAIGNS */}
{loading ?
Memuat…
: (
{campaigns.map(c => { // Normalisasi: PHP asli pakai nama Indonesia, mock pakai Inggris const collected = c.terkumpul ?? c.collected ?? 0; const target = c.target ?? 0; const desc = c.deskripsi || c.description || ''; const cover = c.cover_url || c.image_url; const urgent = c.urgensi === 'tinggi' || c.urgent; const pct = c.percent != null ? c.percent : (target ? Math.min(100, Math.round((collected / target) * 100)) : 0); const done = c.urgensi === 'selesai' || c.status === 'arsip' || c.status === 'selesai' || pct >= 100; const cslug = c.slug || (window.slugify ? slugify(c.title) : c.id); const openCard = (e) => { if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) return; e.preventDefault(); setModal({ campaign: c, amount: finalNominal }); }; return (
{cover ? : } {urgent ? MENDESAK : null}
)}
{/* REKENING */}
{rekening.map((r, i) => )}
{settings.qris_url && (
Scan QRIS
Bayar pakai e-wallet (GoPay, OVO, Dana, ShopeePay) atau m-banking apa pun
QRIS Donasi
)}
{modal && setModal(null)} />}
); } function RekeningCard({ r }) { const [copied, setCopied] = useState(false); const num = r.number || r.nomor || ''; const copy = () => { navigator.clipboard?.writeText(num.replace(/[-\s]/g, '')); setCopied(true); setTimeout(() => setCopied(false), 1600); }; const atasNama = r.atas_nama || r.name || r.nama || ''; return (
{r.bank}
{num}
a.n. {atasNama}
); } function DonasiModal({ modal, rekening, settings, onClose }) { const methods = [...rekening.map(r => r.bank), ...(settings && settings.qris_url ? ['QRIS'] : [])]; const [form, setForm] = useState({ amount: modal.amount || 100000, donor_name: '', donor_phone: '', donor_email: '', metode: methods[0] || 'Transfer', catatan: '' }); const [sending, setSending] = useState(false); const [done, setDone] = useState(false); const upd = (k, v) => setForm(f => ({ ...f, [k]: v })); const waNum = (settings && settings.donasi_wa_konfirmasi) || '628123456789'; const submit = async (e) => { e.preventDefault(); if (form.amount < 1000 || !form.donor_phone) return; setSending(true); try { await api.post('donations.php?action=submit', { ...form, campaign_id: modal.campaign ? modal.campaign.id : null }); setDone(true); } finally { setSending(false); } }; const waConfirm = () => { const msg = `Assalamu'alaikum, saya ingin konfirmasi donasi:\n\nNama: ${form.donor_name || '-'}\nNominal: ${fmtRp(form.amount)}\nProgram: ${modal.campaign ? modal.campaign.title : 'Donasi Umum'}\nMetode: ${form.metode}`; window.open('https://wa.me/' + String(waNum).replace(/\D/g, '').replace(/^0/, '62') + '?text=' + encodeURIComponent(msg), '_blank'); }; return (
e.stopPropagation()} style={{ background: 'var(--surface)', borderRadius: 20, width: '100%', maxWidth: 440, maxHeight: '90vh', overflowY: 'auto', boxShadow: '0 30px 80px rgba(0,0,0,.35)' }}> {done ? (
🤲
Jazakumullah Khairan!

Donasi Anda sebesar {fmtRp(form.amount)} telah dicatat. Mohon transfer & konfirmasi via WhatsApp agar segera kami verifikasi.

) : (
Form Donasi
{modal.campaign ? modal.campaign.title : 'Donasi Umum'}
upd('amount', parseInt(e.target.value) || 0)} required min="1000" style={inp} /> upd('donor_name', e.target.value)} placeholder="Nama Anda" style={inp} /> upd('donor_phone', e.target.value.replace(/[^\d+]/g, ''))} required placeholder="08xxxxxxxxxx" style={inp} /> upd('donor_email', e.target.value)} placeholder="email@contoh.com" style={inp} /> {/* Detail pembayaran sesuai metode terpilih — langsung di form */} {(() => { if (form.metode === 'QRIS' && settings && settings.qris_url) { return (
Scan QR ini dengan e-wallet / m-banking apa pun
QRIS
); } const rk = rekening.find(r => r.bank === form.metode); if (rk) { const num = (rk.nomor || rk.number || ''); return (
{rk.bank} · a.n. {rk.atas_nama || rk.name || rk.nama}
{num}
); } return null; })()}