diff --git a/src/app/investor/withdraw/page.tsx b/src/app/investor/withdraw/page.tsx index ebd6ee3..8814501 100644 --- a/src/app/investor/withdraw/page.tsx +++ b/src/app/investor/withdraw/page.tsx @@ -1,38 +1,98 @@ 'use client'; import { useState } from 'react'; -import { CreditCard, Wallet, ArrowUpRight, History, CheckCircle, Clock, Building2, Smartphone, AlertCircle, ChevronDown } from 'lucide-react'; -import { investors, transactions } from '@/data/mockData'; +import { CreditCard, Wallet, ArrowUpRight, History, CheckCircle, Clock, Building2, Smartphone, AlertCircle, ChevronDown, Settings, X, Bike } from 'lucide-react'; +import { investors, transactions, bikes } from '@/data/mockData'; import toast from 'react-hot-toast'; export default function InvestorWithdrawPage() { - const investor = investors[0]; // mock logged-in investor - const availableBalance = investor.totalEarnings - investor.totalWithdrawn - investor.withdrawalPending; + const investor = investors.find(i => i.id === 'inv1') || investors[0]; + const investorBikes = bikes.filter(b => b.investorId === investor.id); + const availableBalance = investor.totalEarnings - investor.totalWithdrawn - investor.pendingEarnings; const withdrawHistory = transactions.filter(t => t.investorId === investor.id && t.type === 'withdrawal').sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()); - const [amount, setAmount] = useState(''); - const [method, setMethod] = useState<'bank' | 'mobile'>('bank'); + const [showWithdrawModal, setShowWithdrawModal] = useState(false); + const [selectAll, setSelectAll] = useState(false); + const [selectedPlans, setSelectedPlans] = useState([]); + const [selectedBikes, setSelectedBikes] = useState([]); + const [paymentMethod, setPaymentMethod] = useState<'bank' | 'mobile'>('bank'); const [selectedAccount, setSelectedAccount] = useState(''); + const [showAutoWithdrawModal, setShowAutoWithdrawModal] = useState(false); + const [autoWithdrawEnabled, setAutoWithdrawEnabled] = useState(false); + const [autoWithdrawFreq, setAutoWithdrawFreq] = useState('as_per_request'); + const [autoWithdrawMin, setAutoWithdrawMin] = useState('1000'); + const [autoWithdrawAccount, setAutoWithdrawAccount] = useState(''); - const handleWithdraw = (e: React.FormEvent) => { - e.preventDefault(); - const withdrawAmount = Number(amount); - if (!withdrawAmount || withdrawAmount <= 0) { - toast.error('Please enter a valid amount'); - return; + const planColors: Record = { + silver: 'bg-slate-100 text-slate-700', + gold: 'bg-amber-100 text-amber-700', + platinum: 'bg-purple-100 text-purple-700', + diamond: 'bg-blue-100 text-blue-700', + }; + + const bikeStatusColors: Record = { + available: { bg: 'bg-blue-50', text: 'text-blue-600' }, + rented: { bg: 'bg-green-50', text: 'text-green-600' }, + maintenance: { bg: 'bg-amber-50', text: 'text-amber-600' }, + }; + + const assignedBikes = investorBikes; + + const calculatedAmount = selectAll + ? assignedBikes.reduce((sum: number, b: any) => sum + (b.totalEarnings || 0), 0) + : selectedBikes.reduce((sum: number, bikeId: string) => { + const bike = assignedBikes.find((b: any) => b.id === bikeId); + return sum + (bike?.totalEarnings || 0); + }, 0); + + const toggleSelectAll = (checked: boolean) => { + setSelectAll(checked); + if (checked) { + setSelectedPlans(investor.investments?.map((inv: any) => inv.id) || []); + setSelectedBikes(assignedBikes.map(b => b.id)); + } else { + setSelectedPlans([]); + setSelectedBikes([]); } - if (withdrawAmount > availableBalance) { - toast.error('Insufficient available balance'); - return; + }; + + const togglePlan = (planId: string, invBikes: any[]) => { + const isSelected = selectedPlans.includes(planId); + if (isSelected) { + setSelectedPlans(selectedPlans.filter(p => p !== planId)); + setSelectedBikes(selectedBikes.filter(b => !invBikes.find((ib: any) => ib.id === b))); + } else { + setSelectedPlans([...selectedPlans, planId]); + setSelectedBikes([...new Set([...selectedBikes, ...invBikes.map((b: any) => b.id)])]); } + setSelectAll(false); + }; + + const toggleBike = (bikeId: string) => { + setSelectedBikes(prev => prev.includes(bikeId) ? prev.filter(b => b !== bikeId) : [...prev, bikeId]); + setSelectAll(false); + }; + + const handleSubmitWithdraw = () => { if (!selectedAccount) { - toast.error('Please select an account to receive funds'); + toast.error('Please select a payment method'); return; } + if (selectedBikes.length === 0 && !selectAll) { + toast.error('Please select at least one bike or select all'); + return; + } + toast.success(`Withdrawal request for ৳${calculatedAmount.toLocaleString()} submitted successfully.`); + setSelectedPlans([]); + setSelectedBikes([]); + setSelectAll(false); + setShowWithdrawModal(false); + }; - toast.success(`Withdrawal request for ৳${withdrawAmount.toLocaleString()} submitted successfully.`); - setAmount(''); + const handleSaveAutoWithdraw = () => { + toast.success('Auto-withdraw settings saved!'); + setShowAutoWithdrawModal(false); }; return ( @@ -60,8 +120,8 @@ export default function InvestorWithdrawPage() {
-

Total Earnings

-

৳{investor.totalEarnings.toLocaleString()}

+

Pending Request

+

৳{investor.pendingEarnings.toLocaleString()}

Total Withdrawn

@@ -74,98 +134,26 @@ export default function InvestorWithdrawPage() {

Pending Requests

-

You currently have ৳{investor.withdrawalPending.toLocaleString()} in pending withdrawals. Processing takes 1-3 business days.

+

You currently have ৳{investor.pendingEarnings.toLocaleString()} in pending withdrawals. Processing takes 1-3 business days.

- {/* Withdrawal Form */} -
-
-

- Create Withdrawal Request -

- -
-
- -
- - setAmount(e.target.value)} - placeholder="0.00" - className="w-full pl-8 pr-4 py-3 border border-slate-200 rounded-xl text-lg font-semibold focus:outline-none focus:border-investor focus:ring-1 focus:ring-investor transition-all" - /> - -
-
- -
- -
-
setMethod('bank')} - className={`p-4 rounded-xl border-2 cursor-pointer transition-all ${method === 'bank' ? 'border-investor bg-investor/5' : 'border-slate-100 bg-white hover:border-slate-200'}`} - > - -

