feat: implement radio-based payment selection UI and rename paymentOption to paymentType

This commit is contained in:
sazzadulalambd
2026-05-15 12:25:24 +06:00
parent cab01a25ac
commit bb1d4628ee

View File

@@ -134,7 +134,7 @@ export default function InvestorDetailPage() {
selectedBikeIds: [] as string[],
totalInvestment: 0,
paidAmount: 0,
paymentOption: 'full' as 'full' | 'partial',
paymentType: 'full' as 'full' | 'partial',
monthlyReturn: 0,
expectedRoi: 15,
startDate: new Date().toISOString().split('T')[0],
@@ -233,7 +233,7 @@ export default function InvestorDetailPage() {
selectedBikeIds: [],
totalInvestment: 0,
paidAmount: 0,
paymentOption: 'full',
paymentType: 'full',
monthlyReturn: 0,
expectedRoi: 15,
startDate: new Date().toISOString().split('T')[0],
@@ -2234,7 +2234,7 @@ export default function InvestorDetailPage() {
planType: plan.tier.toLowerCase() as any,
totalInvestment: plan.evBasePrice * plan.minQuantity,
paidAmount: plan.evBasePrice * plan.minQuantity,
paymentOption: 'full',
paymentType: 'full',
monthlyReturn: 0
});
}}
@@ -2301,7 +2301,7 @@ export default function InvestorDetailPage() {
setNewInvestment({
...newInvestment,
totalInvestment: val,
paidAmount: newInvestment.paymentOption === 'full' ? val : Math.max(val * 0.5, newInvestment.paidAmount)
paidAmount: newInvestment.paymentType === 'full' ? val : Math.max(val * 0.5, newInvestment.paidAmount)
});
}}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-yellow-50"
@@ -2328,6 +2328,8 @@ export default function InvestorDetailPage() {
</div>
</div>
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4">
<h4 className="text-sm font-semibold text-amber-800 mb-3 flex items-center gap-2">
<TrendingUp className="w-4 h-4" />
@@ -2370,6 +2372,61 @@ export default function InvestorDetailPage() {
/>
</div>
</div>
<div className="bg-slate-50 rounded-xl p-4 border border-slate-200">
<h4 className="text-sm font-semibold text-slate-800 mb-3 flex items-center gap-2">
<CreditCard className="w-4 h-4 text-investor" /> Payment Options
</h4>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 mb-4">
<label className={`flex items-center gap-3 p-3 rounded-lg border-2 cursor-pointer transition-all ${newInvestment.paymentType === 'full' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`}>
<input
type="radio"
name="paymentType"
value="full"
checked={newInvestment.paymentType === 'full'}
onChange={() => setNewInvestment({ ...newInvestment, paymentType: 'full', paidAmount: newInvestment.totalInvestment })}
className="w-4 h-4 text-investor"
/>
<div className="flex-1">
<p className="font-medium text-slate-800 text-sm">Full Payment</p>
<p className="text-xs text-slate-500">Pay total amount at once</p>
</div>
<span className="text-lg font-bold text-green-600">{newInvestment.totalInvestment.toLocaleString()}</span>
</label>
<label className={`flex items-center gap-3 p-3 rounded-lg border-2 cursor-pointer transition-all ${newInvestment.paymentType === 'partial' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`}>
<input
type="radio"
name="paymentType"
value="partial"
checked={newInvestment.paymentType === 'partial'}
onChange={() => setNewInvestment({ ...newInvestment, paymentType: 'partial', paidAmount: Math.floor(newInvestment.totalInvestment * 0.5) })}
className="w-4 h-4 text-investor"
/>
<div className="flex-1">
<p className="font-medium text-slate-800 text-sm">Partial Payment</p>
<p className="text-xs text-slate-500">Pay initial amount (50% min)</p>
</div>
<span className="text-sm font-bold text-amber-600">Min {Math.floor(newInvestment.totalInvestment * 0.5).toLocaleString()}</span>
</label>
</div>
{newInvestment.paymentType === 'partial' && (
<div className="border-t border-slate-200 pt-4 mt-4">
<label className="text-sm font-medium text-slate-600 mb-2 block">Initial Payment () *</label>
<input
type="number"
value={newInvestment.paidAmount}
onChange={(e) => {
const val = Number(e.target.value);
if (val >= newInvestment.totalInvestment * 0.5 && val <= newInvestment.totalInvestment) {
setNewInvestment({ ...newInvestment, paidAmount: val });
}
}}
className="w-full px-3 py-2 border border-investor rounded-lg text-sm bg-white"
/>
<p className="text-xs text-slate-500 mt-2">Balance: {(newInvestment.totalInvestment - newInvestment.paidAmount).toLocaleString()}</p>
</div>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<div>
@@ -2447,54 +2504,7 @@ export default function InvestorDetailPage() {
</div>
</div>
<div className="space-y-3">
<label className="text-sm font-medium text-slate-600 block">Payment Options</label>
<div className="grid grid-cols-2 gap-4">
<button
onClick={() => setNewInvestment({ ...newInvestment, paymentOption: 'full', paidAmount: newInvestment.totalInvestment })}
className={`p-4 rounded-xl border-2 text-left transition-all ${newInvestment.paymentOption === 'full' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`}
>
<div className="flex items-center justify-between mb-1">
<p className="font-bold text-slate-800">Full Payment</p>
{newInvestment.paymentOption === 'full' && <CheckCircle className="w-4 h-4 text-investor" />}
</div>
<p className="text-xs text-slate-500 mb-2">Pay total amount at once</p>
<p className="text-lg font-bold text-investor">{newInvestment.totalInvestment.toLocaleString()}</p>
</button>
<button
onClick={() => setNewInvestment({ ...newInvestment, paymentOption: 'partial', paidAmount: Math.max(newInvestment.totalInvestment * 0.5, newInvestment.paidAmount) })}
className={`p-4 rounded-xl border-2 text-left transition-all ${newInvestment.paymentOption === 'partial' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`}
>
<div className="flex items-center justify-between mb-1">
<p className="font-bold text-slate-800">Partial Payment</p>
{newInvestment.paymentOption === 'partial' && <CheckCircle className="w-4 h-4 text-investor" />}
</div>
<p className="text-xs text-slate-500 mb-2">Pay initial amount (50% min)</p>
<p className="text-lg font-bold text-slate-800">Min {(newInvestment.totalInvestment * 0.5).toLocaleString()}</p>
</button>
</div>
{newInvestment.paymentOption === 'partial' && (
<div className="bg-slate-50 p-4 rounded-lg border border-slate-200 mt-3 animate-in fade-in slide-in-from-top-2">
<label className="text-sm font-medium text-slate-700 mb-2 block">Enter Initial Payment Amount ()</label>
<div className="relative">
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"></span>
<input
type="number"
value={newInvestment.paidAmount}
min={newInvestment.totalInvestment * 0.5}
max={newInvestment.totalInvestment}
onChange={(e) => setNewInvestment({ ...newInvestment, paidAmount: Number(e.target.value) })}
className="w-full pl-8 pr-4 py-2 border border-slate-200 rounded-lg focus:ring-2 focus:ring-investor outline-none text-sm"
/>
</div>
<p className="text-xs text-slate-400 mt-2 flex items-center gap-1">
<AlertTriangle className="w-3 h-3 text-amber-500" /> Remaining {(newInvestment.totalInvestment - newInvestment.paidAmount).toLocaleString()} will be recorded as pending.
</p>
</div>
)}
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">