// checker-page.jsx — Checker (4 Eyes) Approval page for Hibank QRIS BackOffice function CheckerPage({ merchants, setMerchants, primary, secondary }) { const TEAL = primary || '#0056D2'; const ORANGE = secondary || '#cf5a27'; // Seed Maker-Checker Requests const [requests, setRequests] = React.useState([ { id: 'REQ-2606-0812', type: 'Perubahan Parameter Bisnis', detail: 'Ubah MDR Fee MRC-00244 (Batik Lestari Pekalongan) dari 0.70% menjadi 0.50%', maker: 'Merchant ABC', time: '2026-06-24T09:12:00', status: 'pending', targetMerchant: 'MRC-00244', updateKey: 'mdrFee', updateVal: '0.50%' }, { id: 'REQ-2606-0813', type: 'Refund Transaksi Manual', detail: 'Refund Transaksi TX-260624-8831 sebesar Rp 45.000 (Kopi Senja Nusantara)', maker: 'Merchant ABC', time: '2026-06-24T10:15:00', status: 'pending' }, { id: 'REQ-2606-0817', type: 'Pemeriksaan Onboarding Merchant', detail: 'Pemeriksaan kelayakan & validasi dokumen onboarding untuk calon merchant: Kopi Senja Nusantara (MID: MRC-00246, Bidang: 5814 - Kafe/Kopi)', maker: 'Dewi Anggraini ', time: '2026-06-24T10:20:00', status: 'pending', targetMerchant: 'MRC-00246', updateKey: 'status', updateVal: 'approved', isOnboarding: true }, { id: 'REQ-2606-0814', type: 'Perubahan Rekening Pencairan', detail: 'Ubah Rekening MRC-00246 (Kopi Senja Nusantara) ke Bank Mandiri 1310022419 a/n RANGGA PRATAMA', maker: 'Hendra Wijaya ', time: '2026-06-24T10:30:00', status: 'pending', targetMerchant: 'MRC-00246', updateKey: 'accountNumber', updateVal: '1310022419' }, { id: 'REQ-2606-0815', type: 'Suspend Terminal POS', detail: 'Deaktivasi POS-003 (POS Mobile Waiter) di MRC-00244 (Batik Lestari Pekalongan)', maker: 'Rangga Pratama (Operator)', time: '2026-06-24T10:45:00', status: 'pending' }, { id: 'REQ-2606-0816', type: 'Pemberian Limit Khusus', detail: 'Ubah Maks Transaksi MRC-00245 (Toko Bangunan Maju Jaya) dari Rp 10.000.000 menjadi Rp 25.000.000', maker: 'Dewi Anggraini', time: '2026-06-24T11:00:00', status: 'pending' } ]); const [activeTab, setActiveTab] = React.useState('pending'); // 'pending' | 'history' const [view, setView] = React.useState('list'); // 'list' | 'detail' const [selectedReq, setSelectedReq] = React.useState(null); const [checkerNote, setCheckerNote] = React.useState(''); const [toastMessage, setToastMessage] = React.useState(null); const fmtDate = (iso) => { const d = new Date(iso); return d.toLocaleDateString('id-ID', { day: '2-digit', month: 'short', year: 'numeric' }) + ' ' + d.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' }); }; const triggerToast = (msg) => { setToastMessage(msg); setTimeout(() => setToastMessage(null), 3000); }; // Approve action const handleApprove = () => { if (!selectedReq) return; // Perform state updates in requests setRequests(prev => prev.map(req => { if (req.id !== selectedReq.id) return req; return { ...req, status: 'approved', checker: 'Arief Budiman (Checker)', checkedAt: new Date().toISOString(), note: checkerNote.trim() || 'Disetujui' }; })); // If request contains targetMerchant update, apply it to merchants state if (selectedReq.targetMerchant && selectedReq.updateKey && setMerchants) { setMerchants(prev => prev.map(m => { if (m.id !== selectedReq.targetMerchant) return m; return { ...m, [selectedReq.updateKey]: selectedReq.updateVal }; })); } triggerToast(`Pengajuan ${selectedReq.id} berhasil disetujui.`); setSelectedReq(null); setCheckerNote(''); setView('list'); }; // Reject action const handleReject = () => { if (!selectedReq || !checkerNote.trim()) return; setRequests(prev => prev.map(req => { if (req.id !== selectedReq.id) return req; return { ...req, status: 'rejected', checker: 'Arief Budiman (Checker)', checkedAt: new Date().toISOString(), note: checkerNote.trim() }; })); triggerToast(`Pengajuan ${selectedReq.id} telah ditolak.`); setSelectedReq(null); setCheckerNote(''); setView('list'); }; const filteredRequests = requests.filter(r => activeTab === 'pending' ? r.status === 'pending' : r.status !== 'pending' ); // ── DETAILED APPROVAL SUB-PAGE VIEW ── if (view === 'detail' && selectedReq) { const isPending = selectedReq.status === 'pending'; const isApproved = selectedReq.status === 'approved'; const isRejected = selectedReq.status === 'rejected'; return (
{/* Breadcrumb */}
Checker Approval / Detail Request {selectedReq.id}
{/* Main Info */}
{/* Card 1: Request Details */}
{selectedReq.type}

Request ID: {selectedReq.id}

{selectedReq.status === 'pending' ? 'Pending Approval' : selectedReq.status.toUpperCase()}
Pengusul (Maker)
{selectedReq.maker}
Waktu Pengajuan
{fmtDate(selectedReq.time)}
Deskripsi Perubahan:
{selectedReq.detail}
{/* Special Section: Pemeriksaan Onboarding Merchant */} {selectedReq.isOnboarding && (

Dokumen & Informasi Onboarding Calon Merchant

{[ { label: 'NPWP Perusahaan/Pemilik', val: '09.254.812.3-014.000', verified: true }, { label: 'NIK Pemilik', val: '3273011505900002', verified: true }, { label: 'Rekening Bank Penerima', val: 'Bank Hibank - 8820145566 a/n RANGGA PRATAMA', verified: true }, { label: 'Dokumen Legalitas (SIUP/NIB)', val: 'NIB-812739123-A', verified: true } ].map((doc, idx) => (
{doc.label}
{doc.val}
Terverifikasi
))}
)}
{/* Checker Decision Log (If not pending) */} {!isPending && (

Log Otorisasi Checker

Pemeriksa (Checker)
{selectedReq.checker}
Waktu Pemeriksaan
{fmtDate(selectedReq.checkedAt)}
Catatan Checker:
{selectedReq.note || '—'}
)}
{/* Action Form (Sidebar style) */}
{isPending ? (

Form Otorisasi