Bank Transfer

-

1-3 business days

-
-
setMethod('mobile')} - className={`p-4 rounded-xl border-2 cursor-pointer transition-all ${method === 'mobile' ? 'border-investor bg-investor/5' : 'border-slate-100 bg-white hover:border-slate-200'}`} - > - -

Mobile Banking

-

Instant transfer

-
-
-
- -
- -
- - -
-
- -
- -
-
-
+ {/* Right Side */} +
+ + {/* Withdraw Button */} +
@@ -198,8 +186,8 @@ export default function InvestorWithdrawPage() { ৳{t.amount.toLocaleString()} {t.status === 'completed' && } {t.status === 'pending' && } @@ -219,6 +207,290 @@ export default function InvestorWithdrawPage() { + + {/* Withdrawal Request Modal */} + {showWithdrawModal && ( +
+
+
+

Create Withdrawal Request

+ +
+ +
+ {/* Balance Cards */} +
+
+

Available Balance

+

৳{availableBalance.toLocaleString()}

+
+
+

Pending Request

+

৳{investor.pendingEarnings.toLocaleString()}

+
+
+

Total Withdrawn

+

৳{investor.totalWithdrawn.toLocaleString()}

+
+
+ + {/* Select Investment Plans & Bikes */} +
+

Select Investment Plans & Bikes

+
+ {/* Select All */} +
+ toggleSelectAll(e.target.checked)} + className="w-4 h-4 text-investor rounded" + /> + +
+ + {/* Investment Plans with Bikes */} +
+
+

Investment Plans

+
+
+ {investor.investments?.map((inv: any) => { + const invBikes = assignedBikes.filter((b: any) => b.investmentId === inv.id); + const invEarnings = invBikes.reduce((sum: number, b: any) => sum + (b.totalEarnings || 0), 0); + return ( +
+
+ togglePlan(inv.id, invBikes)} + className="w-4 h-4 text-investor rounded" + /> + +
+ {!selectAll && invBikes.length > 0 && ( +
+ {invBikes.map((bike: any) => { + const statusStyle = bikeStatusColors[bike.status] || bikeStatusColors.available; + return ( +
+ toggleBike(bike.id)} + className="w-3 h-3 text-investor rounded" + /> + + ৳{bike.totalEarnings?.toLocaleString() || 0} +
+ ); + })} +
+ )} +
+ ); + })} +
+
+
+
+ + {/* Withdrawal Amount */} +
+

Withdrawal Amount

+
+
+ Calculated Amount + + {selectAll ? 'All Selected' : `${selectedBikes.length} bikes`} + +
+

+ ৳{calculatedAmount.toLocaleString()} +

+

+ Based on {selectAll ? 'all' : selectedBikes.length} selected bike(s) earnings +

+
+
+ + {/* Payment Method */} +
+

Payment Method

+
+ {(investor as any).bankAccounts?.map((account: any) => ( +
{ setPaymentMethod('bank'); setSelectedAccount(account.id); }} + className={`p-4 rounded-lg border cursor-pointer transition-all ${selectedAccount === account.id ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`} + > +
+
+ +
+
+

{account.bankName}

+ {account.isPrimary && Primary} +
+
+

{account.accountNumber}

+
+ ))} +
+ {(investor as any).mobileBanking && ( +
{ setPaymentMethod('mobile'); setSelectedAccount('mobile'); }} + className={`mt-3 p-4 rounded-lg border cursor-pointer transition-all ${selectedAccount === 'mobile' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`} + > +
+
+ +
+
+

{(investor as any).mobileBanking}

+

{(investor as any).mobileBankingNumber}

+
+
+
+ )} +
+
+ +
+ +
+ + +
+
+
+
+ )} + + {/* Auto-Withdraw Modal */} + {showAutoWithdrawModal && ( +
+
+
+

Auto-Withdraw Settings

+ +
+
+
+ +
+ + Automatically withdraw earnings +
+
+ +
+ + +
+ +
+ +
+ + setAutoWithdrawMin(e.target.value)} + className="flex-1 px-3 py-2 border border-slate-200 rounded-lg text-sm" + placeholder="1000" + /> +
+

Minimum balance required for auto-withdrawal

+
+ +
+ +
+ {(investor as any).bankAccounts?.map((account: any) => ( +
+ setAutoWithdrawAccount(account.id)} + className="text-investor" + /> +
+

{account.bankName}

+

{account.accountNumber}

+
+ {account.isPrimary && Primary} +
+ ))} + {(investor as any).mobileBanking && ( +
+ setAutoWithdrawAccount('mobile')} + className="text-investor" + /> +
+

{(investor as any).mobileBanking}

+

{(investor as any).mobileBankingNumber}

+
+ Primary +
+ )} +
+
+
+
+ + +
+
+
+ )} ); } \ No newline at end of file