diff --git a/src/app/admin/investors/[id]/page copy.tsx b/src/app/admin/investors/[id]/page copy.tsx deleted file mode 100644 index ed6ffeb..0000000 --- a/src/app/admin/investors/[id]/page copy.tsx +++ /dev/null @@ -1,1535 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import Link from 'next/link'; -import { useParams } from 'next/navigation'; -import { investors as initialInvestors, bikes as initialBikes, transactions as initialTransactions } from '@/data/mockData'; -import type { Investor } from '@/data/mockData'; -import { - ArrowLeft, Wallet, TrendingUp, Banknote, Calendar, Phone, Mail, MapPin, Edit, Trash2, Plus, X, Bike, - User, FileText, CreditCard, DollarSign, Clock, ChevronDown, ExternalLink, Download, Upload, - AlertTriangle, Shield, Star, CheckCircle, XCircle, Search, Filter, BookOpen, ArrowRight, Printer -} from 'lucide-react'; - -const statusColors: Record = { - active: 'bg-green-100 text-green-700', - pending: 'bg-amber-100 text-amber-700', - inactive: 'bg-slate-100 text-slate-500', - suspended: 'bg-red-100 text-red-700', -}; - -const planColors: Record = { - silver: 'bg-slate-200 text-slate-700', - gold: 'bg-yellow-100 text-yellow-700', - platinum: 'bg-purple-100 text-purple-700', - diamond: 'bg-blue-100 text-blue-700', -}; - -const kycColors: Record = { - verified: 'bg-green-100 text-green-700', - pending: 'bg-amber-100 text-amber-700', - rejected: 'bg-red-100 text-red-700', - not_submitted: 'bg-slate-100 text-slate-500', -}; - -const bikeStatusColors: Record = { - available: 'bg-blue-100 text-blue-700', - rented: 'bg-green-100 text-green-700', - maintenance: 'bg-amber-100 text-amber-700', - retired: 'bg-slate-100 text-slate-500', -}; - -export default function InvestorDetailPage() { - const params = useParams(); - const investorId = params.id as string; - - const [investors] = useState(initialInvestors); - const investor = investors.find(i => i.id === investorId); - - const assignedBikes = initialBikes.filter(b => b.investorId === investorId); - // Investor transactions are filtered below - - const [activeTab, setActiveTab] = useState('overview'); - const [showEditModal, setShowEditModal] = useState(false); - const [showAssignBikeModal, setShowAssignBikeModal] = useState(false); - const [selectedBikeId, setSelectedBikeId] = useState(''); - const [showCreateInvestmentModal, setShowCreateInvestmentModal] = useState(false); - const [showInvoiceModal, setShowInvoiceModal] = useState(false); - const [showJournalModal, setShowJournalModal] = useState(false); - const [selectedInvoice, setSelectedInvoice] = useState(null); - const [investorJournals, setInvestorJournals] = useState([]); - const [showBankModal, setShowBankModal] = useState(false); - const [showMobileBankingModal, setShowMobileBankingModal] = useState(false); - const [showTaxModal, setShowTaxModal] = useState(false); - const [showDocModal, setShowDocModal] = useState(false); - const [editingBank, setEditingBank] = useState({ bankName: '', bankAccountName: '', bankAccountNumber: '', bankBranch: '', bankRouting: '' }); - const [editingMobileBanking, setEditingMobileBanking] = useState({ provider: '', number: '', isPrimary: false }); - const [editingTax, setEditingTax] = useState({ tinNumber: '', passportNumber: '' }); - const [newDoc, setNewDoc] = useState({ type: 'nid', number: '', url: '' }); - const [editingMobileIndex, setEditingMobileIndex] = useState(null); - const investorTransactions = initialTransactions.filter(t => t.investorId === investorId); - const [newInvestment, setNewInvestment] = useState({ - planName: '', - planType: 'gold' as 'silver' | 'gold' | 'platinum' | 'diamond', - selectedBikeIds: [] as string[], - totalInvestment: 0, - monthlyReturn: 0, - expectedRoi: 15, - startDate: new Date().toISOString().split('T')[0], - endDate: '', - paymentMethod: 'bank' as 'bank' | 'mobile' | 'cash' | 'cheque', - transactionReference: '', - notes: '' - }); - - if (!investor) { - return ( -
-
-

Investor Not Found

-

The investor you're looking for doesn't exist.

- - Back to Investors - -
-
- ); - } - - const availableBikesForAssignment = initialBikes.filter(b => !b.investorId && b.status === 'available'); - - const handleAssignBike = () => { - alert('Bike assignment functionality - would update bike investorId here'); - setShowAssignBikeModal(false); - setSelectedBikeId(''); - }; - - const handleCreateInvestment = () => { - const invId = `INV-${Date.now()}`; - const year = new Date().getFullYear(); - const transactionRef = newInvestment.transactionReference || `INV/${year}/${String(investor.investments.length + 1).padStart(4, '0')}`; - - const getDebitAccount = (method: string) => { - switch (method) { - case 'bank': return { code: '1200', name: 'Bank - City Bank' }; - case 'cash': return { code: '1100', name: 'Cash in Hand' }; - case 'mobile': return { code: '1300', name: 'bKash Business' }; - case 'cheque': return { code: '1410', name: 'Cheque Receivable' }; - default: return { code: '1200', name: 'Bank - City Bank' }; - } - }; - - const debitAccount = getDebitAccount(newInvestment.paymentMethod); - - const journalEntry = { - entryId: `JE-${Date.now()}`, - date: newInvestment.startDate, - reference: transactionRef, - description: `${investor.name} - ${newInvestment.planName}`, - entries: [ - { accountCode: debitAccount.code, accountName: debitAccount.name, debit: newInvestment.totalInvestment, credit: 0 }, - { accountCode: '2200', accountName: 'Investor Liabilities', debit: 0, credit: newInvestment.totalInvestment }, - ], - isAuto: true, - sourceType: 'investor_funding', - createdAt: new Date().toISOString(), - type: 'investment', - amount: newInvestment.totalInvestment, - paymentMethod: newInvestment.paymentMethod - }; - - setInvestorJournals([journalEntry, ...investorJournals]); - - console.log('Creating Investment:', { - id: invId, - investorId: investor.id, - ...newInvestment, - actualEarnings: 0, - status: 'active' as const, - transactionId: transactionRef, - createdAt: new Date().toISOString() - }); - - alert(`Investment created successfully! - -Investor: ${investor.name} -Investment ID: ${invId} -Transaction Ref: ${transactionRef} -Amount: ৳${newInvestment.totalInvestment.toLocaleString()} - -Accounting Entry Created (Auto-Journal): -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -Date: ${newInvestment.startDate} -Ref: ${transactionRef} -Description: ${investor.name} - ${newInvestment.planName} - -Debit (Dr): ${debitAccount.name} ৳${newInvestment.totalInvestment.toLocaleString()} -Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleString()} -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`); - setShowCreateInvestmentModal(false); - setNewInvestment({ - planName: '', - planType: 'gold', - selectedBikeIds: [], - totalInvestment: 0, - monthlyReturn: 0, - expectedRoi: 15, - startDate: new Date().toISOString().split('T')[0], - endDate: '', - paymentMethod: 'bank', - transactionReference: '', - notes: '' - }); - }; - - return ( -
-
-
- - - -
-

{investor.name}

-

{investor.id} • {investor.email}

-
-
-
- - -
-
- -
- - {investor.status} - - {investor.investments && investor.investments.length > 0 && ( - - {investor.investments.length} Investment{investor.investments.length > 1 ? 's' : ''} - - )} - - KYC {investor.kycStatus} - - - Risk: {investor.riskLevel} - -
- -
-
-
-
- -
-
-

৳{investor.totalInvested.toLocaleString()}

-

Total Invested

-
-
-
-
-
-
- -
-
-

৳{investor.totalEarnings.toLocaleString()}

-

Total Earnings

-
-
-
-
-
-
- -
-
-

{investor.activeBikes}

-

Active Bikes

-
-
-
-
-
-
- -
-
-

{investor.roi}%

-

ROI

-
-
-
-
- -
-
- - - - - - -
- -
- {activeTab === 'overview' && ( -
-
-
-

Personal Information

-
-
- -
-

Full Name

-

{investor.name}

-
-
-
- -
-

Phone

-

{investor.phone}

-
-
-
- -
-

Email

-

{investor.email}

-
-
-
- -
-

Address

-

{investor.address}

-
-
- {investor.dateOfBirth && ( -
- -
-

Date of Birth

-

{investor.dateOfBirth}

-
-
- )} - {investor.nidNumber && ( -
- -
-

NID Number

-

{investor.nidNumber}

-
-
- )} -
-
- -
-

Emergency Contact

-
- {investor.emergencyContactName && ( -
- -
-

Contact

-

{investor.emergencyContactName}

-

{investor.emergencyContactRelation} • {investor.emergencyContactPhone}

-
-
- )} -
- -

Investment Details

-
-
- -
-

Total Investments

-

- {investor.investments?.length || 0} active investments -

-
-
-
- -
-

Overall Status

-

{investor.status}

-
-
- {investor.referralCode && ( -
- -
-

Referral Code

-

{investor.referralCode}

-

Referrals: {investor.totalReferrals} • Earnings: ৳{investor.referralEarnings}

-
-
- )} -
-
-
- - {investor.notes && ( -
-

Notes

-

{investor.notes}

-
- )} -
- )} - - {activeTab === 'bikes' && ( -
-
-

Assigned Bikes

- -
-
- {assignedBikes.map(bike => ( -
-
-
-
- -
-
-

{bike.model}

-

{bike.brand}

-
-
- - {bike.status} - -
-
-
- Plate - {bike.plateNumber} -
-
- Location - {bike.location} -
-
- Battery - 50 ? 'text-green-600' : bike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'}`}>{bike.batteryLevel}% -
-
- Purchase Price - ৳{bike.purchasePrice?.toLocaleString() || 0} -
-
- Total Earnings - ৳{bike.totalEarnings?.toLocaleString() || 0} -
-
-
- ))} - {assignedBikes.length === 0 && ( -
- -

No bikes assigned yet

-
- )} -
-
- )} - - {activeTab === 'investments' && ( -
-
-

EV Investment Plans

- -
-
- {investor.investments?.map((inv) => ( -
-
-
-

{inv.planName}

-

{inv.planType} Plan

-
- - {inv.status} - -
-
-
-

Investment

-

৳{inv.totalInvestment.toLocaleString()}

-
-
-

Monthly Return

-

৳{inv.monthlyReturn.toLocaleString()}

-
-
-

Expected ROI

-

{inv.expectedRoi}%

-
-
-

Actual Earned

-

৳{inv.actualEarnings.toLocaleString()}

-
-
-
- {inv.startDate} to {inv.endDate || 'Ongoing'} - {inv.paymentMethod} -
-
- ))} - {(!investor.investments || investor.investments.length === 0) && ( -
- -

No investments yet

- -
- )} -
-
- )} - - {activeTab === 'financial' && ( -
-
-
-
-

Bank Details

- -
-
- {investor.bankName ? ( - <> -
- -
-

Bank

-

{investor.bankName}

-

{investor.bankBranch}

-
-
-
- -
-

Account

-

{investor.bankAccountName}

-

{investor.bankAccountNumber}

- {investor.bankRouting &&

Routing: {investor.bankRouting}

} -
-
- - ) : ( -
- -

No bank details added

-
- )} -
-
- -
-
-

Mobile Banking

- -
-
- {investor.mobileBanking ? ( -
- -
-

Primary

-

{investor.mobileBanking}

-

{investor.mobileBankingNumber}

-
- -
- ) : null} - {investor.additionalMobileBanking?.map((mb, idx) => ( -
- -
-

{mb.provider}

-

{mb.number}

-
- {mb.verified ? ( - Verified - ) : ( - Pending - )} - - -
- ))} - {(!investor.mobileBanking && (!investor.additionalMobileBanking || investor.additionalMobileBanking.length === 0)) && ( -
- -

No mobile banking added

-
- )} -
- -
-

Tax Information

- -
-
- {investor.tinNumber || investor.passportNumber ? ( - <> - {investor.tinNumber && ( -
- -
-

TIN

-

{investor.tinNumber}

-
-
- )} - {investor.passportNumber && ( -
- -
-

Passport

-

{investor.passportNumber}

-
-
- )} - - ) : ( -
- -

No tax info added

-
- )} -
-
-
- -
-

Investment Summary

-
-
-

Total Invested

-

৳{investor.totalInvested.toLocaleString()}

-
-
-

Total Earnings

-

৳{investor.totalEarnings.toLocaleString()}

-
-
-

Pending Earnings

-

৳{investor.pendingEarnings.toLocaleString()}

-
-
-

Total Withdrawn

-

৳{investor.totalWithdrawn.toLocaleString()}

-
-
-
-
- )} - - {activeTab === 'transactions' && ( -
-
-

All Transactions

-
- - -
-
- -
-

Pending Withdrawals

-
- {investorTransactions.filter(t => t.type === 'withdrawal' && t.status === 'pending').map(tx => ( -
-
-
- -
-
-

{tx.description}

-

Ref: {tx.referenceNumber || tx.id} • {tx.createdAt}

-
-
-
-

-৳{tx.amount.toLocaleString()}

- - Pending - -
-
- ))} - {investorTransactions.filter(t => t.type === 'withdrawal' && t.status === 'pending').length === 0 && ( -
-

No pending withdrawals

-
- )} -
-
- -
-

Transaction History

-
- {investorTransactions.map(tx => ( -
-
-
- -
-
-

{tx.description}

-
-

{tx.createdAt}

- {tx.referenceNumber && ( - - )} -
-
-
-
-

- {tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' || tx.type === 'referral_bonus' ? '+' : tx.type === 'withdrawal' || tx.type === 'penalty' || tx.type === 'adjustment' ? '-' : '+'}৳{tx.amount.toLocaleString()} -

- - {tx.status} - -
-
- ))} - {investorTransactions.length === 0 && ( -
- -

No transactions yet

-
- )} -
-
-
- )} - - {activeTab === 'documents' && ( -
-
-

KYC Documents

- -
- -
- {investor.kycDocuments?.map((doc, idx) => ( -
-
-
- -
-
-

{doc.type.replace('_', ' ')}

-

{doc.number || 'No document number'} • Uploaded: {doc.uploadedAt || 'N/A'}

-
-
-
- {doc.verified ? ( - - Verified - - ) : ( - - Pending Review - - )} - - -
-
- ))} - {(!investor.kycDocuments || investor.kycDocuments.length === 0) && ( -
- -

No documents uploaded yet

-
- )} -
- -
-

KYC Status: {investor.kycStatus.toUpperCase()}

-

- {investor.kycStatus === 'verified' - ? 'All documents have been verified. Investor is fully verified.' - : investor.kycStatus === 'pending' - ? 'Documents are under review. Verification typically takes 24-48 hours.' - : 'Please upload required documents for verification.'} -

-
-
- )} -
-
- - {showAssignBikeModal && ( -
-
-
-

Assign Bike to Investor

- -
- -
- - -
- -
- - -
-
-
- )} - - {showCreateInvestmentModal && ( -
-
-
-

Create New Investment

- -
- -
-
-
- - setNewInvestment({ ...newInvestment, planName: e.target.value })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - placeholder="e.g., Gold EV Fleet 2024" - /> -
-
- - -
-
- -
- -
- {availableBikesForAssignment.map(bike => ( - - ))} -
-
- -
-
- - setNewInvestment({ ...newInvestment, totalInvestment: Number(e.target.value), monthlyReturn: Math.round(Number(e.target.value) * newInvestment.expectedRoi / 100 / 12) })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - placeholder="0" - /> -
-
- - setNewInvestment({ ...newInvestment, monthlyReturn: Number(e.target.value) })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - placeholder="0" - /> -
-
- - setNewInvestment({ ...newInvestment, expectedRoi: Number(e.target.value) })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - placeholder="15" - /> -
-
- -
-
- - setNewInvestment({ ...newInvestment, startDate: e.target.value })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - /> -
-
- - setNewInvestment({ ...newInvestment, endDate: e.target.value })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - /> -
-
- -
-
- - -
-
- - setNewInvestment({ ...newInvestment, transactionReference: e.target.value })} - className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" - placeholder="Auto-generated if empty" - /> -
-
- -
- -