feat: implement dynamic payment tracking with local storage and update transaction UI for battery investments

This commit is contained in:
sazzadulalambd
2026-05-19 18:22:06 +06:00
parent cd6d6e4386
commit f0d92f31ff

View File

@@ -344,10 +344,61 @@ export default function InvestmentDetailPage({ params }: { params: Promise<{ id:
date: new Date().toISOString().split('T')[0],
notes: ''
});
const [investmentPayments, setInvestmentPayments] = useState<any[]>([
const [investmentPayments, setInvestmentPayments] = useState<any[]>(() => {
if (!investment) return [];
const isBatteryPlan = investment.assetType === 'battery' || investment.planName?.toLowerCase().includes('battery');
if (typeof window !== 'undefined') {
const stored = localStorage.getItem(`jaiben_payments_${investmentId}`);
if (stored) {
try {
return JSON.parse(stored);
} catch (e) {
console.error(e);
}
}
}
if (isBatteryPlan) {
return [
{
id: `pay_${investmentId}`,
date: investment.startDate || '2024-02-01',
amount: investment.totalInvestment,
paymentMethod: investment.paymentMethod || 'bank',
transactionRef: investment.transactionId || 'TXN-BAT-001',
status: 'completed',
notes: 'Full Payment'
}
];
}
if (investmentId === 'ip2') {
return [
{
id: 'pay1_ip2',
date: '2024-01-20',
amount: investment.totalInvestment,
paymentMethod: 'mobile',
transactionRef: 'TXN-002',
status: 'completed',
notes: 'Full Payment'
}
];
}
// Default for ip1 or others
return [
{ id: 'pay1', date: '2024-01-15', amount: 50000, paymentMethod: 'bank', transactionRef: 'TXN-001', status: 'completed', notes: 'First installment' },
{ id: 'pay2', date: '2024-01-20', amount: 35000, paymentMethod: 'mobile', transactionRef: 'TXN-002', status: 'completed', notes: 'Second installment' },
]);
];
});
useEffect(() => {
if (typeof window !== 'undefined') {
localStorage.setItem(`jaiben_payments_${investmentId}`, JSON.stringify(investmentPayments));
}
}, [investmentPayments, investmentId]);
if (!investor || !investment) {
return (
@@ -622,12 +673,7 @@ export default function InvestmentDetailPage({ params }: { params: Promise<{ id:
>
Transactions
</button>
<button
onClick={() => setActiveTab('payments')}
className={`px-4 py-2 text-sm font-medium rounded-lg transition-colors ${activeTab === 'payments' ? 'bg-investor text-white' : 'text-slate-600 hover:bg-slate-100'}`}
>
Payments
</button>
<button
onClick={() => setActiveTab('pnl')}
className={`px-4 py-2 text-sm font-medium rounded-lg transition-colors ${activeTab === 'pnl' ? 'bg-investor text-white' : 'text-slate-600 hover:bg-slate-100'}`}
@@ -762,33 +808,37 @@ export default function InvestmentDetailPage({ params }: { params: Promise<{ id:
</thead>
<tbody className="divide-y divide-slate-100">
<tr>
<td className="px-4 py-3 text-sm text-slate-500">2024-01-15</td>
<td className="px-4 py-3 text-sm text-slate-500">{investment.startDate || '2024-01-15'}</td>
<td className="px-4 py-3 text-sm">Investment Funded</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">Credit</span></td>
<td className="px-4 py-3 text-sm text-right font-medium text-green-600">+৳85,000</td>
<td className="px-4 py-3 text-sm text-right font-medium text-green-600">+৳{investment.totalInvestment.toLocaleString()}</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">Completed</span></td>
</tr>
{investment.status === 'active' && (
<>
<tr>
<td className="px-4 py-3 text-sm text-slate-500">2024-02-15</td>
<td className="px-4 py-3 text-sm">Monthly Return</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs">Return</span></td>
<td className="px-4 py-3 text-sm text-right font-medium text-blue-600">+৳1,700</td>
<td className="px-4 py-3 text-sm text-right font-medium text-blue-600">+৳{(investment.monthlyReturn || (isBattery ? 4500 : 1700)).toLocaleString()}</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">Completed</span></td>
</tr>
<tr>
<td className="px-4 py-3 text-sm text-slate-500">2024-03-15</td>
<td className="px-4 py-3 text-sm">Monthly Return</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs">Return</span></td>
<td className="px-4 py-3 text-sm text-right font-medium text-blue-600">+৳1,700</td>
<td className="px-4 py-3 text-sm text-right font-medium text-blue-600">+৳{(investment.monthlyReturn || (isBattery ? 4500 : 1700)).toLocaleString()}</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">Completed</span></td>
</tr>
<tr>
<td className="px-4 py-3 text-sm text-slate-500">2024-04-15</td>
<td className="px-4 py-3 text-sm">Monthly Return</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs">Return</span></td>
<td className="px-4 py-3 text-sm text-right font-medium text-blue-600">+৳1,700</td>
<td className="px-4 py-3 text-sm text-right font-medium text-blue-600">+৳{(investment.monthlyReturn || (isBattery ? 4500 : 1700)).toLocaleString()}</td>
<td className="px-4 py-3 text-sm"><span className="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">Completed</span></td>
</tr>
</>
)}
</tbody>
</table>
</div>
@@ -825,12 +875,14 @@ export default function InvestmentDetailPage({ params }: { params: Promise<{ id:
<div className="space-y-4">
<div className="flex items-center justify-between">
<h4 className="font-semibold text-slate-800">Payment History</h4>
{!isBattery && (investment.totalInvestment - investmentPayments.reduce((sum, p) => sum + p.amount, 0)) > 0 && (
<button
onClick={() => setShowPartialPaymentModal(true)}
className="px-3 py-1.5 text-xs bg-investor text-white rounded-lg flex items-center gap-1 hover:bg-investor-dark"
>
<Plus className="w-3 h-3" /> Record Payment
</button>
)}
</div>
<div className="bg-slate-50 rounded-xl p-4">
@@ -938,24 +990,6 @@ export default function InvestmentDetailPage({ params }: { params: Promise<{ id:
<button onClick={() => setShowAssignBatteryModal(true)} className="px-3 py-1.5 text-xs bg-emerald-50 text-emerald-700 border border-emerald-200 rounded-lg flex items-center gap-1 hover:bg-emerald-100 transition-colors">
<Plus className="w-3 h-3" /> Assign Existing
</button>
<button onClick={() => {
setRegisterBatteryForm({
serialNumber: `SN-${new Date().getFullYear()}-${Math.floor(10000 + Math.random() * 90000)}`,
brand: 'BYD',
model: 'Li-Ion 60V50Ah',
type: 'lithium-ion',
capacity: 50,
voltage: 60,
purchasePrice: 45000,
deposit: 5000,
rentPrice: 150,
investorShare: 100,
investedAmount: investment.totalInvestment / 10
});
setShowRegisterBatteryModal(true);
}} className="px-3 py-1.5 text-xs bg-investor text-white rounded-lg flex items-center gap-1 hover:bg-investor-dark transition-colors">
<Plus className="w-3 h-3" /> Register & Assign New
</button>
</div>
</div>
{assignedBatteries.length > 0 ? (
@@ -1065,20 +1099,6 @@ export default function InvestmentDetailPage({ params }: { params: Promise<{ id:
<button onClick={() => setShowAddBikeModal(true)} className="px-3 py-1.5 text-xs bg-blue-50 text-blue-700 border border-blue-200 rounded-lg flex items-center gap-1 hover:bg-blue-100 transition-colors">
<Plus className="w-3 h-3" /> Assign Existing
</button>
<button onClick={() => {
setRegisterBikeForm({
plateNumber: `DHAKA-METRO-HA-${Math.floor(1000 + Math.random() * 9000)}`,
brand: 'Etron',
model: 'ET50',
currentRent: 150,
location: 'Banani',
purchasePrice: 200000,
rentalType: 'single_rent'
});
setShowRegisterBikeModal(true);
}} className="px-3 py-1.5 text-xs bg-investor text-white rounded-lg flex items-center gap-1 hover:bg-investor-dark transition-colors">
<Plus className="w-3 h-3" /> Register & Assign New
</button>
</div>
</div>
{assignedBikes.length > 0 ? (