141 lines
6.8 KiB
JavaScript
141 lines
6.8 KiB
JavaScript
import React from 'react';
|
|
|
|
export default function DonationModal({
|
|
showDonationModal,
|
|
setShowDonationModal,
|
|
donationFormData,
|
|
setDonationFormData,
|
|
hubs,
|
|
isSubmittingDonation,
|
|
handleSaveDonation,
|
|
donationsList,
|
|
profile
|
|
}) {
|
|
if (!showDonationModal) return null;
|
|
if (!profile) return null; // Secure fail-safe for unauthenticated users
|
|
|
|
// Check roles: PIC, Hub Head, and Super Admin can record transactions
|
|
const canEdit = profile.role === 'super_admin' || profile.role === 'pic' || profile.role === 'hub_head';
|
|
|
|
// Calculate Running / Total Balance
|
|
const totalBalance = donationsList.reduce((acc, curr) => {
|
|
if (curr.type === 'IN') {
|
|
return acc + Number(curr.amount);
|
|
} else {
|
|
return acc - Number(curr.amount);
|
|
}
|
|
}, 0);
|
|
|
|
// Filter hubs list based on role
|
|
const allowedHubs = profile.role === 'super_admin'
|
|
? hubs
|
|
: hubs.filter(h => h.pic_id === profile.id || h.head_id === profile.id);
|
|
|
|
return (
|
|
<div className="modal-overlay active">
|
|
<div className="modal-content" style={{ maxWidth: '800px', width: '90%' }}>
|
|
<div className="modal-header">
|
|
<h2><i className="fas fa-hand-holding-heart text-primary"></i> Manajemen Donasi / Kas</h2>
|
|
<button className="close-btn" onClick={() => setShowDonationModal(false)}>×</button>
|
|
</div>
|
|
<div className="modal-body" style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: canEdit ? '1fr 1fr' : '1fr',
|
|
gap: '20px',
|
|
maxHeight: '60vh',
|
|
overflowY: 'auto'
|
|
}}>
|
|
|
|
{/* Form Transaksi (Only for PIC & Super Admin) */}
|
|
{canEdit && (
|
|
<div>
|
|
<h3 style={{ margin: '0 0 15px 0', fontSize: '1.1rem' }}>Tambah Transaksi</h3>
|
|
<form onSubmit={handleSaveDonation} style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}>
|
|
<div className="form-group">
|
|
<label>Rumah Ibadah</label>
|
|
<select
|
|
className="form-control"
|
|
value={donationFormData.hub_id}
|
|
onChange={(e) => setDonationFormData({...donationFormData, hub_id: e.target.value})}
|
|
required
|
|
disabled={profile.role !== 'super_admin'}
|
|
>
|
|
<option value="">Pilih Rumah Ibadah</option>
|
|
{allowedHubs.map(h => <option key={h.id} value={h.id}>{h.name}</option>)}
|
|
</select>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>Jenis Transaksi</label>
|
|
<select className="form-control" value={donationFormData.type} onChange={(e) => setDonationFormData({...donationFormData, type: e.target.value})} required>
|
|
<option value="IN">Pemasukan (Donasi/Sedekah)</option>
|
|
<option value="OUT">Pengeluaran (Bantuan/Operasional)</option>
|
|
</select>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>Nominal (Rp)</label>
|
|
<input type="number" className="form-control" value={donationFormData.amount} onChange={(e) => setDonationFormData({...donationFormData, amount: e.target.value})} min="1" required />
|
|
</div>
|
|
<div className="form-group">
|
|
<label>Keterangan</label>
|
|
<textarea className="form-control" value={donationFormData.description} onChange={(e) => setDonationFormData({...donationFormData, description: e.target.value})} required rows="3" placeholder="Contoh: Sedekah hamba Allah / Bantuan Sembako"></textarea>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>Tanggal Transaksi</label>
|
|
<input type="date" className="form-control" value={donationFormData.transaction_date} onChange={(e) => setDonationFormData({...donationFormData, transaction_date: e.target.value})} required />
|
|
</div>
|
|
<button type="submit" className="btn btn-primary" disabled={isSubmittingDonation} style={{ width: '100%', padding: '10px' }}>
|
|
<i className="fas fa-save"></i> {isSubmittingDonation ? 'Menyimpan...' : 'Simpan Transaksi'}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
)}
|
|
|
|
{/* Transaction Logs */}
|
|
<div style={{ background: '#f8fafc', padding: '15px', borderRadius: '8px' }}>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '15px', flexWrap: 'wrap', gap: '10px' }}>
|
|
<h3 style={{ margin: 0, fontSize: '1.1rem' }}>Riwayat Transaksi</h3>
|
|
<div style={{
|
|
padding: '6px 12px',
|
|
background: totalBalance >= 0 ? '#dcfce7' : '#fee2e2',
|
|
color: totalBalance >= 0 ? '#15803d' : '#b91c1c',
|
|
borderRadius: '20px',
|
|
fontWeight: 'bold',
|
|
fontSize: '0.85rem'
|
|
}}>
|
|
Saldo Kas: Rp{totalBalance.toLocaleString('id-ID')}
|
|
</div>
|
|
</div>
|
|
{donationsList.length === 0 ? (
|
|
<p style={{ textAlign: 'center', color: '#94a3b8', fontSize: '0.9rem', padding: '20px 0' }}>Belum ada data transaksi.</p>
|
|
) : (
|
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.85rem' }}>
|
|
<thead>
|
|
<tr style={{ background: '#e2e8f0', textAlign: 'left' }}>
|
|
<th style={{ padding: '8px', borderBottom: '2px solid #cbd5e1' }}>Tanggal</th>
|
|
<th style={{ padding: '8px', borderBottom: '2px solid #cbd5e1' }}>Keterangan</th>
|
|
<th style={{ padding: '8px', borderBottom: '2px solid #cbd5e1', textAlign: 'right' }}>Nominal</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{donationsList.map(d => (
|
|
<tr key={d.id} style={{ borderBottom: '1px solid #e2e8f0' }}>
|
|
<td style={{ padding: '8px', color: '#475569' }}>{d.transaction_date}</td>
|
|
<td style={{ padding: '8px' }}>
|
|
<span style={{ fontWeight: '500', color: '#1e293b' }}>{d.description}</span>
|
|
{d.profiles && d.profiles.full_name && <div style={{ fontSize: '0.7rem', color: '#94a3b8' }}>Oleh: {d.profiles.full_name}</div>}
|
|
</td>
|
|
<td style={{ padding: '8px', textAlign: 'right', fontWeight: 'bold', color: d.type === 'IN' ? '#10b981' : '#ef4444' }}>
|
|
{d.type === 'IN' ? '+' : '-'} Rp{Number(d.amount).toLocaleString('id-ID')}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|