Files
JML/src/app/admin/investors/[id]/page.tsx

4572 lines
251 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { useParams, useRouter } from 'next/navigation';
import { investors as initialInvestors, bikes as initialBikes, transactions as initialTransactions, rentalPayments as initialRentalPayments } from '@/data/mockData';
import type { Investor } from '@/data/mockData';
import toast from 'react-hot-toast';
import {
ArrowLeft, Wallet, TrendingUp, Banknote, Calendar, Phone, Mail, MapPin, Edit, Trash2, Plus, X, Bike, Battery, Unlink, Eye, ShieldAlert, Cpu,
User, FileText, CreditCard, DollarSign, Clock, ChevronDown, ExternalLink, Download, Upload,
AlertTriangle, Shield, Star, CheckCircle, XCircle, Search, Filter, BookOpen, ArrowRight, Printer,
UserCircle, Home, Briefcase, Heart, PhoneCall, PhoneOutgoing, MessageSquare, Save,
ShieldCheck, Building2, Users, Check, AlertOctagon, Activity, Award, Camera, History, Settings
} from 'lucide-react';
import AssignBikeModal from '../components/AssignBikeModal';
import AssignBatteryModal from '../components/AssignBatteryModal';
import UnassignConfirmModal from '../components/UnassignConfirmModal';
const statusColors: Record<string, string> = {
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<string, string> = {
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<string, string> = {
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<string, string> = {
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',
};
function SectionCard({ title, icon: Icon, children, headerBg = 'bg-slate-50', headerBorder = 'border-slate-100', editKey, editingSection, setEditingSection, onEdit, editForm, setEditForm }: { title: string; icon: any; children: React.ReactNode; headerBg?: string; headerBorder?: string; editKey?: string; editingSection?: string | null; setEditingSection?: (s: string | null) => void; onEdit?: () => void; editForm?: any; setEditForm?: any }) {
return (
<div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
<div className={`${headerBg} px-5 py-4 border-b ${headerBorder} flex items-center justify-between`}>
<div className="flex items-center gap-2">
<Icon className="w-5 h-5 text-slate-600" />
<h3 className="font-semibold text-slate-800">{title}</h3>
</div>
{editKey && setEditingSection ? (
editingSection !== editKey ? (
<button onClick={() => { setEditingSection(editKey); onEdit?.(); }} className="p-1.5 hover:bg-white rounded-lg transition-colors">
<Edit className="w-4 h-4 text-slate-500" />
</button>
) : (
<div className="flex gap-1">
<button onClick={() => { toast.success('Updated'); setEditingSection(null); }} className="px-3 py-1.5 bg-green-600 text-white rounded-lg text-xs font-medium hover:bg-green-700">Save</button>
<button onClick={() => setEditingSection(null)} className="px-3 py-1.5 border border-slate-200 text-slate-600 rounded-lg text-xs font-medium hover:bg-slate-50">Cancel</button>
</div>
)
) : null}
</div>
<div className="p-4">
{children}
</div>
</div>
);
}
export default function InvestorDetailPage() {
const params = useParams();
const router = useRouter();
const investorId = params.id as string;
const [investors, setInvestors] = useState<Investor[]>(() => {
if (typeof window !== 'undefined') {
const stored = localStorage.getItem('jaiben_investors');
if (stored) {
try {
return JSON.parse(stored);
} catch (e) {
console.error(e);
}
}
}
return initialInvestors;
});
const investor = investors.find(i => i.id === investorId);
useEffect(() => {
if (typeof window !== 'undefined') {
localStorage.setItem('jaiben_investors', JSON.stringify(investors));
}
}, [investors]);
const [bikes, setBikes] = useState<any[]>(() => {
if (typeof window !== 'undefined') {
const stored = localStorage.getItem('jaiben_bikes');
if (stored) {
try {
return JSON.parse(stored);
} catch (e) {
console.error(e);
}
}
}
return initialBikes;
});
useEffect(() => {
if (typeof window !== 'undefined') {
localStorage.setItem('jaiben_bikes', JSON.stringify(bikes));
}
}, [bikes]);
const assignedBikes = bikes.filter(b => b.investorId === investorId);
const [settings, setSettings] = useState<any>(null);
useEffect(() => {
if (typeof window !== 'undefined') {
const stored = localStorage.getItem('companySettings');
if (stored) {
try {
setSettings(JSON.parse(stored));
} catch (e) {
console.error(e);
}
}
}
}, []);
// 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 [selectedBikeIds, setSelectedBikeIds] = useState<string[]>([]);
const [selectedBikePlanId, setSelectedBikePlanId] = useState('');
const getPlanTargetAssetCount = (plan: any) => {
if (plan.assetType === 'battery' || plan.planName?.toLowerCase().includes('battery')) {
if (plan.id === 'ip3') return 2;
const nameLower = plan.planName?.toLowerCase() || '';
if (nameLower.includes('10')) return 10;
if (nameLower.includes('5')) return 5;
if (nameLower.includes('1')) return 1;
return 1;
} else {
if (plan.id === 'ip1') return 1;
if (plan.id === 'ip2') return 1;
const nameLower = plan.planName?.toLowerCase() || '';
if (nameLower.includes('10')) return 10;
if (nameLower.includes('5')) return 5;
if (nameLower.includes('1')) return 1;
return 1;
}
};
const [showRegisterBikeModal, setShowRegisterBikeModal] = useState(false);
const [unassignConfirmModal, setUnassignConfirmModal] = useState<{
show: boolean;
type: 'bike' | 'battery';
id: string;
name: string;
details: string;
}>({
show: false,
type: 'bike',
id: '',
name: '',
details: ''
});
const [registerBikeForm, setRegisterBikeForm] = useState({
plateNumber: '',
brand: 'Etron',
model: 'ET50',
currentRent: 150,
location: 'Banani',
purchasePrice: 200000,
rentalType: 'single_rent',
investmentId: ''
});
const [showCreateInvestmentModal, setShowCreateInvestmentModal] = useState(false);
const [showInvestmentSuccessModal, setShowInvestmentSuccessModal] = useState(false);
const [lastCreatedInvestment, setLastCreatedInvestment] = useState<any>(null);
const [showInvoiceModal, setShowInvoiceModal] = useState(false);
const [showJournalModal, setShowJournalModal] = useState(false);
const [selectedInvoice, setSelectedInvoice] = useState<any>(null);
const [investorJournals, setInvestorJournals] = useState<any[]>([]);
const [showBankModal, setShowBankModal] = useState(false);
const [editingSection, setEditingSection] = useState<string | null>(null);
const [editForm, setEditForm] = useState<any>({});
const [showMobileBankingModal, setShowMobileBankingModal] = useState(false);
const [showTaxModal, setShowTaxModal] = useState(false);
const [showDocModal, setShowDocModal] = useState(false);
const [editingBankAccount, setEditingBankAccount] = useState<any>({ id: '', bankName: '', accountName: '', accountNumber: '', branch: '', routing: '', isPrimary: false });
const [bankSaveSuccess, setBankSaveSuccess] = useState(false);
const [showDeleteBankModal, setShowDeleteBankModal] = useState(false);
const [bankErrors, setBankErrors] = useState<{ bankName?: string; accountName?: string; accountNumber?: string }>({});
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<number | null>(null);
const [batteries, setBatteries] = useState<any[]>(() => {
if (typeof window !== 'undefined') {
const stored = localStorage.getItem('jaiben_batteries');
if (stored) {
try {
return JSON.parse(stored);
} catch (e) {
console.error(e);
}
}
}
return [
{
id: 'BAT-001',
serialNumber: 'SN-2024-00001',
brand: 'EVE Energy',
model: 'Li-Ion 60V50Ah',
type: 'lithium-ion',
capacity: 50,
voltage: 60,
purchaseDate: '2024-01-15',
purchasePrice: 45000,
deposit: 5000,
rentPrice: 150,
investorId: investorId,
investorName: 'Md. Hasan Mahmud',
investorSharePercentage: 100,
investedAmount: 45000,
investmentId: 'ip3',
status: 'in-use',
currentSoc: 78,
health: 95,
cycleCount: 156
},
{
id: 'BAT-002',
serialNumber: 'SN-2024-00002',
brand: 'CATL',
model: 'LiFePO4 48V40Ah',
type: 'lifepo4',
capacity: 40,
voltage: 48,
purchaseDate: '2024-02-10',
purchasePrice: 38000,
deposit: 4000,
rentPrice: 120,
investorId: investorId,
investorName: 'Md. Hasan Mahmud',
investorSharePercentage: 100,
investedAmount: 38000,
investmentId: 'ip3',
status: 'available',
currentSoc: 92,
health: 98,
cycleCount: 45
},
{
id: 'BAT-005',
serialNumber: 'SN-2024-00005',
brand: 'BYD',
model: 'Li-Ion 60V50Ah',
type: 'lithium-ion',
capacity: 50,
voltage: 60,
purchaseDate: '2024-02-15',
purchasePrice: 45000,
deposit: 5000,
rentPrice: 150,
investorId: investorId,
investorName: 'Md. Hasan Mahmud',
investorSharePercentage: 100,
investedAmount: 45000,
investmentId: 'ip3',
status: 'in-use',
currentSoc: 82,
health: 97,
cycleCount: 18
}
];
});
const [unassignedBatteries, setUnassignedBatteries] = useState<any[]>(() => {
if (typeof window !== 'undefined') {
const stored = localStorage.getItem('jaiben_unassigned_batteries');
if (stored) {
try {
return JSON.parse(stored);
} catch (e) {
console.error(e);
}
}
}
return [
{ id: 'BAT-003', serialNumber: 'SN-2024-00003', brand: 'BYD', model: 'Li-Ion 72V60Ah', type: 'lithium-ion', capacity: 60, voltage: 72, purchasePrice: 52000, deposit: 6000, rentPrice: 180, status: 'available', currentSoc: 85, health: 97, cycleCount: 12 },
{ id: 'BAT-004', serialNumber: 'SN-2024-00004', brand: 'Panasonic', model: 'Li-Ion 60V40Ah', type: 'lithium-ion', capacity: 40, voltage: 60, purchasePrice: 41000, deposit: 4500, rentPrice: 130, status: 'available', currentSoc: 90, health: 99, cycleCount: 8 }
];
});
useEffect(() => {
if (typeof window !== 'undefined') {
localStorage.setItem('jaiben_batteries', JSON.stringify(batteries));
}
}, [batteries]);
useEffect(() => {
if (typeof window !== 'undefined') {
localStorage.setItem('jaiben_unassigned_batteries', JSON.stringify(unassignedBatteries));
}
}, [unassignedBatteries]);
// Patch local storage state to make sure inv1 has the Standard Battery Plan (ip3) and correct assigned batteries
useEffect(() => {
if (!investor) return;
const hasIp3 = investor.investments?.some(inv => inv.id === 'ip3');
if (!hasIp3) {
const updated = investors.map(i => {
if (i.id === investorId) {
const investments = i.investments || [];
return {
...i,
totalInvested: 300000,
investments: [
...investments.filter(inv => inv.id !== 'ip3'),
{
id: 'ip3',
investorId: investorId,
planName: 'Standard Battery Plan',
planType: 'silver' as const,
assetType: 'battery' as const,
batteryIds: ['BAT-001', 'BAT-002', 'BAT-005'],
totalInvestment: 150000,
monthlyReturn: 4500,
expectedRoi: 16,
actualEarnings: 9000,
startDate: '2024-02-01',
endDate: '2025-02-01',
status: 'active' as const,
paymentMethod: 'bank' as const,
transactionId: 'invt3',
createdAt: '2024-02-01'
}
]
};
}
return i;
});
setInvestors(updated);
}
}, [investors, investorId, investor]);
useEffect(() => {
const hasBat5 = batteries.some(b => b.id === 'BAT-005');
const hasIp3Assignment = batteries.some(b => b.id === 'BAT-001' && b.investmentId === 'ip3');
if (!hasBat5 || !hasIp3Assignment) {
const updated = [
{
id: 'BAT-001',
serialNumber: 'SN-2024-00001',
brand: 'EVE Energy',
model: 'Li-Ion 60V50Ah',
type: 'lithium-ion',
capacity: 50,
voltage: 60,
purchaseDate: '2024-01-15',
purchasePrice: 45000,
deposit: 5000,
rentPrice: 150,
investorId: investorId,
investorName: 'Md. Hasan Mahmud',
investorSharePercentage: 100,
investedAmount: 45000,
investmentId: 'ip3',
status: 'in-use',
currentSoc: 78,
health: 95,
cycleCount: 156
},
{
id: 'BAT-002',
serialNumber: 'SN-2024-00002',
brand: 'CATL',
model: 'LiFePO4 48V40Ah',
type: 'lifepo4',
capacity: 40,
voltage: 48,
purchaseDate: '2024-02-10',
purchasePrice: 38000,
deposit: 4000,
rentPrice: 120,
investorId: investorId,
investorName: 'Md. Hasan Mahmud',
investorSharePercentage: 100,
investedAmount: 38000,
investmentId: 'ip3',
status: 'available',
currentSoc: 92,
health: 98,
cycleCount: 45
},
{
id: 'BAT-005',
serialNumber: 'SN-2024-00005',
brand: 'BYD',
model: 'Li-Ion 60V50Ah',
type: 'lithium-ion',
capacity: 50,
voltage: 60,
purchaseDate: '2024-02-15',
purchasePrice: 45000,
deposit: 5000,
rentPrice: 150,
investorId: investorId,
investorName: 'Md. Hasan Mahmud',
investorSharePercentage: 100,
investedAmount: 45000,
investmentId: 'ip3',
status: 'in-use',
currentSoc: 82,
health: 97,
cycleCount: 18
},
...batteries.filter(b => b.id !== 'BAT-001' && b.id !== 'BAT-002' && b.id !== 'BAT-005')
];
setBatteries(updated);
}
}, [batteries, investorId]);
const [showAssignBatteryModal, setShowAssignBatteryModal] = useState(false);
const [selectedBatteryIds, setSelectedBatteryIds] = useState<string[]>([]);
const [selectedBatteryPlanId, setSelectedBatteryPlanId] = useState('');
const [showRegisterBatteryModal, setShowRegisterBatteryModal] = useState(false);
const [showEditBatteryModal, setShowEditBatteryModal] = useState(false);
const [selectedBatteryToAssign, setSelectedBatteryToAssign] = useState<any>(null);
const [selectedBatteryToEdit, setSelectedBatteryToEdit] = useState<any>(null);
const [assignForm, setAssignForm] = useState({
batteryId: '',
investmentId: '',
deposit: 5000,
rentPrice: 150,
investorShare: 60,
investedAmount: 45000
});
const [registerForm, setRegisterForm] = useState({
serialNumber: '',
brand: 'BYD',
model: 'Li-Ion 60V50Ah',
type: 'lithium-ion',
capacity: 50,
voltage: 60,
purchasePrice: 45000,
deposit: 5000,
rentPrice: 150,
investorShare: 100,
investedAmount: 45000,
investmentId: ''
});
const investorTransactions = initialTransactions.filter(t => t.investorId === investorId);
const investorRentalPayments = initialRentalPayments.filter(p => p.investorId === investorId).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
const [rentalPage, setRentalPage] = useState(1);
const [rentalPageSize] = useState(10);
const [rentalSortBy, setRentalSortBy] = useState('date');
const [rentalSortOrder, setRentalSortOrder] = useState<'asc' | 'desc'>('desc');
const [showWithdrawalModal, setShowWithdrawalModal] = useState(false);
const [showAutoWithdrawModal, setShowAutoWithdrawModal] = useState(false);
const [withdrawSelection, setWithdrawSelection] = useState({
selectAll: true,
selectedPlans: [] as string[],
selectedBikes: [] as string[],
amount: 0,
paymentMethod: '',
accountId: ''
});
const [autoWithdrawSettings, setAutoWithdrawSettings] = useState({
enabled: false,
frequency: 'as_per_request' as 'as_per_request' | 'weekly' | 'monthly',
minAmount: 1000,
accountId: ''
});
const [newInvestment, setNewInvestment] = useState({
planName: '',
planType: 'gold' as 'silver' | 'gold' | 'platinum' | 'diamond',
assetType: 'bike' as 'bike' | 'battery',
selectedBikeIds: [] as string[],
selectedBatteryIds: [] as string[],
totalInvestment: 0,
paidAmount: 0,
paymentType: 'full' as 'full' | 'partial',
monthlyReturn: 0,
expectedRoi: 15,
startDate: new Date().toISOString().split('T')[0],
endDate: '',
paymentMethod: 'bank' as 'bank' | 'mobile' | 'cash' | 'cheque',
transactionReference: '',
notes: ''
});
const [showAddPaymentModal, setShowAddPaymentModal] = useState(false);
const [newPayment, setNewPayment] = useState({
amount: 0,
paymentMethod: 'bank' as 'bank' | 'mobile' | 'cash' | 'cheque',
transactionRef: '',
date: new Date().toISOString().split('T')[0],
notes: ''
});
const [investmentPayments, setInvestmentPayments] = useState<any[]>([
{ id: 'pay1', date: '2024-01-15', amount: 50000, paymentMethod: 'bank', transactionRef: 'TXN-001', status: 'completed', notes: 'First payment' }
]);
if (!investor) {
return (
<div className="p-4 lg:p-6">
<div className="text-center py-12">
<h2 className="text-xl font-bold text-slate-800">Investor Not Found</h2>
<p className="text-slate-500 mt-2">The investor you're looking for doesn't exist.</p>
<Link href="/admin/investors" className="mt-4 inline-flex items-center gap-2 text-investor hover:underline">
<ArrowLeft className="w-4 h-4" /> Back to Investors
</Link>
</div>
</div>
);
}
const availableBikesForAssignment = bikes.filter(b => !b.investorId && b.status === 'available');
const handleAssignBike = () => {
if (!selectedBikePlanId) {
toast.error('Please select an investment plan');
return;
}
if (selectedBikeIds.length === 0) {
toast.error('Please select at least one bike');
return;
}
const assignedBikesList: any[] = [];
setBikes(prev => prev.map(b => {
if (selectedBikeIds.includes(b.id)) {
assignedBikesList.push(b);
return {
...b,
investorId: investorId,
investorName: investor.name,
investmentId: selectedBikePlanId,
status: 'rented',
totalEarnings: b.totalEarnings || 0
};
}
return b;
}));
// Update investor's investments to hold the bike IDs
setInvestors(prev => prev.map(inv => {
if (inv.id === investor.id) {
return {
...inv,
investments: inv.investments?.map((item: any) => {
if (item.id === selectedBikePlanId) {
const currentBikeIds = item.bikeIds || [];
const uniqueNewBikeIds = Array.from(new Set([...currentBikeIds, ...selectedBikeIds]));
return {
...item,
bikeIds: uniqueNewBikeIds
};
}
return item;
})
};
}
return inv;
}));
const bikeNames = assignedBikesList.map(b => `${b.model} (${b.plateNumber})`).join(', ');
toast.success(`Successfully assigned ${selectedBikeIds.length} bike(s): ${bikeNames}`);
setShowAssignBikeModal(false);
setSelectedBikeIds([]);
setSelectedBikePlanId('');
};
const handleRegisterAndAssignBike = () => {
if (!registerBikeForm.plateNumber) {
toast.error('Please enter a plate number');
return;
}
const evInv = investor.investments?.find((inv: any) => inv.assetType === 'bike' || inv.planName.toLowerCase().includes('ev') || inv.planName.toLowerCase().includes('bike')) || investor.investments?.[0];
const newBike = {
id: `BIKE-${Date.now()}`,
plateNumber: registerBikeForm.plateNumber,
brand: registerBikeForm.brand,
model: registerBikeForm.model,
currentRent: Number(registerBikeForm.currentRent),
location: registerBikeForm.location,
purchasePrice: Number(registerBikeForm.purchasePrice),
rentalType: registerBikeForm.rentalType,
investorId: investorId,
investorName: investor.name,
investmentId: registerBikeForm.investmentId || evInv?.id || 'ip1',
status: 'rented',
batteryLevel: 100,
totalEarnings: 0
};
setBikes(prev => [...prev, newBike]);
setShowRegisterBikeModal(false);
toast.success(`New bike ${newBike.model} registered and assigned!`);
};
const handleUnassignBike = (bikeId: string) => {
setBikes(prev => prev.map(b => {
if (b.id === bikeId) {
return {
...b,
investorId: null,
investorName: null,
investmentId: null,
status: 'available'
};
}
return b;
}));
toast.success('Bike successfully unassigned from investor!');
};
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.paidAmount,
paymentMethod: newInvestment.paymentMethod
};
const createdInv = {
id: invId,
investorId: investor.id,
...newInvestment,
bikeIds: [],
batteryIds: [],
actualEarnings: 0,
status: 'active' as const,
transactionId: transactionRef,
createdAt: new Date().toISOString(),
debitAccount,
journalEntry
};
setInvestorJournals([journalEntry, ...investorJournals]);
setLastCreatedInvestment(createdInv);
setInvestors(prev => prev.map(inv => {
if (inv.id === investor.id) {
return {
...inv,
investments: [...(inv.investments || []), createdInv],
totalInvested: inv.totalInvested + newInvestment.totalInvestment
};
}
return inv;
}));
setShowCreateInvestmentModal(false);
setShowInvestmentSuccessModal(true);
setNewInvestment({
planName: '',
planType: 'gold',
assetType: 'bike',
selectedBikeIds: [],
selectedBatteryIds: [],
totalInvestment: 0,
paidAmount: 0,
paymentType: 'full',
monthlyReturn: 0,
expectedRoi: 15,
startDate: new Date().toISOString().split('T')[0],
endDate: '',
paymentMethod: 'bank',
transactionReference: '',
notes: ''
});
};
const handleUnassignBattery = (batteryId: string) => {
const batteryToUnassign = batteries.find(b => b.id === batteryId);
if (!batteryToUnassign) return;
setBatteries(prev => prev.filter(b => b.id !== batteryId));
setUnassignedBatteries(prev => [
...prev,
{
...batteryToUnassign,
investorId: null,
investorName: null,
investorSharePercentage: null,
investedAmount: null,
investmentId: null,
status: 'available'
}
]);
toast.success('Battery successfully unassigned from investor!');
};
const handleAssignBattery = () => {
if (!selectedBatteryPlanId) {
toast.error('Please select an investment plan');
return;
}
if (selectedBatteryIds.length === 0) {
toast.error('Please select at least one battery');
return;
}
const assignedObjList: any[] = [];
const chosenBatteries = unassignedBatteries.filter(b => selectedBatteryIds.includes(b.id));
chosenBatteries.forEach(batteryToAssign => {
const assignedObj = {
...batteryToAssign,
investorId: investorId,
investorName: investor.name,
investorSharePercentage: Number(assignForm.investorShare),
investedAmount: Number(assignForm.investedAmount),
investmentId: selectedBatteryPlanId,
deposit: Number(assignForm.deposit),
rentPrice: Number(assignForm.rentPrice),
status: 'in-use'
};
assignedObjList.push(assignedObj);
});
setBatteries(prev => [...prev, ...assignedObjList]);
setUnassignedBatteries(prev => prev.filter(b => !selectedBatteryIds.includes(b.id)));
// Update investor's investments to hold the battery IDs
setInvestors(prev => prev.map(inv => {
if (inv.id === investor.id) {
return {
...inv,
investments: inv.investments?.map((item: any) => {
if (item.id === selectedBatteryPlanId) {
const currentBatteryIds = item.batteryIds || [];
const uniqueNewBatteryIds = Array.from(new Set([...currentBatteryIds, ...selectedBatteryIds]));
return {
...item,
batteryIds: uniqueNewBatteryIds
};
}
return item;
})
};
}
return inv;
}));
const serialsList = chosenBatteries.map(b => b.serialNumber).join(', ');
toast.success(`Successfully assigned ${selectedBatteryIds.length} battery pack(s): ${serialsList}`);
setShowAssignBatteryModal(false);
setSelectedBatteryIds([]);
setSelectedBatteryPlanId('');
};
const handleRegisterAndAssignBattery = () => {
if (!registerForm.serialNumber) {
toast.error('Please enter a serial number');
return;
}
const newBat = {
id: `BAT-${Date.now()}`,
serialNumber: registerForm.serialNumber,
brand: registerForm.brand,
model: registerForm.model,
type: registerForm.type,
capacity: Number(registerForm.capacity),
voltage: Number(registerForm.voltage),
purchaseDate: new Date().toISOString().split('T')[0],
purchasePrice: Number(registerForm.purchasePrice),
deposit: Number(registerForm.deposit),
rentPrice: Number(registerForm.rentPrice),
investorId: investorId,
investorName: investor.name,
investorSharePercentage: Number(registerForm.investorShare),
investedAmount: Number(registerForm.investedAmount),
investmentId: registerForm.investmentId,
status: 'in-use',
currentSoc: 100,
health: 100,
cycleCount: 0
};
setBatteries(prev => [...prev, newBat]);
setShowRegisterBatteryModal(false);
toast.success('New battery registered and assigned!');
};
const handleSaveEditBattery = () => {
if (!selectedBatteryToEdit) return;
setBatteries(prev => prev.map(b => {
if (b.id === selectedBatteryToEdit.id) {
return {
...b,
deposit: Number(assignForm.deposit),
rentPrice: Number(assignForm.rentPrice),
investorSharePercentage: Number(assignForm.investorShare),
investedAmount: Number(assignForm.investedAmount),
investmentId: assignForm.investmentId
};
}
return b;
}));
setShowEditBatteryModal(false);
setSelectedBatteryToEdit(null);
toast.success('Battery assignment updated successfully!');
};
const bikeTemplates = settings?.plans?.investment?.map((plan: any) => ({
id: plan.id,
name: plan.name,
tier: plan.tier || 'Standard',
evBasePrice: plan.evBasePrice || 200000,
minQuantity: plan.minQuantity || 1,
duration: plan.durationMonths || 12,
maxInvestment: plan.maxInvestment || 1000000,
lockIn: plan.lockInMonths || 3,
exitPenalty: plan.earlyExitPenalty || 10,
profitShareSingle: plan.ficoSingleRent || 45,
profitShareOwn: plan.ficoRentToOwn || 55,
profitShareEV: plan.ficoShareEv || 60
})) || [
{ id: 'inv_demo_1', name: '1 Bike Plan', tier: 'Economy', evBasePrice: 200000, minQuantity: 1, duration: 12, maxInvestment: 1000000, lockIn: 3, exitPenalty: 10, profitShareSingle: 45, profitShareOwn: 55, profitShareEV: 60 },
{ id: 'inv_demo_2', name: '5 Bike Plan', tier: 'Standard', evBasePrice: 180000, minQuantity: 5, duration: 24, maxInvestment: 5000000, lockIn: 6, exitPenalty: 15, profitShareSingle: 50, profitShareOwn: 60, profitShareEV: 65 }
];
const batteryTemplates = settings?.plans?.batteryInvestment?.map((plan: any) => ({
id: plan.id,
name: plan.name,
tier: plan.tier || 'Standard',
evBasePrice: plan.batteryBasePrice || 15000,
minQuantity: plan.minQuantity || 10,
duration: plan.durationMonths || 12,
maxInvestment: plan.maxInvestment || 500000,
lockIn: plan.lockInMonths || 3,
exitPenalty: plan.earlyExitPenalty || 10,
profitSharePercent: plan.profitSharePercent || 40,
profitShareSingle: plan.profitSharePercent || 40,
profitShareOwn: plan.profitSharePercent || 40,
profitShareEV: plan.profitSharePercent || 40
})) || [
{ id: 'bat_demo_1', name: '1 Battery Pack Plan', tier: 'Silver', evBasePrice: 45000, minQuantity: 1, duration: 12, maxInvestment: 500000, lockIn: 3, exitPenalty: 8, profitSharePercent: 40, profitShareSingle: 40, profitShareOwn: 40, profitShareEV: 40 },
{ id: 'bat_demo_2', name: '5 Battery Pack Plan', tier: 'Gold', evBasePrice: 42000, minQuantity: 5, duration: 18, maxInvestment: 2000000, lockIn: 4, exitPenalty: 10, profitSharePercent: 48, profitShareSingle: 48, profitShareOwn: 48, profitShareEV: 48 },
{ id: 'bat_demo_3', name: '10 Battery Pack Fleet', tier: 'Platinum', evBasePrice: 40000, minQuantity: 10, duration: 24, maxInvestment: 5000000, lockIn: 6, exitPenalty: 12, profitSharePercent: 55, profitShareSingle: 55, profitShareOwn: 55, profitShareEV: 55 }
];
const allTemplates = [...bikeTemplates, ...batteryTemplates];
const activeTemplate = allTemplates.find(t => t.name === newInvestment.planName) || (newInvestment.assetType === 'battery' ? batteryTemplates[0] : bikeTemplates[0]);
return (
<div className="p-4 lg:p-6">
<button onClick={() => router.push('/admin/investors')} className="flex items-center gap-2 text-slate-600 hover:text-slate-800 mb-4">
<ArrowLeft className="w-4 h-4" /> Back to Investors
</button>
{/* Profile Card Header */}
<div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden mb-6">
<div className="p-5">
<div className="flex flex-col lg:flex-row lg:items-start gap-5">
{/* Profile Image */}
<div className="relative group flex-shrink-0 mx-auto lg:mx-0">
<div className="w-24 h-24 rounded-full bg-gradient-to-br from-purple-500 to-blue-500 flex items-center justify-center shadow-lg border-4 border-white">
<span className="text-3xl font-extrabold text-white">{investor.name.charAt(0)}</span>
</div>
<label className="absolute bottom-0 right-0 w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity shadow-lg border-2 border-white">
<Camera className="w-4 h-4 text-white" />
<input type="file" accept="image/*" className="hidden" onChange={() => toast.success('Profile image updated')} />
</label>
</div>
{/* Profile Info */}
<div className="flex-1">
<div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4">
<div>
<h1 className="text-2xl font-extrabold text-slate-800">{investor.name}</h1>
<p className="text-sm text-slate-500 mt-0.5">{investor.id} &bull; {investor.email}</p>
<div className="flex items-center gap-2 mt-1">
{investor.referralCode && (
<span className="inline-flex items-center gap-1 text-xs font-medium px-2 py-0.5 rounded bg-purple-50 text-purple-700 border border-purple-100">
<Star className="w-3 h-3" /> Ref: {investor.referralCode}
</span>
)}
{investor.totalReferrals > 0 && (
<span className="text-xs text-slate-400">Referrals: {investor.totalReferrals}</span>
)}
</div>
<div className="flex flex-wrap items-center gap-2 mt-2">
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${statusColors[investor.status]}`}>{investor.status}</span>
{investor.investments && investor.investments.length > 0 && (
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${planColors[investor.investments[0].planType]}`}>
{investor.investments.length} Investment{investor.investments.length > 1 ? 's' : ''}
</span>
)}
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${kycColors[investor.kycStatus]}`}>
<ShieldCheck className="w-3 h-3" /> KYC {investor.kycStatus}
</span>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${investor.riskLevel === 'low' ? 'bg-green-100 text-green-700' : investor.riskLevel === 'medium' ? 'bg-amber-100 text-amber-700' : 'bg-red-100 text-red-700'}`}>
Risk: {investor.riskLevel}
</span>
</div>
</div>
{/* <div className="flex items-center gap-2 flex-shrink-0">
<button onClick={() => setShowEditModal(true)} className="py-2 px-4 border border-slate-200 text-slate-600 rounded-lg font-semibold text-sm hover:bg-slate-50 flex items-center gap-2">
<Edit className="w-4 h-4" /> Edit
</button>
<button className="py-2 px-4 bg-red-500 text-white rounded-lg font-semibold text-sm hover:bg-red-600 flex items-center gap-2">
<Trash2 className="w-4 h-4" /> Delete
</button>
</div> */}
</div>
{/* Stats Row */}
<div className="grid grid-cols-3 lg:grid-cols-7 gap-3 mt-5">
<div className="p-3 bg-purple-50 rounded-lg border border-purple-100">
<p className="text-xs text-purple-600 font-medium">Total Invested</p>
<p className="text-sm font-bold text-purple-700">{investor.totalInvested.toLocaleString()}</p>
</div>
<div className="p-3 bg-green-50 rounded-lg border border-green-100">
<p className="text-xs text-green-600 font-medium">Total Earnings</p>
<p className="text-sm font-bold text-green-700">{investor.totalEarnings.toLocaleString()}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg border border-slate-100">
<p className="text-xs text-slate-600 font-medium">Total Withdrawn</p>
<p className="text-sm font-bold text-slate-700">{investor.totalWithdrawn.toLocaleString()}</p>
</div>
<div className="p-3 bg-blue-50 rounded-lg border border-blue-100">
<p className="text-xs text-blue-600 font-medium">Current Balance</p>
<p className="text-sm font-bold text-blue-700">{(investor.totalEarnings - investor.totalWithdrawn - investor.pendingEarnings).toLocaleString()}</p>
</div>
<div className="p-3 bg-amber-50 rounded-lg border border-amber-100">
<p className="text-xs text-amber-600 font-medium">Active Bikes</p>
<p className="text-sm font-bold text-amber-700">{investor.activeBikes}</p>
</div>
<div className="p-3 bg-emerald-50 rounded-lg border border-emerald-100">
<p className="text-xs text-emerald-600 font-medium">Active Batteries</p>
<p className="text-sm font-bold text-emerald-700">{batteries.filter(b => b.investorId === investorId).length}</p>
</div>
<div className="p-3 bg-red-50 rounded-lg border border-red-100">
<p className="text-xs text-red-600 font-medium">Pending Request</p>
<p className="text-sm font-bold text-red-700">{investor.pendingEarnings.toLocaleString()}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 mb-6">
<div className="border-b border-slate-100 flex overflow-x-auto">
<button
onClick={() => setActiveTab('overview')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'overview' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<User className="w-4 h-4 inline mr-1" /> Overview
</button>
<button
onClick={() => setActiveTab('investments')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'investments' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<TrendingUp className="w-4 h-4 inline mr-1" /> Investments ({investor.investments?.length || 0})
</button>
<button
onClick={() => setActiveTab('bikes')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'bikes' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<Bike className="w-4 h-4 inline mr-1" /> Bikes ({assignedBikes.length})
</button>
<button
onClick={() => setActiveTab('batteries')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'batteries' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<Battery className="w-4 h-4 inline mr-1" /> Batteries ({batteries.filter(b => b.investorId === investorId).length})
</button>
<button
onClick={() => setActiveTab('financial')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'financial' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<Banknote className="w-4 h-4 inline mr-1" /> Account Info
</button>
<button
onClick={() => setActiveTab('rentals')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'rentals' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<History className="w-4 h-4 inline mr-1" /> Rental History
</button>
<button
onClick={() => setActiveTab('transactions')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'transactions' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<DollarSign className="w-4 h-4 inline mr-1" /> Transactions
</button>
<button
onClick={() => setActiveTab('documents')}
className={`px-4 py-3 text-sm font-medium whitespace-nowrap ${activeTab === 'documents' ? 'border-b-2 border-investor text-investor' : 'text-slate-500'}`}
>
<FileText className="w-4 h-4 inline mr-1" /> Documents
</button>
</div>
<div className="p-5">
{activeTab === 'overview' && (
<div className="space-y-4">
<div className="flex gap-4">
<div className="flex-1 space-y-4">
<SectionCard title="Personal Information" icon={User} headerBg="bg-emerald-50" headerBorder="border-emerald-100" editKey="personal" editingSection={editingSection} setEditingSection={setEditingSection} onEdit={() => setEditForm({
fullName: investor.name,
phone: investor.phone,
phoneAlt: investor.phoneAlt || '',
email: investor.email,
nidNumber: investor.nidNumber || '',
tinNumber: investor.tinNumber || '',
dateOfBirth: investor.dateOfBirth || '',
gender: investor.gender || '',
occupation: investor.occupation || '',
bloodGroup: (investor as any).bloodGroup || '',
maritalStatus: (investor as any).maritalStatus || '',
religion: (investor as any).religion || '',
nationality: (investor as any).nationality || 'Bangladeshi'
})} editForm={editForm} setEditForm={setEditForm}>
{editingSection === 'personal' ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Full Name</label>
<input type="text" value={editForm.fullName || ''} onChange={(e) => setEditForm({ ...editForm, fullName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Phone</label>
<input type="text" value={editForm.phone || ''} onChange={(e) => setEditForm({ ...editForm, phone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Alternate Phone</label>
<input type="text" value={editForm.phoneAlt || ''} onChange={(e) => setEditForm({ ...editForm, phoneAlt: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Email</label>
<input type="email" value={editForm.email || ''} onChange={(e) => setEditForm({ ...editForm, email: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">NID Number</label>
<input type="text" value={editForm.nidNumber || ''} onChange={(e) => setEditForm({ ...editForm, nidNumber: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">TIN Number</label>
<input type="text" value={editForm.tinNumber || ''} onChange={(e) => setEditForm({ ...editForm, tinNumber: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Date of Birth</label>
<input type="date" value={editForm.dateOfBirth || ''} onChange={(e) => setEditForm({ ...editForm, dateOfBirth: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Gender</label>
<select value={editForm.gender || ''} onChange={(e) => setEditForm({ ...editForm, gender: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Occupation</label>
<input type="text" value={editForm.occupation || ''} onChange={(e) => setEditForm({ ...editForm, occupation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Blood Group</label>
<select value={editForm.bloodGroup || ''} onChange={(e) => setEditForm({ ...editForm, bloodGroup: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select</option>
<option value="A+">A+</option>
<option value="A-">A-</option>
<option value="B+">B+</option>
<option value="B-">B-</option>
<option value="O+">O+</option>
<option value="O-">O-</option>
<option value="AB+">AB+</option>
<option value="AB-">AB-</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Marital Status</label>
<select value={editForm.maritalStatus || ''} onChange={(e) => setEditForm({ ...editForm, maritalStatus: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select</option>
<option value="Single">Single</option>
<option value="Married">Married</option>
<option value="Divorced">Divorced</option>
<option value="Widowed">Widowed</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Religion</label>
<select value={editForm.religion || ''} onChange={(e) => setEditForm({ ...editForm, religion: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select</option>
<option value="Islam">Islam</option>
<option value="Hinduism">Hinduism</option>
<option value="Christianity">Christianity</option>
<option value="Buddhism">Buddhism</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Nationality</label>
<input type="text" value={editForm.nationality || ''} onChange={(e) => setEditForm({ ...editForm, nationality: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Full Name</p>
<p className="font-medium text-slate-700">{investor.name}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Phone</p>
<p className="font-medium text-slate-700">{investor.phone}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Alternate Phone</p>
<p className="font-medium text-slate-700">{investor.phoneAlt || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Email</p>
<p className="font-medium text-slate-700">{investor.email}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">NID Number</p>
<p className="font-medium text-slate-700">{investor.nidNumber || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">TIN Number</p>
<p className="font-medium text-slate-700">{investor.tinNumber || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Date of Birth</p>
<p className="font-medium text-slate-700">{investor.dateOfBirth || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Gender</p>
<p className="font-medium text-slate-700">{investor.gender || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Occupation</p>
<p className="font-medium text-slate-700">{investor.occupation || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Blood Group</p>
<p className="font-medium text-slate-700">{(investor as any).bloodGroup || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Marital Status</p>
<p className="font-medium text-slate-700">{(investor as any).maritalStatus || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Religion</p>
<p className="font-medium text-slate-700">{(investor as any).religion || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Nationality</p>
<p className="font-medium text-slate-700">{(investor as any).nationality || 'Bangladeshi'}</p>
</div>
</div>
)}
</SectionCard>
<SectionCard title="Nominee Details" icon={Heart} headerBg="bg-orange-50" headerBorder="border-orange-100" editKey="nominee" editingSection={editingSection} setEditingSection={setEditingSection} onEdit={() => setEditForm({
nomineeName: (investor as any).nomineeName || '',
nomineeRelation: (investor as any).nomineeRelation || '',
nomineeNid: (investor as any).nomineeNid || '',
nomineePhone: (investor as any).nomineePhone || '',
nomineeEmail: (investor as any).nomineeEmail || '',
nomineeAddress: (investor as any).nomineeAddress || '',
nomineeShare: (investor as any).nomineeShare || ''
})} editForm={editForm} setEditForm={setEditForm}>
{editingSection === 'nominee' ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div>
<label className="text-xs text-slate-500 mb-1 block">Nominee Name</label>
<input type="text" value={editForm.nomineeName || ''} onChange={(e) => setEditForm({ ...editForm, nomineeName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Relationship</label>
<select value={editForm.nomineeRelation || ''} onChange={(e) => setEditForm({ ...editForm, nomineeRelation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select</option>
<option value="Spouse">Spouse</option>
<option value="Child">Child</option>
<option value="Parent">Parent</option>
<option value="Sibling">Sibling</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">NID Number</label>
<input type="text" value={editForm.nomineeNid || ''} onChange={(e) => setEditForm({ ...editForm, nomineeNid: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Phone</label>
<input type="text" value={editForm.nomineePhone || ''} onChange={(e) => setEditForm({ ...editForm, nomineePhone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Email</label>
<input type="email" value={editForm.nomineeEmail || ''} onChange={(e) => setEditForm({ ...editForm, nomineeEmail: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Share %</label>
<input type="number" value={editForm.nomineeShare || ''} onChange={(e) => setEditForm({ ...editForm, nomineeShare: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Address</label>
<input type="text" value={editForm.nomineeAddress || ''} onChange={(e) => setEditForm({ ...editForm, nomineeAddress: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Nominee Name</p>
<p className="font-medium text-slate-700">{(investor as any).nomineeName || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Relationship</p>
<p className="font-medium text-slate-700">{(investor as any).nomineeRelation || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">NID Number</p>
<p className="font-medium text-slate-700">{(investor as any).nomineeNid || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Phone</p>
<p className="font-medium text-slate-700">{(investor as any).nomineePhone || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Email</p>
<p className="font-medium text-slate-700">{(investor as any).nomineeEmail || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Share %</p>
<p className="font-medium text-slate-700">{(investor as any).nomineeShare || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg md:col-span-2">
<p className="text-xs text-slate-500">Address</p>
<p className="font-medium text-slate-700">{(investor as any).nomineeAddress || '-'}</p>
</div>
</div>
)}
</SectionCard>
<SectionCard title="Emergency Contact" icon={PhoneCall} headerBg="bg-red-50" headerBorder="border-red-100" editKey="emergency" editingSection={editingSection} setEditingSection={setEditingSection} onEdit={() => setEditForm({
emergencyName: investor.emergencyContactName || '',
emergencyRelation: investor.emergencyContactRelation || '',
emergencyPhone: investor.emergencyContactPhone || '',
emergencyEmail: (investor as any).emergencyEmail || '',
emergencyAddress: (investor as any).emergencyAddress || ''
})} editForm={editForm} setEditForm={setEditForm}>
{editingSection === 'emergency' ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div>
<label className="text-xs text-slate-500 mb-1 block">Contact Name</label>
<input type="text" value={editForm.emergencyName || ''} onChange={(e) => setEditForm({ ...editForm, emergencyName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Relationship</label>
<select value={editForm.emergencyRelation || ''} onChange={(e) => setEditForm({ ...editForm, emergencyRelation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select</option>
<option value="Spouse">Spouse</option>
<option value="Child">Child</option>
<option value="Parent">Parent</option>
<option value="Sibling">Sibling</option>
<option value="Friend">Friend</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Phone</label>
<input type="text" value={editForm.emergencyPhone || ''} onChange={(e) => setEditForm({ ...editForm, emergencyPhone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Email</label>
<input type="email" value={editForm.emergencyEmail || ''} onChange={(e) => setEditForm({ ...editForm, emergencyEmail: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Address</label>
<input type="text" value={editForm.emergencyAddress || ''} onChange={(e) => setEditForm({ ...editForm, emergencyAddress: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Contact Name</p>
<p className="font-medium text-slate-700">{investor.emergencyContactName || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Relationship</p>
<p className="font-medium text-slate-700">{investor.emergencyContactRelation || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Phone</p>
<p className="font-medium text-slate-700">{investor.emergencyContactPhone || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Email</p>
<p className="font-medium text-slate-700">{(investor as any).emergencyEmail || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg md:col-span-2">
<p className="text-xs text-slate-500">Address</p>
<p className="font-medium text-slate-700">{(investor as any).emergencyAddress || '-'}</p>
</div>
</div>
)}
</SectionCard>
</div>
<div className="flex-1 space-y-4">
<SectionCard title="Investment Information" icon={Briefcase} headerBg="bg-blue-50" headerBorder="border-blue-100" editKey="investmentInfo" editingSection={editingSection} setEditingSection={setEditingSection} onEdit={() => setEditForm({
companyName: (investor as any).companyName || '',
monthlyIncome: (investor as any).monthlyIncome || '',
investmentSource: (investor as any).investmentSource || '',
profession: investor.occupation || ''
})} editForm={editForm} setEditForm={setEditForm}>
{editingSection === 'investmentInfo' ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Company / Business Name</label>
<input type="text" value={editForm.companyName || ''} onChange={(e) => setEditForm({ ...editForm, companyName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Monthly Income ()</label>
<input type="number" value={editForm.monthlyIncome || ''} onChange={(e) => setEditForm({ ...editForm, monthlyIncome: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Investment Source</label>
<input type="text" value={editForm.investmentSource || ''} onChange={(e) => setEditForm({ ...editForm, investmentSource: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="e.g., Savings, Business profit, Inheritance" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Profession / Occupation</label>
<input type="text" value={editForm.profession || ''} onChange={(e) => setEditForm({ ...editForm, profession: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
) : (
<div className="space-y-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Company / Business Name</p>
<p className="font-medium text-slate-700">{(investor as any).companyName || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Monthly Income</p>
<p className="font-medium text-slate-700">{(investor as any).monthlyIncome || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Investment Source</p>
<p className="font-medium text-slate-700">{(investor as any).investmentSource || '-'}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Profession / Occupation</p>
<p className="font-medium text-slate-700">{investor.occupation || '-'}</p>
</div>
</div>
</div>
)}
</SectionCard>
<SectionCard title="Present Address" icon={Home} headerBg="bg-green-50" headerBorder="border-green-100" editKey="presentAddress" editingSection={editingSection} setEditingSection={setEditingSection} onEdit={() => {
const parts = investor.address.split(',').map(s => s.trim());
setEditForm({
addressLine1: parts.slice(0, 2).join(', '),
addressLine2: parts.slice(2, 4).join(', '),
division: parts[4] || 'Dhaka',
district: parts[5] || 'Dhaka',
thana: parts[3] || '',
zipCode: parts[6] || '',
landmark: parts[7] || ''
});
}} editForm={editForm} setEditForm={setEditForm}>
{editingSection === 'presentAddress' ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Address Line 1 (House/Flat + Road)</label>
<input type="text" value={editForm.addressLine1 || ''} onChange={(e) => setEditForm({ ...editForm, addressLine1: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Address Line 2 (Block + Area)</label>
<input type="text" value={editForm.addressLine2 || ''} onChange={(e) => setEditForm({ ...editForm, addressLine2: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Division</label>
<select value={editForm.division || ''} onChange={(e) => setEditForm({ ...editForm, division: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="Dhaka">Dhaka</option>
<option value="Chittagong">Chittagong</option>
<option value="Sylhet">Sylhet</option>
<option value="Khulna">Khulna</option>
<option value="Barisal">Barisal</option>
<option value="Rangpur">Rangpur</option>
<option value="Mymensingh">Mymensingh</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">District</label>
<select value={editForm.district || ''} onChange={(e) => setEditForm({ ...editForm, district: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="Dhaka">Dhaka</option>
<option value="Gazipur">Gazipur</option>
<option value="Narayanganj">Narayanganj</option>
<option value="Tangail">Tangail</option>
<option value="Kishoreganj">Kishoreganj</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Thana</label>
<input type="text" value={editForm.thana || ''} onChange={(e) => setEditForm({ ...editForm, thana: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Zip Code</label>
<input type="text" value={editForm.zipCode || ''} onChange={(e) => setEditForm({ ...editForm, zipCode: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Landmark</label>
<input type="text" value={editForm.landmark || ''} onChange={(e) => setEditForm({ ...editForm, landmark: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
) : (
<div className="space-y-2">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Address Line 1</p>
<p className="font-medium text-slate-700">{investor.address}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Landmark</p>
<p className="font-medium text-slate-700">-</p>
</div>
<div className="grid grid-cols-2 gap-2">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Division</p>
<p className="font-medium text-slate-700">Dhaka</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">District</p>
<p className="font-medium text-slate-700">Dhaka</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Thana</p>
<p className="font-medium text-slate-700">-</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Zip Code</p>
<p className="font-medium text-slate-700">1205</p>
</div>
</div>
</div>
)}
</SectionCard>
<SectionCard title="Permanent Address" icon={Home} headerBg="bg-emerald-50" headerBorder="border-emerald-100" editKey="permanentAddress" editingSection={editingSection} setEditingSection={setEditingSection} onEdit={() => {
const parts = investor.address.split(',').map(s => s.trim());
setEditForm({
addressLine1: parts.slice(0, 2).join(', '),
addressLine2: parts.slice(2, 4).join(', '),
division: parts[4] || 'Dhaka',
district: parts[5] || 'Dhaka',
thana: parts[3] || '',
zipCode: parts[6] || '',
isSameAsPresent: true
});
}} editForm={editForm} setEditForm={setEditForm}>
{editingSection === 'permanentAddress' ? (
<div>
<div className="flex items-center gap-2 mb-4">
<input type="checkbox" id="sameAsPresent" checked={editForm.isSameAsPresent || false} onChange={(e) => setEditForm({ ...editForm, isSameAsPresent: e.target.checked })} className="rounded text-investor" />
<label htmlFor="sameAsPresent" className="text-sm text-slate-600">Same as Present Address</label>
</div>
{!editForm.isSameAsPresent && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Address Line 1 (House/Flat + Road)</label>
<input type="text" value={editForm.addressLine1 || ''} onChange={(e) => setEditForm({ ...editForm, addressLine1: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div className="md:col-span-2">
<label className="text-xs text-slate-500 mb-1 block">Address Line 2 (Block + Area)</label>
<input type="text" value={editForm.addressLine2 || ''} onChange={(e) => setEditForm({ ...editForm, addressLine2: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Division</label>
<select value={editForm.division || ''} onChange={(e) => setEditForm({ ...editForm, division: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="Dhaka">Dhaka</option>
<option value="Chittagong">Chittagong</option>
<option value="Sylhet">Sylhet</option>
<option value="Khulna">Khulna</option>
<option value="Barisal">Barisal</option>
<option value="Rangpur">Rangpur</option>
<option value="Mymensingh">Mymensingh</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">District</label>
<select value={editForm.district || ''} onChange={(e) => setEditForm({ ...editForm, district: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="Dhaka">Dhaka</option>
<option value="Gazipur">Gazipur</option>
<option value="Narayanganj">Narayanganj</option>
<option value="Tangail">Tangail</option>
<option value="Kishoreganj">Kishoreganj</option>
</select>
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Thana</label>
<input type="text" value={editForm.thana || ''} onChange={(e) => setEditForm({ ...editForm, thana: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Zip Code</label>
<input type="text" value={editForm.zipCode || ''} onChange={(e) => setEditForm({ ...editForm, zipCode: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
)}
</div>
) : (
<div className="space-y-2">
<div className="flex items-center gap-2 mb-2">
<span className="text-xs bg-blue-100 text-blue-700 px-2 py-1 rounded-full">Same as Present</span>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Address Line 1</p>
<p className="font-medium text-slate-700">{investor.address}</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Landmark</p>
<p className="font-medium text-slate-700">-</p>
</div>
<div className="grid grid-cols-2 gap-2">
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Division</p>
<p className="font-medium text-slate-700">Dhaka</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">District</p>
<p className="font-medium text-slate-700">Dhaka</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Thana</p>
<p className="font-medium text-slate-700">-</p>
</div>
<div className="p-3 bg-slate-50 rounded-lg">
<p className="text-xs text-slate-500">Zip Code</p>
<p className="font-medium text-slate-700">1205</p>
</div>
</div>
</div>
)}
</SectionCard>
</div>
</div>
{investor.notes && (
<div className="mt-6">
<h3 className="font-semibold text-slate-800 mb-2">Notes</h3>
<p className="text-sm text-slate-600 bg-slate-50 p-3 rounded-lg">{investor.notes}</p>
</div>
)}
</div>
)}
{activeTab === 'bikes' && (
<div>
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
<div>
<h3 className="font-bold text-lg text-slate-800 flex items-center gap-2">
<Bike className="w-5 h-5 text-investor" />
Assigned Bikes
</h3>
<p className="text-sm text-slate-500">
{assignedBikes.length} bikes across {investor.investments?.filter((inv: any) => inv.assetType === 'bike' || !inv.assetType).length || 0} EV Investment Plans
</p>
</div>
<div className="flex flex-wrap items-center gap-2">
<button
onClick={() => {
setSelectedBikeIds([]);
setSelectedBikePlanId('');
setShowAssignBikeModal(true);
}}
className="px-4 py-2 bg-blue-50 text-blue-700 border border-blue-200 rounded-lg text-sm font-semibold hover:bg-blue-100 flex items-center gap-2 transition-colors"
>
<Plus className="w-4 h-4" /> Assign Existing
</button>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{assignedBikes.map(bike => {
const investment = investor.investments?.find((inv: any) => inv.id === bike.investmentId);
const planColors: Record<string, string> = {
silver: 'from-slate-400 to-slate-600',
gold: 'from-amber-400 to-amber-600',
platinum: 'from-purple-400 to-purple-600',
diamond: 'from-blue-400 to-blue-600',
};
const planBadges: Record<string, string> = {
silver: 'bg-slate-100 text-slate-600',
gold: 'bg-amber-100 text-amber-700',
platinum: 'bg-purple-100 text-purple-700',
diamond: 'bg-blue-100 text-blue-700',
};
const planBg: Record<string, string> = {
silver: 'bg-slate-50 border-slate-200',
gold: 'bg-amber-50 border-amber-200',
platinum: 'bg-purple-50 border-purple-200',
diamond: 'bg-blue-50 border-blue-200',
};
const rentalTypes: Record<string, { label: string; color: string }> = {
single_rent: { label: 'Single Rent', color: 'text-green-600' },
rent_to_own: { label: 'Rent to Own', color: 'text-blue-600' },
share_ev: { label: 'Share EV', color: 'text-purple-600' },
};
const statusConfig: Record<string, { bg: string; color: string }> = {
rented: { bg: 'bg-green-100', color: 'text-green-700' },
available: { bg: 'bg-blue-100', color: 'text-blue-700' },
maintenance: { bg: 'bg-amber-100', color: 'text-amber-700' },
retired: { bg: 'bg-slate-100', color: 'text-slate-600' },
};
const rentalInfo = rentalTypes[bike.rentalType || 'single_rent'] || rentalTypes.single_rent;
const planType = investment?.planType || 'gold';
const status = statusConfig[bike.status] || statusConfig.available;
return (
<div
key={bike.id}
className={`block bg-white rounded-xl border ${planBg[planType]} overflow-hidden hover:shadow-lg transition-all group relative`}
>
<div className={`h-2 bg-gradient-to-r ${planColors[planType]}`} />
<div className="p-4">
<div className="flex items-start gap-3 mb-3">
<div className={`w-12 h-12 rounded-xl bg-gradient-to-br ${planColors[planType]} flex items-center justify-center shadow-sm`}>
<Bike className="w-6 h-6 text-white" />
</div>
<div className="flex-1 min-w-0">
<h4 className="font-semibold text-slate-800 truncate">{bike.model}</h4>
<p className="text-sm text-slate-500">{bike.brand}</p>
</div>
<span className={`px-2 py-1 rounded-full text-xs font-medium ${status.bg} ${status.color} capitalize`}>
{bike.status}
</span>
</div>
<div className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium ${planBadges[planType]} capitalize mb-3`}>
<span className={`w-2 h-2 rounded-full ${planType === 'silver' ? 'bg-slate-500' :
planType === 'gold' ? 'bg-amber-500' :
planType === 'platinum' ? 'bg-purple-500' : 'bg-blue-500'
}`} />
{planType} Plan {investment?.planName || 'Investment'}
</div>
<div className="grid grid-cols-2 gap-2 mb-3">
<div className="bg-white/80 rounded-lg p-2">
<p className="text-xs text-slate-400">Plate</p>
<p className="text-sm font-medium text-slate-700 truncate">{bike.plateNumber.split('-').pop()}</p>
</div>
<div className="bg-white/80 rounded-lg p-2">
<p className="text-xs text-slate-400">Location</p>
<p className="text-sm font-medium text-slate-700 truncate">{bike.location}</p>
</div>
</div>
<div className="bg-white/80 rounded-lg p-3 space-y-2">
<div className="flex items-center justify-between">
<span className="text-xs text-slate-500">Rental Type</span>
<span className={`text-xs font-semibold ${rentalInfo.color}`}>{rentalInfo.label}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-xs text-slate-500">Total Earnings</span>
<span className="text-sm font-bold text-green-600">{bike.totalEarnings?.toLocaleString() || 0}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-xs text-slate-500">Battery</span>
<span className={`text-xs font-medium ${bike.batteryLevel > 50 ? 'text-green-600' :
bike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'
}`}>{bike.batteryLevel}%</span>
</div>
</div>
<div className="mt-3 pt-3 border-t border-slate-100 flex justify-end gap-2">
<Link href={`/admin/fleet/${bike.id}`} className="text-xs text-slate-500 hover:text-slate-800 font-semibold transition-colors px-2 py-1 bg-slate-100 rounded">
View Details
</Link>
<button
onClick={() => {
setUnassignConfirmModal({
show: true,
type: 'bike',
id: bike.id,
name: bike.model,
details: bike.plateNumber
});
}}
className="text-xs text-red-600 hover:text-red-800 font-semibold transition-colors px-2 py-1 bg-red-50 rounded"
>
Unassign
</button>
</div>
</div>
</div>
);
})}
{assignedBikes.length === 0 && (
<div className="col-span-full text-center py-12 border-2 border-dashed border-slate-200 rounded-xl">
<Bike className="w-12 h-12 mx-auto mb-3 text-slate-300" />
<p className="text-slate-500">No bikes assigned to this investor</p>
<p className="text-sm text-slate-400 mt-1">Bikes will appear here once assigned to investments</p>
</div>
)}
</div>
</div>
)}
{activeTab === 'batteries' && (
<div>
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
<div>
<h3 className="font-bold text-lg text-slate-800 flex items-center gap-2">
<Battery className="w-5 h-5 text-emerald-600 animate-pulse" />
Assigned Batteries
</h3>
<p className="text-sm text-slate-500">
{batteries.filter(b => b.investorId === investorId).length} battery packs assigned to this partner
</p>
</div>
<div className="flex flex-wrap items-center gap-2">
<button
onClick={() => {
const batInv = investor.investments?.find((inv: any) => inv.assetType === 'battery' || inv.planName.toLowerCase().includes('battery')) || investor.investments?.[0];
setAssignForm({
batteryId: '',
investmentId: batInv?.id || '',
deposit: 5000,
rentPrice: 150,
investorShare: 100,
investedAmount: 45000
});
setSelectedBatteryIds([]);
setSelectedBatteryPlanId('');
setShowAssignBatteryModal(true);
}}
className="px-4 py-2 bg-emerald-50 text-emerald-700 border border-emerald-200 rounded-lg text-sm font-semibold hover:bg-emerald-100 flex items-center gap-2 transition-colors"
>
<Plus className="w-4 h-4" /> Assign Existing
</button>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
{batteries.filter(b => b.investorId === investorId).map(battery => {
const investment = investor.investments?.find((inv: any) => inv.id === battery.investmentId);
const dailyPayout = Math.floor(battery.rentPrice * (battery.investorSharePercentage / 100));
const statusConfig: Record<string, { bg: string; text: string; dot: string }> = {
'in-use': { bg: 'bg-green-50 text-green-700 border-green-200', text: 'In Use', dot: 'bg-green-500' },
'available': { bg: 'bg-blue-50 text-blue-700 border-blue-200', text: 'Available', dot: 'bg-blue-500' },
'maintenance': { bg: 'bg-amber-50 text-amber-700 border-amber-200', text: 'Maintenance', dot: 'bg-amber-500' },
};
const status = statusConfig[battery.status] || { bg: 'bg-slate-50 text-slate-700 border-slate-200', text: battery.status || 'Unknown', dot: 'bg-slate-500' };
return (
<div
key={battery.id}
className="bg-white rounded-xl border border-slate-200 overflow-hidden hover:shadow-md hover:border-emerald-300 transition-all group relative flex flex-col"
>
<div className="h-1.5 bg-gradient-to-r from-emerald-400 to-green-600" />
<div className="p-4 flex-1 flex flex-col justify-between space-y-4">
{/* Card Header */}
<div>
<div className="flex items-start justify-between">
<span className="text-xs font-semibold font-mono text-slate-400 tracking-wider">
{battery.serialNumber}
</span>
<span className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-semibold border ${status.bg}`}>
<span className={`w-1.5 h-1.5 rounded-full ${status.dot} animate-pulse`} />
{status.text}
</span>
</div>
<h4 className="font-bold text-slate-800 mt-1">{battery.brand} &bull; {battery.model}</h4>
<p className="text-xs text-slate-400 mt-0.5">ID: {battery.id}</p>
<div className="mt-1.5 flex items-center">
<span className="text-xs font-semibold px-2 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-100">
Plan: {investment?.planName || 'Unlinked Plan'}
</span>
</div>
</div>
{/* Co-ownership Payout details */}
<div className="bg-slate-50 border border-slate-100 rounded-lg p-3 space-y-2">
<div className="flex justify-between text-xs">
<span className="text-slate-500">Refundable Deposit</span>
<span className="font-semibold text-slate-700">{battery.deposit?.toLocaleString()}</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-slate-500">Daily Rent Price</span>
<span className="font-semibold text-slate-700">{battery.rentPrice}/day</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-slate-500">Your Share %</span>
<span className="font-bold text-emerald-600">{battery.investorSharePercentage}%</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-slate-500">Capital Contribution</span>
<span className="font-semibold text-slate-700">{battery.investedAmount?.toLocaleString()}</span>
</div>
<div className="pt-2 border-t border-dashed border-slate-200 flex justify-between items-center text-xs">
<span className="font-medium text-emerald-800">Your Daily Payout</span>
<span className="text-sm font-extrabold text-emerald-600">{dailyPayout}/day</span>
</div>
</div>
{/* BMS parameters */}
<div className="grid grid-cols-3 gap-2 bg-emerald-50/40 rounded-lg p-2.5 text-center border border-emerald-100/50">
<div>
<p className="text-[10px] text-emerald-700 font-medium">BMS SOC</p>
<div className="flex items-center justify-center gap-1 mt-0.5">
<Cpu className="w-3 h-3 text-emerald-600" />
<span className="text-xs font-bold text-slate-800">{battery.currentSoc}%</span>
</div>
</div>
<div>
<p className="text-[10px] text-emerald-700 font-medium">SOH Health</p>
<p className="text-xs font-bold text-slate-800 mt-0.5">{battery.health}%</p>
</div>
<div>
<p className="text-[10px] text-emerald-700 font-medium">Cycles</p>
<p className="text-xs font-bold text-slate-800 mt-0.5">{battery.cycleCount}</p>
</div>
</div>
{/* Actions block */}
<div className="pt-3 border-t border-slate-100 flex items-center justify-between gap-2">
<button
onClick={() => router.push(`/admin/batteries/${battery.id}`)}
className="p-1.5 text-slate-400 hover:text-slate-600 hover:bg-slate-50 rounded-lg transition-all flex items-center justify-center gap-1 border border-slate-150"
title="View Battery BMS"
>
<Eye className="w-4 h-4 text-emerald-600" /> <span className="text-xs text-slate-500 font-medium">Details</span>
</button>
<div className="flex items-center gap-1">
<button
onClick={() => {
setSelectedBatteryToEdit(battery);
setAssignForm({
batteryId: battery.id,
investmentId: battery.investmentId || '',
deposit: battery.deposit || 5000,
rentPrice: battery.rentPrice || 150,
investorShare: battery.investorSharePercentage || 100,
investedAmount: battery.investedAmount || 45000
});
setShowEditBatteryModal(true);
}}
className="px-2.5 py-1 text-xs font-bold text-slate-600 border border-slate-200 rounded hover:bg-slate-50 transition-all flex items-center gap-1"
>
<Edit className="w-3 h-3" /> Edit
</button>
<button
onClick={() => {
setUnassignConfirmModal({
show: true,
type: 'battery',
id: battery.id,
name: `${battery.brand} ${battery.model}`,
details: battery.serialNumber
});
}}
className="px-2 py-1 text-xs font-bold text-red-600 hover:bg-red-50 rounded transition-all flex items-center gap-0.5"
title="Unassign Battery"
>
<Unlink className="w-3.5 h-3.5" /> Remove
</button>
</div>
</div>
</div>
</div>
);
})}
{batteries.filter(b => b.investorId === investorId).length === 0 && (
<div className="col-span-full text-center py-16 bg-slate-50 border-2 border-dashed border-slate-200 rounded-xl">
<Battery className="w-12 h-12 mx-auto mb-3 text-slate-300 animate-bounce" />
<h4 className="font-semibold text-slate-600 mb-2">No Batteries Assigned</h4>
<p className="text-slate-400 mb-4">Link high-yield battery pack assets to this partner</p>
<button
onClick={() => {
const batInv = investor.investments?.find((inv: any) => inv.assetType === 'battery' || inv.planName.toLowerCase().includes('battery')) || investor.investments?.[0];
setAssignForm({
batteryId: '',
investmentId: batInv?.id || '',
deposit: 5000,
rentPrice: 150,
investorShare: 100,
investedAmount: 45000
});
setShowAssignBatteryModal(true);
}}
className="px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-semibold hover:bg-emerald-700"
>
Assign First Battery
</button>
</div>
)}
</div>
</div>
)}
{activeTab === 'investments' && (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h3 className="font-semibold text-slate-800">EV Investment Plans</h3>
<p className="text-sm text-slate-500">Manage investment portfolios for this investor</p>
</div>
<button onClick={() => setShowCreateInvestmentModal(true)} className="py-2 px-4 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-2">
<Plus className="w-4 h-4" /> Create Investment
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{investor.investments?.map((inv) => {
const planConfig: Record<string, { bg: string; border: string; icon: string }> = {
silver: { bg: 'bg-slate-100', border: 'border-slate-300', icon: 'text-slate-500' },
gold: { bg: 'bg-amber-100', border: 'border-amber-300', icon: 'text-amber-500' },
platinum: { bg: 'bg-purple-100', border: 'border-purple-300', icon: 'text-purple-500' },
diamond: { bg: 'bg-blue-100', border: 'border-blue-300', icon: 'text-blue-500' },
};
const style = planConfig[inv.planType] || planConfig.gold;
return (
<div key={inv.id} className={`bg-white rounded-xl border ${style.border} overflow-hidden`}>
<div className={`${style.bg} p-4 flex items-center justify-between`}>
<div>
<h4 className="font-semibold text-slate-800">{inv.planName}</h4>
<p className="text-sm text-slate-500 capitalize">{inv.planType} Plan</p>
</div>
<span className={`text-xs font-medium px-2.5 py-1 rounded-full ${inv.status === 'active' ? 'bg-green-100 text-green-700' : 'bg-slate-200 text-slate-600'}`}>
{inv.status}
</span>
</div>
<div className="p-4 space-y-4">
<div className="grid grid-cols-2 gap-3">
<div className="bg-slate-50 rounded-lg p-3">
<p className="text-xs text-slate-500">Investment</p>
<p className="font-bold text-slate-800">{inv.totalInvestment.toLocaleString()}</p>
</div>
<div className="bg-purple-50 rounded-lg p-3">
<p className="text-xs text-purple-600">Total Return</p>
<p className="font-bold text-purple-700">{inv.actualEarnings.toLocaleString()}</p>
</div>
</div>
<div className="bg-slate-50 rounded-lg p-3 space-y-1.5">
<div className="flex justify-between text-xs">
<span className="text-slate-400">Duration</span>
<span className="font-medium">12 months</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-slate-400">Lock-in Period</span>
<span className="font-medium">3 months</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-slate-400">Early Exit Penalty</span>
<span className="font-medium text-red-500">10%</span>
</div>
</div>
<div className="flex items-center justify-between text-sm">
<span className="text-slate-400">{inv.startDate} - {inv.endDate || 'Ongoing'}</span>
<span className="capitalize text-slate-500">{inv.paymentMethod}</span>
</div>
<div className="pt-3 border-t border-slate-100">
<p className="text-xs text-slate-400 mb-2">ID: #{inv.id?.slice(-6) || 'N/A'}</p>
<div className="flex gap-2">
<Link href={`/admin/investors/${investor.id}/investments/${inv.id}`} className="flex-1 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 rounded-lg border border-slate-200 text-center">
View
</Link>
{/* <Link href={`/admin/investors/${investor.id}/investments/${inv.id}/statement`} className="flex-1 py-2 text-sm font-medium text-investor hover:bg-investor/10 rounded-lg border border-investor/30 text-center flex items-center justify-center gap-1">
<Printer className="w-4 h-4" /> Statement
</Link> */}
</div>
</div>
</div>
</div>
);
})}
</div>
{(!investor.investments || investor.investments.length === 0) && (
<div className="text-center py-16 bg-slate-50 rounded-xl border-2 border-dashed border-slate-200">
<TrendingUp className="w-12 h-12 mx-auto mb-3 text-slate-300" />
<h4 className="font-semibold text-slate-600 mb-2">No Investments Yet</h4>
<p className="text-slate-400 mb-4">Create your first investment plan for this investor</p>
<button onClick={() => setShowCreateInvestmentModal(true)} className="px-4 py-2 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark">
<Plus className="w-4 h-4 inline mr-1" /> Create Investment
</button>
</div>
)}
</div>
)}
{activeTab === 'financial' && (
<div className="space-y-6">
<div className="grid lg:grid-cols-2 gap-6">
<div>
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-800">Bank Accounts ({investor.bankAccounts?.length || 0})</h3>
<button onClick={() => {
setEditingBankAccount({ id: '', bankName: '', accountName: '', accountNumber: '', branch: '', routing: '', isPrimary: false });
setShowBankModal(true);
}} className="text-sm text-investor hover:underline flex items-center gap-1">
<Plus className="w-4 h-4" /> Add Account
</button>
</div>
<div className="space-y-3">
{investor.bankAccounts && investor.bankAccounts.length > 0 ? (
investor.bankAccounts.map((account: any) => (
<div key={account.id} className="p-4 bg-white border border-slate-200 rounded-xl hover:shadow-md transition-all">
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg flex items-center justify-center bg-slate-100">
<Banknote className="w-5 h-5 text-slate-500" />
</div>
<div>
<p className="font-semibold text-slate-800">{account.bankName}</p>
<p className="text-xs text-slate-500">{account.branch}</p>
</div>
</div>
<button onClick={() => {
setEditingBankAccount(account);
setShowBankModal(true);
}} className="p-1.5 hover:bg-slate-100 rounded-lg text-slate-500">
<Edit className="w-4 h-4" />
</button>
</div>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-slate-500">Account Name</span>
<span className="font-medium text-slate-700">{account.accountName}</span>
</div>
<div className="flex justify-between">
<span className="text-slate-500">Account Number</span>
<span className="font-mono text-slate-700">{account.accountNumber}</span>
</div>
{account.routing && (
<div className="flex justify-between">
<span className="text-slate-500">Routing</span>
<span className="font-medium text-slate-700">{account.routing}</span>
</div>
)}
</div>
</div>
))
) : (
<div className="text-center py-10 border-2 border-dashed border-slate-200 rounded-xl">
<Banknote className="w-10 h-10 mx-auto mb-3 text-slate-300" />
<p className="text-sm text-slate-500 mb-2">No bank accounts added</p>
<button onClick={() => {
setEditingBankAccount({ id: '', bankName: '', accountName: '', accountNumber: '', branch: '', routing: '', isPrimary: false });
setShowBankModal(true);
}} className="px-4 py-2 text-sm bg-investor text-white rounded-lg hover:bg-investor-dark">
Add First Account
</button>
</div>
)}
</div>
</div>
<div>
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-800">Mobile Banking</h3>
<button onClick={() => {
setEditingMobileBanking({ provider: '', number: '', isPrimary: !investor.mobileBanking });
setEditingMobileIndex(null);
setShowMobileBankingModal(true);
}} className="text-sm text-investor hover:underline flex items-center gap-1">
<Plus className="w-4 h-4" /> Add
</button>
</div>
<div className="space-y-3">
{investor.mobileBanking ? (
<div className="flex items-center gap-3 p-3 bg-purple-50 rounded-lg">
<Phone className="w-5 h-5 text-purple-500" />
<div className="flex-1">
<p className="text-xs text-purple-600 font-medium">{investor.mobileBanking}</p>
<p className="text-xs text-slate-400">{investor.mobileBankingNumber}</p>
</div>
<button onClick={() => {
setEditingMobileBanking({ provider: investor.mobileBanking || '', number: investor.mobileBankingNumber || '', isPrimary: true });
setEditingMobileIndex(-1);
setShowMobileBankingModal(true);
}} className="p-1 hover:bg-purple-100 rounded">
<Edit className="w-4 h-4 text-purple-500" />
</button>
</div>
) : null}
{investor.additionalMobileBanking?.map((mb, idx) => (
<div key={idx} className="flex items-center gap-3 p-3 bg-slate-50 rounded-lg">
<Phone className="w-5 h-5 text-slate-400" />
<div className="flex-1">
<p className="text-xs text-slate-500">{mb.provider}</p>
<p className="font-medium text-slate-700">{mb.number}</p>
</div>
{mb.verified ? (
<span className="text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full">Verified</span>
) : (
<span className="text-xs bg-amber-100 text-amber-700 px-2 py-1 rounded-full">Pending</span>
)}
<button onClick={() => {
setEditingMobileBanking({ provider: mb.provider, number: mb.number, isPrimary: false });
setEditingMobileIndex(idx);
setShowMobileBankingModal(true);
}} className="p-1 hover:bg-slate-200 rounded">
<Edit className="w-4 h-4 text-slate-400" />
</button>
<button onClick={() => alert(`Delete mobile banking ${mb.provider}`)} className="p-1 hover:bg-red-50 rounded">
<Trash2 className="w-4 h-4 text-red-400" />
</button>
</div>
))}
{(!investor.mobileBanking && (!investor.additionalMobileBanking || investor.additionalMobileBanking.length === 0)) && (
<div className="text-center py-8 text-slate-400 border-2 border-dashed border-slate-200 rounded-lg">
<Phone className="w-8 h-8 mx-auto mb-2 opacity-50" />
<p className="text-sm">No mobile banking added</p>
</div>
)}
</div>
<div className="flex items-center justify-between mb-4 mt-6">
<h3 className="font-semibold text-slate-800">Tax Information</h3>
<button onClick={() => {
setEditingTax({
tinNumber: investor.tinNumber || '',
passportNumber: investor.passportNumber || ''
});
setShowTaxModal(true);
}} className="text-sm text-investor hover:underline flex items-center gap-1">
<Edit className="w-4 h-4" /> {investor.tinNumber || investor.passportNumber ? 'Edit' : 'Add'}
</button>
</div>
<div className="space-y-3">
{investor.tinNumber || investor.passportNumber ? (
<>
{investor.tinNumber && (
<div className="flex items-center gap-3 p-3 bg-slate-50 rounded-lg">
<FileText className="w-5 h-5 text-slate-400" />
<div>
<p className="text-xs text-slate-500">TIN</p>
<p className="font-medium text-slate-700">{investor.tinNumber}</p>
</div>
</div>
)}
{investor.passportNumber && (
<div className="flex items-center gap-3 p-3 bg-slate-50 rounded-lg">
<FileText className="w-5 h-5 text-slate-400" />
<div>
<p className="text-xs text-slate-500">Passport</p>
<p className="font-medium text-slate-700">{investor.passportNumber}</p>
</div>
</div>
)}
</>
) : (
<div className="text-center py-8 text-slate-400 border-2 border-dashed border-slate-200 rounded-lg">
<FileText className="w-8 h-8 mx-auto mb-2 opacity-50" />
<p className="text-sm">No tax info added</p>
</div>
)}
</div>
</div>
</div>
<div>
<h3 className="font-semibold text-slate-800 mb-4">Investment Summary</h3>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
<div className="bg-purple-50 rounded-lg p-4">
<p className="text-sm text-purple-600">Total Invested</p>
<p className="text-xl font-bold text-purple-700">{investor.totalInvested.toLocaleString()}</p>
</div>
<div className="bg-green-50 rounded-lg p-4">
<p className="text-sm text-green-600">Total Earnings</p>
<p className="text-xl font-bold text-green-700">{investor.totalEarnings.toLocaleString()}</p>
</div>
<div className="bg-amber-50 rounded-lg p-4">
<p className="text-sm text-amber-600">Pending Earnings</p>
<p className="text-xl font-bold text-amber-700">{investor.pendingEarnings.toLocaleString()}</p>
</div>
<div className="bg-slate-50 rounded-lg p-4">
<p className="text-sm text-slate-600">Total Withdrawn</p>
<p className="text-xl font-bold text-slate-700">{investor.totalWithdrawn.toLocaleString()}</p>
</div>
</div>
</div>
</div>
)}
{activeTab === 'transactions' && (
<div>
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-800">All Transactions</h3>
<div className="flex gap-2">
<button onClick={() => setShowWithdrawalModal(true)} className="py-2 px-3 bg-red-500 text-white rounded-lg text-sm font-medium hover:bg-red-600 flex items-center gap-1">
<Banknote className="w-4 h-4" /> Request Withdrawal
</button>
<button className="py-2 px-3 border border-slate-200 text-slate-600 rounded-lg text-sm font-medium hover:bg-slate-50 flex items-center gap-1">
<Download className="w-4 h-4" /> Export
</button>
</div>
</div>
<div className="mb-6">
<h4 className="font-semibold text-slate-700 mb-3">Pending Withdrawals</h4>
<div className="space-y-2">
{investorTransactions.filter(t => t.type === 'withdrawal' && t.status === 'pending').map(tx => (
<div key={tx.id} className="flex items-center justify-between p-4 bg-amber-50 border border-amber-200 rounded-lg">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center">
<Banknote className="w-6 h-6 text-red-600" />
</div>
<div>
<p className="text-sm font-medium text-slate-700">{tx.description}</p>
<p className="text-xs text-amber-600">Ref: {tx.referenceNumber || tx.id} {tx.createdAt}</p>
</div>
</div>
<div className="text-right">
<p className="text-lg font-bold text-red-600">-{tx.amount.toLocaleString()}</p>
<span className="text-xs font-medium px-2 py-1 rounded-full bg-amber-100 text-amber-700">
Pending
</span>
</div>
</div>
))}
{investorTransactions.filter(t => t.type === 'withdrawal' && t.status === 'pending').length === 0 && (
<div className="text-center py-4 text-slate-400 border border-dashed border-slate-200 rounded-lg">
<p className="text-sm">No pending withdrawals</p>
</div>
)}
</div>
</div>
<div>
<h4 className="font-semibold text-slate-700 mb-3">Transaction History</h4>
<div className="space-y-2">
{investorTransactions.map(tx => {
const getAccountingInfo = (type: string, amount: number) => {
if (type === 'investment') {
return {
debitAccount: 'Bank - City Bank (1200)',
creditAccount: 'Investor Liabilities (2200)',
amount: amount
};
} else if (type === 'earning' || type === 'bike_earning' || type === 'investment_return') {
return {
debitAccount: 'Investor Liabilities (2200)',
creditAccount: 'Rental Income (4200)',
amount: amount
};
} else if (type === 'withdrawal') {
return {
debitAccount: 'Investor Liabilities (2200)',
creditAccount: 'Bank - City Bank (1200)',
amount: amount
};
}
return {
debitAccount: 'N/A',
creditAccount: 'N/A',
amount: amount
};
};
return (
<div key={tx.id} className="flex items-center justify-between p-3 bg-slate-50 rounded-lg">
<div className="flex items-center gap-3">
<div className={`w-10 h-10 rounded-full flex items-center justify-center ${tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' ? 'bg-green-100' :
tx.type === 'withdrawal' ? 'bg-red-100' :
tx.type === 'investment' ? 'bg-purple-100' :
tx.type === 'referral_bonus' ? 'bg-yellow-100' :
tx.type === 'adjustment' || tx.type === 'penalty' ? 'bg-orange-100' : 'bg-blue-100'
}`}>
<DollarSign className={`w-5 h-5 ${tx.type === 'earning' || tx.type === 'bike_earning' ? 'text-green-600' :
tx.type === 'withdrawal' ? 'text-red-600' :
tx.type === 'investment' ? 'text-purple-600' :
tx.type === 'referral_bonus' ? 'text-yellow-600' :
tx.type === 'adjustment' || tx.type === 'penalty' ? 'text-orange-600' : 'text-blue-600'
}`} />
</div>
<div>
<p className="text-sm font-medium text-slate-700">{tx.description}</p>
<div className="flex items-center gap-2">
<p className="text-xs text-slate-400">{tx.createdAt}</p>
{tx.referenceNumber && (
<button
onClick={() => {
const accounting = getAccountingInfo(tx.type, tx.amount);
setSelectedInvoice({
reference: tx.referenceNumber,
date: tx.createdAt,
type: tx.type,
amount: tx.amount,
description: tx.description,
status: tx.status,
investorName: investor.name,
investorId: investor.id,
debitAccount: accounting.debitAccount,
creditAccount: accounting.creditAccount
});
setShowInvoiceModal(true);
}}
className="text-xs text-investor hover:underline flex items-center gap-1"
>
Ref: {tx.referenceNumber}
<BookOpen className="w-3 h-3" />
</button>
)}
</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className="text-right">
<p className={`text-lg font-bold ${tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' || tx.type === 'referral_bonus' ? 'text-green-600' : 'text-red-600'}`}>
{tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' || tx.type === 'referral_bonus' ? '+' : '-'}{tx.amount.toLocaleString()}
</p>
<span className={`text-xs font-medium px-2 py-1 rounded-full ${tx.status === 'completed' ? 'bg-green-100 text-green-700' :
tx.status === 'pending' ? 'bg-amber-100 text-amber-700' : 'bg-slate-100 text-slate-600'
}`}>
{tx.status}
</span>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
)}
{activeTab === 'documents' && (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h3 className="font-semibold text-slate-800">KYC Documents</h3>
<p className="text-sm text-slate-500">Manage investor verification documents</p>
</div>
<button onClick={() => setShowDocModal(true)} className="px-4 py-2 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-2">
<Plus className="w-4 h-4" /> Upload Document
</button>
</div>
<div className="space-y-2">
{investor.kycDocuments?.map((doc, idx) => (
<div key={idx} className="flex items-center justify-between p-4 bg-white border border-slate-200 rounded-xl">
<div className="flex items-center gap-3">
<div className={`w-12 h-12 rounded-lg flex items-center justify-center ${doc.type === 'nid' ? 'bg-blue-100' :
doc.type === 'passport' ? 'bg-purple-100' :
doc.type === 'bank_statement' ? 'bg-green-100' :
doc.type === 'tin_certificate' ? 'bg-amber-100' : 'bg-slate-100'
}`}>
<FileText className={`w-6 h-6 ${doc.type === 'nid' ? 'text-blue-600' :
doc.type === 'passport' ? 'text-purple-600' :
doc.type === 'bank_statement' ? 'text-green-600' :
doc.type === 'tin_certificate' ? 'text-amber-600' : 'text-slate-600'
}`} />
</div>
<div>
<p className="text-sm font-medium text-slate-700 capitalize">{doc.type.replace('_', ' ')}</p>
<p className="text-xs text-slate-400">{doc.number || 'No document number'} Uploaded: {doc.uploadedAt || 'N/A'}</p>
</div>
</div>
<div className="flex items-center gap-2">
{doc.verified ? (
<span className="flex items-center gap-1 text-xs font-medium px-3 py-1.5 rounded-full bg-green-100 text-green-700">
<CheckCircle className="w-3 h-3" /> Verified
</span>
) : (
<span className="flex items-center gap-1 text-xs font-medium px-3 py-1.5 rounded-full bg-amber-100 text-amber-700">
<Clock className="w-3 h-3" /> Pending Review
</span>
)}
<button onClick={() => alert('Edit document')} className="p-2 hover:bg-slate-100 rounded-lg">
<Edit className="w-4 h-4 text-slate-400" />
</button>
<button onClick={() => { if (confirm('Delete this document?')) alert('Document deleted'); }} className="p-2 hover:bg-red-50 rounded-lg">
<Trash2 className="w-4 h-4 text-red-400" />
</button>
</div>
</div>
))}
{(!investor.kycDocuments || investor.kycDocuments.length === 0) && (
<div className="text-center py-12 text-slate-400 border-2 border-dashed border-slate-200 rounded-lg">
<FileText className="w-12 h-12 mx-auto mb-2 opacity-50" />
<p>No documents uploaded yet</p>
</div>
)}
</div>
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<h4 className="font-semibold text-blue-800 mb-2">KYC Status: {investor.kycStatus.toUpperCase()}</h4>
<p className="text-sm text-blue-700">
{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.'}
</p>
</div>
</div>
)}
{activeTab === 'rentals' && (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h3 className="font-semibold text-slate-800">Daily Rental History</h3>
<p className="text-sm text-slate-500">Track daily rental payments for investor's bikes</p>
</div>
<button className="px-4 py-2 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-2">
<Download className="w-4 h-4" /> Export
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="bg-white rounded-xl border border-slate-200 p-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center">
<DollarSign className="w-5 h-5 text-green-600" />
</div>
<div>
<p className="text-sm text-slate-500">Total Collected</p>
<p className="text-xl font-bold text-green-600">৳{investorRentalPayments.filter(p => p.status === 'paid').reduce((sum, p) => sum + p.amount, 0).toLocaleString()}</p>
</div>
</div>
</div>
<div className="bg-white rounded-xl border border-slate-200 p-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
<Bike className="w-5 h-5 text-blue-600" />
</div>
<div>
<p className="text-sm text-slate-500">Active Rentals</p>
<p className="text-xl font-bold text-slate-800">{new Set(investorRentalPayments.filter(p => p.status === 'paid').map(p => p.bikeId)).size}</p>
</div>
</div>
</div>
<div className="bg-white rounded-xl border border-slate-200 p-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-amber-100 rounded-lg flex items-center justify-center">
<Clock className="w-5 h-5 text-amber-600" />
</div>
<div>
<p className="text-sm text-slate-500">Pending</p>
<p className="text-xl font-bold text-amber-600">৳{investorRentalPayments.filter(p => p.status === 'pending').reduce((sum, p) => sum + p.amount, 0).toLocaleString()}</p>
</div>
</div>
</div>
<div className="bg-white rounded-xl border border-slate-200 p-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-red-100 rounded-lg flex items-center justify-center">
<AlertTriangle className="w-5 h-5 text-red-600" />
</div>
<div>
<p className="text-sm text-slate-500">Failed</p>
<p className="text-xl font-bold text-red-600">৳{investorRentalPayments.filter(p => p.status === 'failed').reduce((sum, p) => sum + p.amount, 0).toLocaleString()}</p>
</div>
</div>
</div>
</div>
<div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
<div className="p-4 border-b border-slate-100 flex items-center justify-between">
<div className="flex items-center gap-2">
<h4 className="font-semibold text-slate-800">Daily Payment Records</h4>
<span className="px-2 py-1 bg-slate-100 text-slate-600 text-xs rounded-full">{investorRentalPayments.length} records</span>
</div>
<div className="flex items-center gap-2">
<select className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm">
<option value="all">All Bikes</option>
{assignedBikes.map((bike: any) => (
<option key={bike.id} value={bike.id}>{bike.model}</option>
))}
</select>
<select className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm">
<option value="all">All Plans</option>
<option value="single">Single Rent</option>
<option value="rent-to-own">Rent to Own</option>
<option value="share_ev">Share EV</option>
</select>
<select className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm">
<option value="all">All Status</option>
<option value="paid">Paid</option>
<option value="pending">Pending</option>
<option value="failed">Failed</option>
</select>
</div>
</div>
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-slate-50">
<tr>
<th
onClick={() => {
if (rentalSortBy === 'date') {
setRentalSortOrder(rentalSortOrder === 'asc' ? 'desc' : 'asc');
} else {
setRentalSortBy('date');
setRentalSortOrder('desc');
}
}}
className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase cursor-pointer hover:bg-slate-100"
>
<div className="flex items-center gap-1">
Date
{rentalSortBy === 'date' && (
<span className="text-investor">{rentalSortOrder === 'asc' ? '' : ''}</span>
)}
</div>
</th>
<th
onClick={() => {
if (rentalSortBy === 'bike') {
setRentalSortOrder(rentalSortOrder === 'asc' ? 'desc' : 'asc');
} else {
setRentalSortBy('bike');
setRentalSortOrder('asc');
}
}}
className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase cursor-pointer hover:bg-slate-100"
>
<div className="flex items-center gap-1">
Bike
{rentalSortBy === 'bike' && (
<span className="text-investor">{rentalSortOrder === 'asc' ? '' : ''}</span>
)}
</div>
</th>
<th className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase">Biker</th>
<th className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase">Plan</th>
<th className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase">Duration</th>
<th
onClick={() => {
if (rentalSortBy === 'amount') {
setRentalSortOrder(rentalSortOrder === 'asc' ? 'desc' : 'asc');
} else {
setRentalSortBy('amount');
setRentalSortOrder('desc');
}
}}
className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase cursor-pointer hover:bg-slate-100"
>
<div className="flex items-center gap-1">
Amount
{rentalSortBy === 'amount' && (
<span className="text-investor">{rentalSortOrder === 'asc' ? '' : ''}</span>
)}
</div>
</th>
<th className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase">Method</th>
<th className="px-4 py-3 text-left text-xs font-medium text-slate-500 uppercase">Status</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-100">
{(() => {
const sortedPayments = [...investorRentalPayments].sort((a, b) => {
if (rentalSortBy === 'date') {
return rentalSortOrder === 'asc'
? new Date(a.date).getTime() - new Date(b.date).getTime()
: new Date(b.date).getTime() - new Date(a.date).getTime();
} else if (rentalSortBy === 'bike') {
return rentalSortOrder === 'asc'
? a.bikeModel.localeCompare(b.bikeModel)
: b.bikeModel.localeCompare(a.bikeModel);
} else if (rentalSortBy === 'amount') {
return rentalSortOrder === 'asc'
? a.amount - b.amount
: b.amount - a.amount;
}
return 0;
});
const totalPages = Math.ceil(sortedPayments.length / rentalPageSize);
const paginatedPayments = sortedPayments.slice(
(rentalPage - 1) * rentalPageSize,
rentalPage * rentalPageSize
);
return paginatedPayments.map((payment: any) => {
const planColors: Record<string, { label: string; bg: string; color: string }> = {
single: { label: 'Single Rent', bg: 'bg-green-100', color: 'text-green-700' },
'rent-to-own': { label: 'Rent to Own', bg: 'bg-blue-100', color: 'text-blue-700' },
share_ev: { label: 'Share EV', bg: 'bg-purple-100', color: 'text-purple-700' },
};
const statusConfig: Record<string, { label: string; bg: string; color: string }> = {
paid: { label: 'Paid', bg: 'bg-green-100', color: 'text-green-700' },
pending: { label: 'Pending', bg: 'bg-amber-100', color: 'text-amber-700' },
failed: { label: 'Failed', bg: 'bg-red-100', color: 'text-red-700' },
};
const plan = planColors[payment.planType] || planColors.single;
const status = statusConfig[payment.status] || statusConfig.pending;
return (
<tr key={payment.id} className="hover:bg-slate-50">
<td className="px-4 py-3">
<div>
<p className="text-sm font-medium text-slate-800">{payment.date}</p>
<p className="text-xs text-slate-400">{payment.transactionId || payment.id}</p>
</div>
</td>
<td className="px-4 py-3">
<div className="flex items-center gap-2">
<Bike className="w-4 h-4 text-slate-400" />
<div>
<p className="text-sm font-medium text-slate-800">{payment.bikeModel}</p>
<p className="text-xs text-slate-400">{payment.plateNumber}</p>
</div>
</div>
</td>
<td className="px-4 py-3">
<div className="flex items-center gap-2">
<User className="w-4 h-4 text-slate-400" />
<span className="text-sm text-slate-700">{payment.bikerName}</span>
</div>
</td>
<td className="px-4 py-3">
<span className={`px-2 py-1 rounded-full text-xs font-medium ${plan.bg} ${plan.color}`}>
{plan.label}
</span>
</td>
<td className="px-4 py-3">
<span className="text-sm text-slate-600">{payment.duration}</span>
</td>
<td className="px-4 py-3">
<p className="text-sm font-bold text-slate-800">৳{payment.amount.toLocaleString()}</p>
</td>
<td className="px-4 py-3">
<span className="text-sm text-slate-600 capitalize">{payment.paymentMethod}</span>
</td>
<td className="px-4 py-3">
<span className={`px-2 py-1 rounded-full text-xs font-medium ${status.bg} ${status.color}`}>
{status.label}
</span>
</td>
</tr>
);
});
})()}
</tbody>
</table>
{investorRentalPayments.length === 0 && (
<div className="text-center py-12 text-slate-400">
<DollarSign className="w-12 h-12 mx-auto mb-2 opacity-50" />
<p>No rental payments found</p>
</div>
)}
</div>
{investorRentalPayments.length > rentalPageSize && (
<div className="p-4 border-t border-slate-100 flex items-center justify-between">
<p className="text-sm text-slate-500">
Showing {((rentalPage - 1) * rentalPageSize) + 1} to {Math.min(rentalPage * rentalPageSize, investorRentalPayments.length)} of {investorRentalPayments.length}
</p>
<div className="flex items-center gap-2">
<button
onClick={() => setRentalPage(p => Math.max(1, p - 1))}
disabled={rentalPage === 1}
className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm disabled:opacity-50 disabled:cursor-not-allowed hover:bg-slate-50"
>
Previous
</button>
{Array.from({ length: Math.ceil(investorRentalPayments.length / rentalPageSize) }, (_, i) => i + 1).map(page => (
<button
key={page}
onClick={() => setRentalPage(page)}
className={`px-3 py-1.5 border rounded-lg text-sm ${rentalPage === page
? 'bg-investor text-white border-investor'
: 'border-slate-200 hover:bg-slate-50'
}`}
>
{page}
</button>
))}
<button
onClick={() => setRentalPage(p => Math.min(Math.ceil(investorRentalPayments.length / rentalPageSize), p + 1))}
disabled={rentalPage === Math.ceil(investorRentalPayments.length / rentalPageSize)}
className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm disabled:opacity-50 disabled:cursor-not-allowed hover:bg-slate-50"
>
Next
</button>
</div>
</div>
)}
</div>
</div>
)}
</div>
</div>
{showWithdrawalModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800 flex items-center gap-2">
<Banknote className="w-5 h-5 text-red-500" /> Request Withdrawal
</h2>
<button onClick={() => setShowWithdrawalModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 overflow-y-auto flex-1 space-y-6">
<div className="grid grid-cols-3 gap-4">
<div className="bg-green-50 rounded-lg p-4 border border-green-100">
<p className="text-xs text-green-600 font-medium">Available Balance</p>
<p className="text-lg font-bold text-green-700">৳{(investor.totalEarnings - investor.totalWithdrawn - investor.pendingEarnings).toLocaleString()}</p>
</div>
<div className="bg-amber-50 rounded-lg p-4 border border-amber-100">
<p className="text-xs text-amber-600 font-medium">Pending Request</p>
<p className="text-lg font-bold text-amber-700">৳{investor.pendingEarnings.toLocaleString()}</p>
</div>
<div className="bg-slate-50 rounded-lg p-4 border border-slate-100">
<p className="text-xs text-slate-600 font-medium">Total Withdrawn</p>
<p className="text-lg font-bold text-slate-700">৳{investor.totalWithdrawn.toLocaleString()}</p>
</div>
</div>
<div>
<h4 className="font-semibold text-slate-800 mb-3">Select EV Investment Plans & Bikes</h4>
<div className="space-y-4">
<div className="flex items-center gap-3 p-4 bg-slate-50 rounded-lg border border-slate-200">
<input
type="checkbox"
id="selectAll"
checked={withdrawSelection.selectAll}
onChange={(e) => {
setWithdrawSelection({
...withdrawSelection,
selectAll: e.target.checked,
selectedPlans: e.target.checked ? investor.investments?.map((inv: any) => inv.id) || [] : [],
selectedBikes: e.target.checked ? assignedBikes.map(b => b.id) : []
});
}}
className="w-4 h-4 text-investor rounded"
/>
<label htmlFor="selectAll" className="flex-1">
<span className="font-medium text-slate-800">Select All</span>
<p className="text-xs text-slate-500">Include all investments and bikes</p>
</label>
</div>
<div className="border border-slate-200 rounded-lg overflow-hidden">
<div className="bg-slate-50 px-4 py-2 border-b border-slate-200">
<p className="text-sm font-medium text-slate-700">EV Investment Plans</p>
</div>
<div className="divide-y divide-slate-100">
{investor.investments?.map((inv: any) => {
const planColors: Record<string, string> = {
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 invBikes = assignedBikes.filter(b => b.investmentId === inv.id);
const invEarnings = invBikes.reduce((sum: number, b: any) => sum + (b.totalEarnings || 0), 0);
return (
<div key={inv.id} className="p-4">
<div className="flex items-center gap-3 mb-2">
<input
type="checkbox"
id={`plan-${inv.id}`}
checked={withdrawSelection.selectAll || withdrawSelection.selectedPlans.includes(inv.id)}
disabled={withdrawSelection.selectAll}
onChange={(e) => {
const newPlans = e.target.checked
? [...withdrawSelection.selectedPlans, inv.id]
: withdrawSelection.selectedPlans.filter((p: string) => p !== inv.id);
const newBikes = e.target.checked
? [...new Set([...withdrawSelection.selectedBikes, ...invBikes.map((b: any) => b.id)])]
: withdrawSelection.selectedBikes.filter((b: string) => !invBikes.find((ib: any) => ib.id === b));
setWithdrawSelection({ ...withdrawSelection, selectedPlans: newPlans, selectedBikes: newBikes });
}}
className="w-4 h-4 text-investor rounded"
/>
<label htmlFor={`plan-${inv.id}`} className="flex-1 flex items-center justify-between">
<div>
<span className="font-medium text-slate-800">{inv.planName}</span>
<span className={`ml-2 px-2 py-0.5 rounded text-xs capitalize ${planColors[inv.planType]}`}>{inv.planType}</span>
</div>
<span className="text-sm font-bold text-green-600">৳{invEarnings.toLocaleString()}</span>
</label>
</div>
{!withdrawSelection.selectAll && invBikes.length > 0 && (
<div className="ml-7 pl-4 border-l-2 border-slate-200 space-y-2">
{invBikes.map((bike: any) => (
<div key={bike.id} className="flex items-center gap-2">
<input
type="checkbox"
id={`bike-${bike.id}`}
checked={withdrawSelection.selectedBikes.includes(bike.id)}
onChange={(e) => {
const newBikes = e.target.checked
? [...withdrawSelection.selectedBikes, bike.id]
: withdrawSelection.selectedBikes.filter((b: string) => b !== bike.id);
setWithdrawSelection({ ...withdrawSelection, selectedBikes: newBikes });
}}
className="w-3 h-3 text-investor rounded"
/>
<label htmlFor={`bike-${bike.id}`} className="flex-1 text-sm text-slate-600">
{bike.model} - {bike.plateNumber}
</label>
<span className="text-xs text-green-600 font-medium">৳{bike.totalEarnings?.toLocaleString() || 0}</span>
</div>
))}
</div>
)}
</div>
);
})}
</div>
</div>
</div>
</div>
<div>
<h4 className="font-semibold text-slate-800 mb-3">Withdrawal Amount</h4>
<div className="bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 rounded-xl p-5">
<div className="flex items-center justify-between mb-2">
<span className="text-sm text-slate-600">Calculated Amount</span>
<span className={`text-xs px-2 py-0.5 rounded-full ${withdrawSelection.selectAll ? 'bg-green-100 text-green-700' : 'bg-amber-100 text-amber-700'}`}>
{withdrawSelection.selectAll ? 'All Selected' : `${withdrawSelection.selectedBikes.length} bikes`}
</span>
</div>
<p className="text-3xl font-bold text-green-700 mb-1">
৳{(withdrawSelection.selectAll
? assignedBikes.reduce((sum: number, b: any) => sum + (b.totalEarnings || 0), 0)
: withdrawSelection.selectedBikes.reduce((sum: number, bikeId: string) => {
const bike = assignedBikes.find((b: any) => b.id === bikeId);
return sum + (bike?.totalEarnings || 0);
}, 0)
).toLocaleString()}
</p>
<p className="text-xs text-slate-500">
Based on {withdrawSelection.selectAll ? 'all' : withdrawSelection.selectedBikes.length} selected bike(s) earnings
</p>
</div>
</div>
<div>
<h4 className="font-semibold text-slate-800 mb-3">Payment Method</h4>
<div className="grid grid-cols-2 gap-3">
{investor.bankAccounts?.map((account: any) => (
<div
key={account.id}
onClick={() => setWithdrawSelection({ ...withdrawSelection, paymentMethod: 'bank', accountId: account.id })}
className={`p-4 rounded-lg border cursor-pointer transition-all ${withdrawSelection.accountId === account.id ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`}
>
<div className="flex items-center gap-2 mb-1">
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${account.isPrimary ? 'bg-green-100' : 'bg-slate-100'}`}>
<Banknote className={`w-4 h-4 ${account.isPrimary ? 'text-green-600' : 'text-slate-500'}`} />
</div>
<div>
<p className="text-sm font-medium text-slate-800">{account.bankName}</p>
{account.isPrimary && <span className="text-xs text-green-600">Primary</span>}
</div>
</div>
<p className="text-xs text-slate-500">{account.accountNumber}</p>
</div>
))}
</div>
{investor.mobileBanking && (
<div
onClick={() => setWithdrawSelection({ ...withdrawSelection, paymentMethod: 'mobile', accountId: 'mobile' })}
className={`mt-3 p-4 rounded-lg border cursor-pointer transition-all ${withdrawSelection.paymentMethod === 'mobile' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300'}`}
>
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-pink-100 flex items-center justify-center">
<Phone className="w-4 h-4 text-pink-600" />
</div>
<div>
<p className="text-sm font-medium text-slate-800">{investor.mobileBanking}</p>
<p className="text-xs text-slate-500">{investor.mobileBankingNumber}</p>
</div>
</div>
</div>
)}
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-between items-center">
<button
onClick={() => { setShowWithdrawalModal(false); setShowAutoWithdrawModal(true); }}
className="px-4 py-2 text-sm text-slate-600 hover:text-investor flex items-center gap-1"
>
<Settings className="w-4 h-4" /> Configure Auto-Withdraw
</button>
<div className="flex gap-3">
<button onClick={() => setShowWithdrawalModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
Cancel
</button>
<button
disabled={!withdrawSelection.accountId || (withdrawSelection.selectedPlans.length === 0 && !withdrawSelection.selectAll)}
className="px-6 py-2 bg-red-500 text-white rounded-lg text-sm font-medium hover:bg-red-600 disabled:opacity-50 disabled:cursor-not-allowed"
>
Submit Request
</button>
</div>
</div>
</div>
</div>
)}
{showAutoWithdrawModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800 flex items-center gap-2">
<Settings className="w-5 h-5 text-investor" /> Auto-Withdraw Settings
</h2>
<button onClick={() => setShowAutoWithdrawModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 space-y-5">
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
<div>
<p className="font-medium text-slate-800">Enable Auto-Withdraw</p>
<p className="text-xs text-slate-500">Automatically withdraw earnings</p>
</div>
<button
onClick={() => setAutoWithdrawSettings({ ...autoWithdrawSettings, enabled: !autoWithdrawSettings.enabled })}
className={`w-12 h-6 rounded-full transition-colors ${autoWithdrawSettings.enabled ? 'bg-investor' : 'bg-slate-300'}`}
>
<div className={`w-5 h-5 bg-white rounded-full shadow transition-transform ${autoWithdrawSettings.enabled ? 'translate-x-6' : 'translate-x-0.5'}`} />
</button>
</div>
{autoWithdrawSettings.enabled && (
<>
<div>
<label className="text-sm font-medium text-slate-700 mb-2 block">Withdrawal Frequency</label>
<div className="grid grid-cols-3 gap-2">
{[
{ value: 'as_per_request', label: 'As Requested' },
{ value: 'weekly', label: 'Weekly' },
{ value: 'monthly', label: 'Monthly' }
].map(opt => (
<button
key={opt.value}
onClick={() => setAutoWithdrawSettings({ ...autoWithdrawSettings, frequency: opt.value as any })}
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors ${autoWithdrawSettings.frequency === opt.value ? 'bg-investor text-white' : 'bg-slate-100 text-slate-600 hover:bg-slate-200'}`}
>
{opt.label}
</button>
))}
</div>
</div>
<div>
<label className="text-sm font-medium text-slate-700 mb-2 block">Minimum Amount</label>
<div className="relative">
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500">৳</span>
<input
type="number"
value={autoWithdrawSettings.minAmount}
onChange={(e) => setAutoWithdrawSettings({ ...autoWithdrawSettings, minAmount: Number(e.target.value) })}
className="w-full pl-8 pr-4 py-2 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-investor"
/>
</div>
<p className="text-xs text-slate-400 mt-1">Minimum balance required for auto-withdrawal</p>
</div>
<div>
<label className="text-sm font-medium text-slate-700 mb-2 block">Destination Account</label>
<div className="space-y-2">
{investor.bankAccounts?.map((account: any) => (
<div
key={account.id}
onClick={() => setAutoWithdrawSettings({ ...autoWithdrawSettings, accountId: account.id })}
className={`p-3 rounded-lg border cursor-pointer flex items-center gap-3 ${autoWithdrawSettings.accountId === account.id ? 'border-investor bg-investor/5' : 'border-slate-200'}`}
>
<div className={`w-4 h-4 rounded-full border-2 ${autoWithdrawSettings.accountId === account.id ? 'border-investor bg-investor' : 'border-slate-300'}`}>
{autoWithdrawSettings.accountId === account.id && <div className="w-full h-full rounded-full bg-white scale-50" />}
</div>
<div>
<p className="text-sm font-medium">{account.bankName}</p>
<p className="text-xs text-slate-500">{account.accountNumber}</p>
</div>
{account.isPrimary && <span className="ml-auto text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded">Primary</span>}
</div>
))}
{investor.mobileBanking && (
<div
onClick={() => setAutoWithdrawSettings({ ...autoWithdrawSettings, accountId: 'mobile' })}
className={`p-3 rounded-lg border cursor-pointer flex items-center gap-3 ${autoWithdrawSettings.accountId === 'mobile' ? 'border-investor bg-investor/5' : 'border-slate-200'}`}
>
<div className={`w-4 h-4 rounded-full border-2 ${autoWithdrawSettings.accountId === 'mobile' ? 'border-investor bg-investor' : 'border-slate-300'}`}>
{autoWithdrawSettings.accountId === 'mobile' && <div className="w-full h-full rounded-full bg-white scale-50" />}
</div>
<div>
<p className="text-sm font-medium">{investor.mobileBanking}</p>
<p className="text-xs text-slate-500">{investor.mobileBankingNumber}</p>
</div>
</div>
)}
</div>
</div>
</>
)}
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowAutoWithdrawModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
Cancel
</button>
<button
onClick={() => { alert('Auto-withdraw settings saved!'); setShowAutoWithdrawModal(false); }}
className="px-4 py-2 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark"
>
Save Settings
</button>
</div>
</div>
</div>
)}
<AssignBatteryModal
isOpen={showAssignBatteryModal}
onClose={() => setShowAssignBatteryModal(false)}
investor={investor}
batteries={batteries}
unassignedBatteries={unassignedBatteries}
onAssign={(planId, batteryIds) => {
const assignedBatteriesList: any[] = [];
setBatteries(prev => prev.map(b => {
if (batteryIds.includes(b.id)) {
assignedBatteriesList.push(b);
return {
...b,
investorId: investorId,
investorName: investor.name,
investmentId: planId,
status: 'in-use',
investedAmount: b.purchasePrice || 45000,
investorSharePercentage: 100,
deposit: b.deposit || 5000,
rentPrice: b.rentPrice || 150
};
}
return b;
}));
setUnassignedBatteries(prev => prev.filter(b => !batteryIds.includes(b.id)));
setInvestors(prev => prev.map(inv => {
if (inv.id === investor.id) {
return {
...inv,
investments: inv.investments?.map((item: any) => {
if (item.id === planId) {
const currentBatteryIds = item.batteryIds || [];
const uniqueNewBatteryIds = Array.from(new Set([...currentBatteryIds, ...batteryIds]));
return {
...item,
batteryIds: uniqueNewBatteryIds
};
}
return item;
})
};
}
return inv;
}));
const batteryNames = assignedBatteriesList.map(b => `${b.brand} ${b.model}`).join(', ');
toast.success(`Successfully assigned ${batteryIds.length} battery/ies: ${batteryNames}`);
}}
/>
{showRegisterBatteryModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-lg overflow-hidden flex flex-col">
<div className="p-5 border-b border-emerald-100 bg-emerald-50 flex items-center justify-between">
<h2 className="text-lg font-bold text-emerald-800 flex items-center gap-2">
<Battery className="w-5 h-5 text-emerald-600 animate-bounce" />
Register & Assign New Battery
</h2>
<button onClick={() => setShowRegisterBatteryModal(false)} className="p-2 hover:bg-emerald-100 rounded-lg text-emerald-600">
<X className="w-5 h-5" />
</button>
</div>
<div className="p-5 space-y-4 overflow-y-auto max-h-[75vh]">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Serial Number *</label>
<input
type="text"
value={registerForm.serialNumber}
onChange={(e) => setRegisterForm({ ...registerForm, serialNumber: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm font-mono font-semibold"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Brand *</label>
<select
value={registerForm.brand}
onChange={(e) => setRegisterForm({ ...registerForm, brand: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="BYD">BYD</option>
<option value="CATL">CATL</option>
<option value="EVE Energy">EVE Energy</option>
<option value="Panasonic">Panasonic</option>
</select>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Model *</label>
<input
type="text"
value={registerForm.model}
onChange={(e) => setRegisterForm({ ...registerForm, model: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Cell Chemistry *</label>
<select
value={registerForm.type}
onChange={(e) => setRegisterForm({ ...registerForm, type: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="lithium-ion">Lithium-Ion</option>
<option value="lifepo4">LiFePO4</option>
</select>
</div>
</div>
<div className="grid grid-cols-3 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Capacity (Ah)</label>
<input
type="number"
value={registerForm.capacity}
onChange={(e) => setRegisterForm({ ...registerForm, capacity: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Voltage (V)</label>
<input
type="number"
value={registerForm.voltage}
onChange={(e) => setRegisterForm({ ...registerForm, voltage: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Purchase Price (৳)</label>
<input
type="number"
value={registerForm.purchasePrice}
onChange={(e) => setRegisterForm({ ...registerForm, purchasePrice: Number(e.target.value), investedAmount: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
<div className="border-t border-dashed border-slate-200 pt-3">
<label className="text-sm font-semibold text-emerald-800 mb-2 block">Assignment Settings</label>
<div className="space-y-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Link to Investment Plan *</label>
<select
value={registerForm.investmentId}
onChange={(e) => setRegisterForm({ ...registerForm, investmentId: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="">Select plan</option>
{investor.investments?.map((inv: any) => (
<option key={inv.id} value={inv.id}>
{inv.planName} (#{inv.id?.slice(-6)})
</option>
))}
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Refundable Deposit (৳) *</label>
<input
type="number"
value={registerForm.deposit}
onChange={(e) => setRegisterForm({ ...registerForm, deposit: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Daily Rent Price (৳) *</label>
<input
type="number"
value={registerForm.rentPrice}
onChange={(e) => setRegisterForm({ ...registerForm, rentPrice: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Investor Share % *</label>
<input
type="number"
value={registerForm.investorShare}
onChange={(e) => setRegisterForm({ ...registerForm, investorShare: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Capital Invested (৳) *</label>
<input
type="number"
value={registerForm.investedAmount}
onChange={(e) => setRegisterForm({ ...registerForm, investedAmount: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
</div>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button
onClick={() => setShowRegisterBatteryModal(false)}
className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm font-semibold hover:bg-slate-50"
>
Cancel
</button>
<button
onClick={handleRegisterAndAssignBattery}
disabled={!registerForm.serialNumber || !registerForm.investmentId}
className="px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-semibold hover:bg-emerald-700 disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
>
Register & Assign
</button>
</div>
</div>
</div>
)}
{showEditBatteryModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md overflow-hidden flex flex-col">
<div className="p-5 border-b border-emerald-100 bg-emerald-50 flex items-center justify-between">
<h2 className="text-lg font-bold text-emerald-800 flex items-center gap-2">
<Battery className="w-5 h-5 text-emerald-600 animate-pulse" />
Edit Battery Assignment
</h2>
<button onClick={() => setShowEditBatteryModal(false)} className="p-2 hover:bg-emerald-100 rounded-lg text-emerald-600">
<X className="w-5 h-5" />
</button>
</div>
<div className="p-5 space-y-4 overflow-y-auto max-h-[75vh]">
<div className="bg-slate-50 p-3 rounded-lg border border-slate-200">
<p className="text-xs text-slate-500 font-medium">SELECTED ASSET</p>
<p className="font-bold text-slate-800 text-sm mt-0.5">
{selectedBatteryToEdit?.brand} {selectedBatteryToEdit?.model} ({selectedBatteryToEdit?.serialNumber})
</p>
<p className="text-xs text-slate-400">ID: {selectedBatteryToEdit?.id}</p>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Link to Investment Plan *</label>
<select
value={assignForm.investmentId}
onChange={(e) => setAssignForm({ ...assignForm, investmentId: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="">Select plan</option>
{investor.investments?.map((inv: any) => (
<option key={inv.id} value={inv.id}>
{inv.planName} (#{inv.id?.slice(-6)})
</option>
))}
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Refundable Deposit (৳) *</label>
<input
type="number"
value={assignForm.deposit}
onChange={(e) => setAssignForm({ ...assignForm, deposit: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Daily Rent Price (৳) *</label>
<input
type="number"
value={assignForm.rentPrice}
onChange={(e) => setAssignForm({ ...assignForm, rentPrice: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Investor Share % *</label>
<input
type="number"
value={assignForm.investorShare}
onChange={(e) => setAssignForm({ ...assignForm, investorShare: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Contribution (৳) *</label>
<input
type="number"
value={assignForm.investedAmount}
onChange={(e) => setAssignForm({ ...assignForm, investedAmount: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button
onClick={() => setShowEditBatteryModal(false)}
className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm font-semibold hover:bg-slate-50"
>
Cancel
</button>
<button
onClick={handleSaveEditBattery}
disabled={!assignForm.investmentId}
className="px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-semibold hover:bg-emerald-700 disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
>
Save Changes
</button>
</div>
</div>
</div>
)}
<AssignBikeModal
isOpen={showAssignBikeModal}
onClose={() => setShowAssignBikeModal(false)}
investor={investor}
bikes={bikes}
onAssign={(planId, bikeIds) => {
const assignedBikesList: any[] = [];
setBikes(prev => prev.map(b => {
if (bikeIds.includes(b.id)) {
assignedBikesList.push(b);
return {
...b,
investorId: investorId,
investorName: investor.name,
investmentId: planId,
status: 'rented',
totalEarnings: b.totalEarnings || 0
};
}
return b;
}));
setInvestors(prev => prev.map(inv => {
if (inv.id === investor.id) {
return {
...inv,
investments: inv.investments?.map((item: any) => {
if (item.id === planId) {
const currentBikeIds = item.bikeIds || [];
const uniqueNewBikeIds = Array.from(new Set([...currentBikeIds, ...bikeIds]));
return {
...item,
bikeIds: uniqueNewBikeIds
};
}
return item;
})
};
}
return inv;
}));
const bikeNames = assignedBikesList.map(b => `${b.model} (${b.plateNumber})`).join(', ');
toast.success(`Successfully assigned ${bikeIds.length} bike(s): ${bikeNames}`);
}}
/>
<UnassignConfirmModal
isOpen={unassignConfirmModal.show}
onClose={() => setUnassignConfirmModal(prev => ({ ...prev, show: false }))}
type={unassignConfirmModal.type}
name={unassignConfirmModal.name}
details={unassignConfirmModal.details}
onConfirm={() => {
if (unassignConfirmModal.type === 'bike') {
handleUnassignBike(unassignConfirmModal.id);
} else {
handleUnassignBattery(unassignConfirmModal.id);
}
}}
/>
{showRegisterBikeModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">Register & Assign New Bike</h2>
<button onClick={() => setShowRegisterBikeModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 space-y-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Plate Number</label>
<input
type="text"
value={registerBikeForm.plateNumber}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, plateNumber: e.target.value })}
placeholder="DHAKA-METRO-HA-1234"
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Brand</label>
<input
type="text"
value={registerBikeForm.brand}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, brand: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Model</label>
<input
type="text"
value={registerBikeForm.model}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, model: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Purchase Price (৳)</label>
<input
type="number"
value={registerBikeForm.purchasePrice}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, purchasePrice: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Daily Rent (৳)</label>
<input
type="number"
value={registerBikeForm.currentRent}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, currentRent: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Location</label>
<input
type="text"
value={registerBikeForm.location}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, location: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Rental Type</label>
<select
value={registerBikeForm.rentalType}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, rentalType: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="single_rent">Single Rent</option>
<option value="rent_to_own">Rent to Own</option>
<option value="share_ev">Share EV</option>
</select>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Attach to Investment Plan</label>
<select
value={registerBikeForm.investmentId}
onChange={(e) => setRegisterBikeForm({ ...registerBikeForm, investmentId: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="">Select plan</option>
{investor.investments?.filter((inv: any) => inv.assetType === 'bike' || !inv.assetType).map((inv: any) => (
<option key={inv.id} value={inv.id}>{inv.planName} ({inv.id})</option>
))}
</select>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowRegisterBikeModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">Cancel</button>
<button onClick={handleRegisterAndAssignBike} className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark">Register & Assign</button>
</div>
</div>
</div>
)}
{showCreateInvestmentModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-3xl max-h-[90vh] overflow-hidden flex flex-col">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<div>
<h2 className="text-lg font-bold text-slate-800">Create New Investment</h2>
<p className="text-sm text-slate-500">Set up investment for {investor.name}</p>
</div>
<button onClick={() => setShowCreateInvestmentModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 overflow-y-auto flex-1 space-y-5">
{/* Asset Type Selector */}
<div>
<label className="text-sm font-semibold text-slate-700 mb-2 block">Asset Investment Category *</label>
<div className="grid grid-cols-2 gap-4">
<button
onClick={() => {
setNewInvestment({
...newInvestment,
assetType: 'bike',
planName: bikeTemplates[0].name,
planType: bikeTemplates[0].tier.toLowerCase() as any,
totalInvestment: bikeTemplates[0].evBasePrice * bikeTemplates[0].minQuantity,
paidAmount: bikeTemplates[0].evBasePrice * bikeTemplates[0].minQuantity,
paymentType: 'full'
});
}}
className={`py-3 px-4 rounded-xl border-2 flex items-center justify-center gap-2 font-bold text-sm transition-all ${newInvestment.assetType === 'bike'
? 'bg-investor/10 border-investor text-investor shadow-sm'
: 'bg-white border-slate-200 text-slate-600 hover:bg-slate-50'
}`}
>
<Bike className="w-5 h-5 text-investor" /> Bike Investment Plan
</button>
<button
onClick={() => {
setNewInvestment({
...newInvestment,
assetType: 'battery',
planName: batteryTemplates[0].name,
planType: batteryTemplates[0].tier.toLowerCase() as any,
totalInvestment: batteryTemplates[0].evBasePrice * batteryTemplates[0].minQuantity,
paidAmount: batteryTemplates[0].evBasePrice * batteryTemplates[0].minQuantity,
paymentType: 'full'
});
}}
className={`py-3 px-4 rounded-xl border-2 flex items-center justify-center gap-2 font-bold text-sm transition-all ${newInvestment.assetType === 'battery'
? 'bg-emerald-50 border-emerald-500 text-emerald-800 shadow-sm'
: 'bg-white border-slate-200 text-slate-600 hover:bg-slate-50'
}`}
>
<Battery className="w-5 h-5 text-emerald-600 animate-pulse" /> Battery Investment Plan
</button>
</div>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-2 block">Select Plan Template</label>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{(newInvestment.assetType === 'battery' ? batteryTemplates : bikeTemplates).map((plan: any) => (
<button
key={plan.id}
onClick={() => {
setNewInvestment({
...newInvestment,
planName: plan.name,
planType: plan.tier.toLowerCase() as any,
totalInvestment: plan.evBasePrice * plan.minQuantity,
paidAmount: plan.evBasePrice * plan.minQuantity,
paymentType: 'full',
monthlyReturn: 0
});
}}
className={`p-4 rounded-lg border-2 text-left transition-all ${newInvestment.planName === plan.name ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-investor/50'}`}
>
<p className="font-semibold text-slate-800">{plan.name}</p>
<p className="text-xs text-slate-500">৳{plan.evBasePrice.toLocaleString()} × {plan.minQuantity} {newInvestment.assetType}(s)</p>
<p className="text-sm text-slate-600 mt-1">Duration: {plan.duration} months</p>
</button>
))}
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Plan Name *</label>
<input
type="text"
value={newInvestment.planName}
onChange={(e) => setNewInvestment({ ...newInvestment, planName: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm font-semibold"
placeholder="Plan name"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Plan Type (Tier)</label>
<select
value={newInvestment.planType}
onChange={(e) => setNewInvestment({ ...newInvestment, planType: e.target.value as any })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="silver">Silver</option>
<option value="gold">Gold</option>
<option value="platinum">Platinum</option>
<option value="diamond">Diamond</option>
</select>
</div>
</div>
<div className="grid grid-cols-3 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">{newInvestment.assetType === 'battery' ? 'Battery Pack Cost ()' : 'EV Base Price ()'}</label>
<input type="text" disabled value={`৳${activeTemplate.evBasePrice.toLocaleString()}`} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 font-semibold cursor-not-allowed text-slate-700" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Min Quantity ({newInvestment.assetType === 'battery' ? 'Packs' : 'Bikes'})</label>
<input type="text" disabled value={activeTemplate.minQuantity} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 font-semibold cursor-not-allowed text-slate-700" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Min Investment (৳)</label>
<input type="text" value={`৳${(activeTemplate.evBasePrice * activeTemplate.minQuantity).toLocaleString()}`} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 font-bold cursor-not-allowed text-slate-700" />
<p className="text-[10px] text-slate-400 mt-1">= Qty × Base Price</p>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Investment Amount (৳) *</label>
<input
type="number"
value={newInvestment.totalInvestment}
onChange={(e) => {
const val = Number(e.target.value);
setNewInvestment({
...newInvestment,
totalInvestment: val,
paidAmount: newInvestment.assetType === 'battery' ? val : (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 font-bold"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Max Investment Cap (৳)</label>
<input type="text" value={`৳${activeTemplate.maxInvestment.toLocaleString()}`} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed font-semibold text-slate-700" />
</div>
</div>
<div className="grid grid-cols-3 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Duration (Months)</label>
<input type="text" value={`${activeTemplate.duration} Months`} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed font-semibold text-slate-700" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Lock-in Period (Months)</label>
<input type="text" value={`${activeTemplate.lockIn} Months`} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed font-semibold text-slate-700" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Early Exit Penalty (%)</label>
<input type="text" value={`${activeTemplate.exitPenalty}%`} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed font-semibold text-slate-700" />
</div>
</div>
<div className="bg-emerald-50 border border-emerald-200 rounded-xl p-4">
<h4 className="text-sm font-semibold text-emerald-800 mb-3 flex items-center gap-2">
<TrendingUp className="w-4 h-4" />
{newInvestment.assetType === 'battery' ? 'Partner Profit Sharing Percentage' : 'FICO Share - Partner Yield Sharing Percentages'}
</h4>
<p className="text-xs text-emerald-600 mb-3">Profit sharing ratio when {newInvestment.assetType}s are utilized</p>
{newInvestment.assetType === 'battery' ? (
<div className="flex items-center justify-between bg-white p-3 rounded-lg border border-emerald-250">
<span className="text-sm font-medium text-slate-700">Profit Share Percent (%)</span>
<span className="font-bold text-emerald-600 text-lg">{activeTemplate.profitSharePercent || activeTemplate.profitShareSingle}%</span>
</div>
) : (
<div className="grid grid-cols-3 gap-4">
<div>
<label className="text-xs text-slate-500 mb-1 block">Single Rent (%)</label>
<input type="text" value={`${activeTemplate.profitShareSingle}%`} disabled className="w-full px-3 py-2 border border-emerald-250 rounded-lg text-sm bg-white cursor-not-allowed font-semibold text-slate-700 text-center" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Rent to Own (%)</label>
<input type="text" value={`${activeTemplate.profitShareOwn}%`} disabled className="w-full px-3 py-2 border border-emerald-250 rounded-lg text-sm bg-white cursor-not-allowed font-semibold text-slate-700 text-center" />
</div>
<div>
<label className="text-xs text-slate-500 mb-1 block">Share an EV (%)</label>
<input type="text" value={`${activeTemplate.profitShareEV}%`} disabled className="w-full px-3 py-2 border border-emerald-250 rounded-lg text-sm bg-white cursor-not-allowed font-semibold text-slate-700 text-center" />
</div>
</div>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Start Date *</label>
<input
type="date"
value={newInvestment.startDate}
onChange={(e) => setNewInvestment({ ...newInvestment, startDate: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">End Date</label>
<input
type="date"
value={newInvestment.endDate}
onChange={(e) => setNewInvestment({ ...newInvestment, endDate: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
</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>
{newInvestment.assetType === 'battery' ? (
<div className="flex justify-between items-center bg-white p-3.5 rounded-lg border border-slate-200 shadow-sm">
<div>
<p className="font-semibold text-slate-800 text-sm flex items-center gap-1.5">
<Check className="w-4 h-4 text-emerald-600" /> Full Payment Only
</p>
<p className="text-xs text-slate-400 mt-0.5">Battery plans require full upfront capital</p>
</div>
<span className="text-lg font-bold text-green-600">৳{newInvestment.totalInvestment.toLocaleString()}</span>
</div>
) : (
<>
<div className="grid grid-cols-1 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>
</div>
</>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Payment Method</label>
<select
value={newInvestment.paymentMethod}
onChange={(e) => setNewInvestment({ ...newInvestment, paymentMethod: e.target.value as any })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
<option value="bank">Bank Transfer</option>
<option value="mobile">Mobile Banking</option>
<option value="cash">Cash</option>
<option value="cheque">Cheque</option>
</select>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Transaction Reference</label>
<input
type="text"
value={newInvestment.transactionReference}
onChange={(e) => 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"
/>
</div>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Description</label>
<textarea
value={newInvestment.notes}
onChange={(e) => setNewInvestment({ ...newInvestment, notes: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
rows={2}
/>
</div>
<div className="bg-green-50 border border-green-200 rounded-xl p-4">
<h4 className="font-semibold text-green-800 mb-3 flex items-center gap-2">
<TrendingUp className="w-4 h-4" />
Auto-Journal Entry
</h4>
<div className="bg-white rounded-lg p-4 border border-green-100">
<div className="flex items-center justify-between text-sm mb-2">
<span className="text-slate-500">Date:</span>
<span className="font-medium">{newInvestment.startDate || 'Not set'}</span>
</div>
<div className="flex items-center justify-between text-sm mb-3">
<span className="text-slate-500">Reference:</span>
<span className="font-medium">{newInvestment.transactionReference || `INV/${new Date().getFullYear()}/auto`}</span>
</div>
<div className="space-y-2">
<div className="flex items-center justify-between p-3 bg-green-50 rounded-lg border border-green-200">
<div>
<p className="text-xs text-green-600 font-medium uppercase">Debit (Dr)</p>
<p className="font-medium text-slate-800">
{newInvestment.paymentMethod === 'bank' ? 'Bank - City Bank' : newInvestment.paymentMethod === 'cash' ? 'Cash in Hand' : 'bKash Business'} ({newInvestment.paymentMethod === 'bank' ? '1200' : newInvestment.paymentMethod === 'cash' ? '1100' : '1300'})
</p>
</div>
<p className="font-bold text-green-700">৳{newInvestment.paidAmount.toLocaleString()}</p>
</div>
<div className="flex justify-center">
<div className="w-8 h-8 rounded-full bg-green-200 flex items-center justify-center">
<span className="text-green-600">▼</span>
</div>
</div>
<div className="flex items-center justify-between p-3 bg-blue-50 rounded-lg border border-blue-200">
<div>
<p className="text-xs text-blue-600 font-medium uppercase">Credit (Cr)</p>
<p className="font-medium text-slate-800">Investor Liabilities (2200)</p>
</div>
<p className="font-bold text-blue-700">৳{newInvestment.paidAmount.toLocaleString()}</p>
</div>
</div>
</div>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowCreateInvestmentModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
Cancel
</button>
<button
onClick={handleCreateInvestment}
disabled={!newInvestment.planName || !newInvestment.totalInvestment}
className="px-4 py-2 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark disabled:opacity-50 flex items-center gap-2"
>
<Plus className="w-4 h-4" /> Create Investment
</button>
</div>
</div>
</div>
)}
{showBankModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">{editingBankAccount.id ? 'Edit' : 'Add'} Bank Account</h2>
<button onClick={() => setShowBankModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 space-y-4">
{bankSaveSuccess ? (
<div className="text-center py-8">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Check className="w-8 h-8 text-green-600" />
</div>
<h3 className="text-lg font-bold text-slate-800 mb-2">Bank Account Saved!</h3>
<p className="text-sm text-slate-500">
{editingBankAccount.isPrimary ? 'Primary account has been updated.' : 'Bank account has been saved successfully.'}
</p>
</div>
) : (
<>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Bank Name <span className="text-red-500">*</span></label>
<input
type="text"
value={editingBankAccount.bankName}
onChange={(e) => {
setEditingBankAccount({ ...editingBankAccount, bankName: e.target.value });
setBankErrors({ ...bankErrors, bankName: '' });
}}
className={`w-full px-3 py-2 border rounded-lg text-sm ${bankErrors.bankName ? 'border-red-300 bg-red-50' : 'border-slate-200'}`}
placeholder="e.g., Standard Chartered Bank"
/>
{bankErrors.bankName && <p className="text-xs text-red-500 mt-1">{bankErrors.bankName}</p>}
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Branch</label>
<input type="text" value={editingBankAccount.branch} onChange={(e) => setEditingBankAccount({ ...editingBankAccount, branch: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="e.g., Gulshan Branch" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Account Name <span className="text-red-500">*</span></label>
<input
type="text"
value={editingBankAccount.accountName}
onChange={(e) => {
setEditingBankAccount({ ...editingBankAccount, accountName: e.target.value });
setBankErrors({ ...bankErrors, accountName: '' });
}}
className={`w-full px-3 py-2 border rounded-lg text-sm ${bankErrors.accountName ? 'border-red-300 bg-red-50' : 'border-slate-200'}`}
placeholder="Account holder name"
/>
{bankErrors.accountName && <p className="text-xs text-red-500 mt-1">{bankErrors.accountName}</p>}
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Account Number <span className="text-red-500">*</span></label>
<input
type="text"
value={editingBankAccount.accountNumber}
onChange={(e) => {
setEditingBankAccount({ ...editingBankAccount, accountNumber: e.target.value });
setBankErrors({ ...bankErrors, accountNumber: '' });
}}
className={`w-full px-3 py-2 border rounded-lg text-sm ${bankErrors.accountNumber ? 'border-red-300 bg-red-50' : 'border-slate-200'}`}
placeholder="Account number"
/>
{bankErrors.accountNumber && <p className="text-xs text-red-500 mt-1">{bankErrors.accountNumber}</p>}
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Routing Number</label>
<input type="text" value={editingBankAccount.routing} onChange={(e) => setEditingBankAccount({ ...editingBankAccount, routing: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Routing number" />
</div>
<div className="flex items-center gap-3 p-3 bg-slate-50 rounded-lg">
<input
type="checkbox"
id="isPrimary"
checked={editingBankAccount.isPrimary}
onChange={(e) => setEditingBankAccount({ ...editingBankAccount, isPrimary: e.target.checked })}
className="w-4 h-4 text-investor rounded border-slate-300"
/>
<label htmlFor="isPrimary" className="text-sm text-slate-700">
<span className="font-medium">Set as Primary Account</span>
<p className="text-xs text-slate-500">Primary account will be used for withdrawals by default</p>
</label>
</div>
</>
)}
</div>
<div className="p-5 border-t border-slate-100 flex justify-between">
{bankSaveSuccess ? (
<div className="flex gap-2 ml-auto">
<button onClick={() => { setShowBankModal(false); setBankSaveSuccess(false); }} className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark">Done</button>
</div>
) : (
<>
{editingBankAccount.id && (
<button onClick={() => setShowDeleteBankModal(true)} className="px-4 py-2 border border-red-200 text-red-600 rounded-lg text-sm hover:bg-red-50 flex items-center gap-1">
<Trash2 className="w-4 h-4" /> Delete
</button>
)}
<div className="flex gap-2 ml-auto">
<button onClick={() => setShowBankModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">Cancel</button>
<button onClick={() => {
const errors: { bankName?: string; accountName?: string; accountNumber?: string } = {};
if (!editingBankAccount.bankName) errors.bankName = 'Bank name is required';
if (!editingBankAccount.accountName) errors.accountName = 'Account name is required';
if (!editingBankAccount.accountNumber) errors.accountNumber = 'Account number is required';
if (Object.keys(errors).length > 0) {
setBankErrors(errors);
return;
}
setBankErrors({});
setBankSaveSuccess(true);
}} className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark">Save</button>
</div>
</>
)}
</div>
</div>
</div>
)}
{showMobileBankingModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">{editingMobileIndex !== null ? 'Edit' : 'Add'} Mobile Banking</h2>
<button onClick={() => setShowMobileBankingModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 space-y-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Provider</label>
<select value={editingMobileBanking.provider} onChange={(e) => setEditingMobileBanking({ ...editingMobileBanking, provider: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select Provider</option>
<option value="Bkash">Bkash</option>
<option value="Nagad">Nagad</option>
<option value="Rocket">Rocket</option>
<option value="Upay">Upay</option>
</select>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Mobile Number</label>
<input type="text" value={editingMobileBanking.number} onChange={(e) => setEditingMobileBanking({ ...editingMobileBanking, number: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="01XXXXXXXXX" />
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowMobileBankingModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">Cancel</button>
<button onClick={() => { alert('Mobile banking saved!'); setShowMobileBankingModal(false); }} className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark">Save</button>
</div>
</div>
</div>
)}
{showDeleteBankModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-[60] p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h3 className="text-lg font-bold text-slate-800 flex items-center gap-2">
<Trash2 className="w-5 h-5 text-red-500" /> Delete Bank Account
</h3>
<button onClick={() => setShowDeleteBankModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5">
<p className="text-slate-600 mb-4">Are you sure you want to delete this bank account?</p>
<div className="bg-slate-50 rounded-lg p-4 space-y-2">
<div className="flex justify-between">
<span className="text-slate-500">Bank</span>
<span className="font-medium">{editingBankAccount.bankName}</span>
</div>
<div className="flex justify-between">
<span className="text-slate-500">Account</span>
<span className="font-mono">{editingBankAccount.accountNumber}</span>
</div>
</div>
{editingBankAccount.isPrimary && (
<div className="mt-3 p-3 bg-amber-50 border border-amber-200 rounded-lg flex items-center gap-2">
<AlertTriangle className="w-5 h-5 text-amber-600" />
<p className="text-sm text-amber-700">This is the primary account. Deleting it may affect withdrawal settings.</p>
</div>
)}
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowDeleteBankModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
Cancel
</button>
<button
onClick={() => {
console.log('Deleting bank account:', editingBankAccount.id);
setShowDeleteBankModal(false);
setShowBankModal(false);
}}
className="px-4 py-2 bg-red-500 text-white rounded-lg text-sm font-medium hover:bg-red-600"
>
Delete Account
</button>
</div>
</div>
</div>
)}
{showTaxModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">Tax Information</h2>
<button onClick={() => setShowTaxModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 space-y-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">TIN Number</label>
<input type="text" value={editingTax.tinNumber} onChange={(e) => setEditingTax({ ...editingTax, tinNumber: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="TIN Number" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Passport Number</label>
<input type="text" value={editingTax.passportNumber} onChange={(e) => setEditingTax({ ...editingTax, passportNumber: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Passport Number" />
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-between">
{(investor.tinNumber || investor.passportNumber) && (
<button onClick={() => { alert('Tax info deleted'); setShowTaxModal(false); }} className="px-4 py-2 border border-red-200 text-red-600 rounded-lg text-sm hover:bg-red-50">Delete All</button>
)}
<div className="flex gap-2 ml-auto">
<button onClick={() => setShowTaxModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">Cancel</button>
<button onClick={() => { alert('Tax info saved!'); setShowTaxModal(false); }} className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark">Save</button>
</div>
</div>
</div>
</div>
)}
{showDocModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">Upload Document</h2>
<button onClick={() => setShowDocModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 space-y-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Document Type</label>
<select value={newDoc.type} onChange={(e) => setNewDoc({ ...newDoc, type: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="nid">NID Card</option>
<option value="passport">Passport</option>
<option value="bank_statement">Bank Statement</option>
<option value="tin_certificate">TIN Certificate</option>
<option value="trade_license">Trade License</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Document Number</label>
<input type="text" value={newDoc.number} onChange={(e) => setNewDoc({ ...newDoc, number: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Document number (optional)" />
</div>
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Upload File</label>
<div className="border-2 border-dashed border-slate-200 rounded-lg p-6 text-center">
<FileText className="w-10 h-10 text-slate-300 mx-auto mb-2" />
<p className="text-sm text-slate-500 mb-2">Click to upload or drag and drop</p>
<p className="text-xs text-slate-400">PNG, JPG, PDF up to 10MB</p>
</div>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowDocModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">Cancel</button>
<button onClick={() => { alert('Document uploaded successfully!'); setShowDocModal(false); }} className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark">Upload</button>
</div>
</div>
</div>
)}
{showJournalModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">Journal Records</h2>
<button onClick={() => setShowJournalModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-5 overflow-y-auto flex-1">
{investorJournals.length > 0 ? (
<div className="space-y-3">
{investorJournals.map((journal, idx) => (
<div key={idx} className="bg-slate-50 rounded-lg p-4 border border-slate-200">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<span className="text-xs font-mono text-slate-500">{journal.reference}</span>
<span className="text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700">Auto</span>
</div>
<span className="text-xs text-slate-500">{journal.date}</span>
</div>
<div className="space-y-2">
<div className="flex items-center justify-between bg-white p-2 rounded border border-slate-200">
<div>
<p className="text-sm font-medium">Debit (Dr)</p>
<p className="text-xs text-slate-500">Bank - City Bank (1200)</p>
</div>
<p className="font-bold text-green-600">৳{journal.amount.toLocaleString()}</p>
</div>
<div className="flex items-center justify-center py-0.5">
<ArrowRight className="w-4 h-4 text-slate-400 rotate-90" />
</div>
<div className="flex items-center justify-between bg-white p-2 rounded border border-slate-200">
<div>
<p className="text-sm font-medium">Credit (Cr)</p>
<p className="text-xs text-slate-500">Investor Liabilities (2200)</p>
</div>
<p className="font-bold text-red-600">৳{journal.amount.toLocaleString()}</p>
</div>
</div>
<div className="mt-2 pt-2 border-t border-slate-200 text-xs text-slate-500">
{journal.description}
</div>
</div>
))}
</div>
) : (
<div className="text-center py-8 text-slate-400">
<BookOpen className="w-12 h-12 mx-auto mb-2 opacity-50" />
<p>No journal records yet</p>
<p className="text-sm">Create an investment to see auto-journal entries</p>
</div>
)}
</div>
</div>
</div>
)}
{showInvoiceModal && selectedInvoice && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-lg">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h2 className="text-lg font-bold text-slate-800">Invoice</h2>
<button onClick={() => setShowInvoiceModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
<div className="p-6" id="invoice-content">
<div className="text-center border-b border-slate-200 pb-4 mb-4">
<h1 className="text-xl font-extrabold text-investor">JAIBEN Mobility Ltd</h1>
<p className="text-xs text-slate-500">EV Rental & Investment Company</p>
</div>
<div className="flex justify-between mb-4">
<div>
<p className="text-xs text-slate-500">Invoice No</p>
<p className="text-sm font-medium">{selectedInvoice.reference}</p>
</div>
<div className="text-right">
<p className="text-xs text-slate-500">Date</p>
<p className="text-sm font-medium">{selectedInvoice.date}</p>
</div>
</div>
<div className="mb-4">
<p className="text-xs text-slate-500">Investor</p>
<p className="text-sm font-medium">{selectedInvoice.investorName}</p>
<p className="text-xs text-slate-400">{selectedInvoice.investorId}</p>
</div>
<table className="w-full mb-4">
<thead>
<tr className="border-b border-slate-200">
<th className="text-left py-2 text-xs text-slate-500">Description</th>
<th className="text-right py-2 text-xs text-slate-500">Amount</th>
</tr>
</thead>
<tbody>
<tr className="border-b border-slate-100">
<td className="py-3 text-sm">{selectedInvoice.description}</td>
<td className="py-3 text-sm text-right font-medium">৳{selectedInvoice.amount.toLocaleString()}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td className="py-2 text-sm font-medium">Total</td>
<td className="py-2 text-sm font-bold text-right">৳{selectedInvoice.amount.toLocaleString()}</td>
</tr>
</tfoot>
</table>
<div className="flex justify-between mb-2">
<span className="text-xs text-slate-500">Status</span>
<span className={`text-xs px-2 py-1 rounded-full ${selectedInvoice.status === 'completed' ? 'bg-green-100 text-green-700' :
selectedInvoice.status === 'pending' ? 'bg-amber-100 text-amber-700' : 'bg-slate-100 text-slate-700'
}`}>
{selectedInvoice.status}
</span>
</div>
<div className="mt-4 pt-4 border-t border-slate-200">
<p className="text-xs text-slate-500 mb-2">Double Entry Accounting (Journal)</p>
<div className="bg-slate-50 rounded-lg p-3 border border-slate-200">
<div className="flex items-center justify-between mb-2">
<div>
<p className="text-xs font-medium">Debit (Dr)</p>
<p className="text-xs text-slate-500">{selectedInvoice.debitAccount || 'N/A'}</p>
</div>
<p className="text-sm font-bold">৳{selectedInvoice.amount.toLocaleString()}</p>
</div>
<div className="flex items-center justify-center py-1">
<ArrowRight className="w-4 h-4 text-slate-400 rotate-90" />
</div>
<div className="flex items-center justify-between">
<div>
<p className="text-xs font-medium">Credit (Cr)</p>
<p className="text-xs text-slate-500">{selectedInvoice.creditAccount || 'N/A'}</p>
</div>
<p className="text-sm font-bold">৳{selectedInvoice.amount.toLocaleString()}</p>
</div>
</div>
</div>
<div className="mt-6 pt-4 border-t border-slate-200 text-center">
<p className="text-xs text-slate-400">Thank you for your investment!</p>
<p className="text-xs text-slate-400">Generated on {new Date().toLocaleDateString()}</p>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-between">
<button
onClick={() => window.print()}
className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark flex items-center gap-2"
>
<Printer className="w-4 h-4" /> Print
</button>
<button
onClick={() => {
import('jspdf').then(jsPDF => {
const doc = new jsPDF.default();
doc.setFontSize(18);
doc.setTextColor(6, 95, 70);
doc.text('JAIBEN Mobility Ltd', 20, 20);
doc.setFontSize(12);
doc.setTextColor(0);
doc.text('Invoice: ' + selectedInvoice.reference, 20, 30);
doc.text('Date: ' + selectedInvoice.date, 20, 38);
doc.text('Investor: ' + selectedInvoice.investorName, 20, 46);
doc.text('Description: ' + selectedInvoice.description, 20, 54);
doc.text('Amount: ' + selectedInvoice.amount.toLocaleString(), 20, 64);
doc.text('Status: ' + selectedInvoice.status, 20, 72);
if (selectedInvoice.debitAccount) {
doc.setFontSize(10);
doc.setTextColor(100);
doc.text('Double Entry Accounting:', 20, 85);
doc.text('Dr: ' + selectedInvoice.debitAccount + ' ' + selectedInvoice.amount.toLocaleString(), 20, 93);
doc.text('Cr: ' + selectedInvoice.creditAccount + ' ' + selectedInvoice.amount.toLocaleString(), 20, 101);
}
doc.setFontSize(9);
doc.setTextColor(150);
doc.text('Thank you for your investment!', 20, 115);
doc.save(`invoice-${selectedInvoice.reference}.pdf`);
});
}}
className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50 flex items-center gap-2"
>
<Download className="w-4 h-4" /> PDF
</button>
<button onClick={() => setShowInvoiceModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">Close</button>
</div>
</div>
</div>
)}
{showInvestmentSuccessModal && lastCreatedInvestment && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-lg">
<div className="p-5 border-b border-slate-100 flex items-center justify-between bg-green-50">
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center">
<Check className="w-6 h-6 text-green-600" />
</div>
<div>
<h2 className="text-lg font-bold text-green-800">Investment Created!</h2>
<p className="text-sm text-green-600">Auto-journal entry generated</p>
</div>
</div>
<button onClick={() => setShowInvestmentSuccessModal(false)} className="p-2 hover:bg-green-100 rounded-lg">
<X className="w-5 h-5 text-green-400" />
</button>
</div>
<div className="p-5 space-y-4">
<div className="bg-slate-50 rounded-lg p-4 space-y-2">
<div className="flex justify-between">
<span className="text-sm text-slate-500">Investment ID</span>
<span className="text-sm font-medium">#{lastCreatedInvestment.id.slice(-8)}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-slate-500">Transaction Ref</span>
<span className="text-sm font-medium">{lastCreatedInvestment.transactionId}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-slate-500">Amount</span>
<span className="text-sm font-bold text-green-600">৳{lastCreatedInvestment.totalInvestment.toLocaleString()}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-slate-500">Plan</span>
<span className="text-sm font-medium">{lastCreatedInvestment.planName}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-slate-500">Date</span>
<span className="text-sm font-medium">{lastCreatedInvestment.startDate}</span>
</div>
</div>
<div className="bg-green-50 border border-green-200 rounded-xl p-4">
<h4 className="text-sm font-semibold text-green-800 mb-3 flex items-center gap-2">
<FileText className="w-4 h-4" />
Auto-Journal Entry
</h4>
<div className="bg-white rounded-lg p-3 border border-green-100">
<div className="space-y-2">
<div className="flex items-center justify-between p-2 bg-green-50 rounded border border-green-200">
<div>
<p className="text-xs text-green-600 font-medium uppercase">Debit (Dr)</p>
<p className="text-sm font-medium text-slate-800">{lastCreatedInvestment.debitAccount?.name}</p>
<p className="text-xs text-slate-400">{lastCreatedInvestment.debitAccount?.code}</p>
</div>
<p className="font-bold text-green-700">৳{lastCreatedInvestment.totalInvestment.toLocaleString()}</p>
</div>
<div className="flex justify-center">
<div className="w-6 h-6 rounded-full bg-green-200 flex items-center justify-center">
<span className="text-green-600 text-xs">▼</span>
</div>
</div>
<div className="flex items-center justify-between p-2 bg-blue-50 rounded border border-blue-200">
<div>
<p className="text-xs text-blue-600 font-medium uppercase">Credit (Cr)</p>
<p className="text-sm font-medium text-slate-800">Investor Liabilities</p>
<p className="text-xs text-slate-400">2200</p>
</div>
<p className="font-bold text-blue-700">৳{lastCreatedInvestment.totalInvestment.toLocaleString()}</p>
</div>
</div>
</div>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowInvestmentSuccessModal(false)} className="px-4 py-2 bg-green-600 text-white rounded-lg text-sm font-medium hover:bg-green-700 flex items-center gap-2">
<Check className="w-4 h-4" /> Done
</button>
</div>
</div>
</div>
)}
{showAddPaymentModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-lg">
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
<h3 className="text-lg font-bold text-slate-800 flex items-center gap-2">
<CreditCard className="w-5 h-5 text-investor" /> Record Payment
</h3>
<button onClick={() => setShowAddPaymentModal(false)} className="p-1 hover:bg-slate-100 rounded-lg">
<X className="w-5 h-5 text-slate-500" />
</button>
</div>
<div className="p-5 space-y-4">
<div>
<label className="text-sm font-medium text-slate-700 mb-1 block">Amount (৳) <span className="text-red-500">*</span></label>
<input
type="number"
value={newPayment.amount || ''}
onChange={(e) => setNewPayment({ ...newPayment, amount: Number(e.target.value) })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-investor"
placeholder="Enter payment amount"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-slate-700 mb-1 block">Date</label>
<input
type="date"
value={newPayment.date}
onChange={(e) => setNewPayment({ ...newPayment, date: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-investor"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-700 mb-1 block">Payment Method</label>
<select
value={newPayment.paymentMethod}
onChange={(e) => setNewPayment({ ...newPayment, paymentMethod: e.target.value as any })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-investor"
>
<option value="bank">Bank Transfer</option>
<option value="mobile">Mobile Banking</option>
<option value="cash">Cash</option>
<option value="cheque">Cheque</option>
</select>
</div>
</div>
<div>
<label className="text-sm font-medium text-slate-700 mb-1 block">Transaction Reference</label>
<input
type="text"
value={newPayment.transactionRef}
onChange={(e) => setNewPayment({ ...newPayment, transactionRef: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-investor"
placeholder="e.g., TXN-12345"
/>
</div>
<div>
<label className="text-sm font-medium text-slate-700 mb-1 block">Notes</label>
<textarea
value={newPayment.notes}
onChange={(e) => setNewPayment({ ...newPayment, notes: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-investor"
rows={2}
/>
</div>
</div>
<div className="p-5 border-t border-slate-100 flex justify-end gap-3">
<button onClick={() => setShowAddPaymentModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
Cancel
</button>
<button
onClick={() => {
if (newPayment.amount <= 0) {
alert('Please enter a valid amount');
return;
}
const payment = {
id: `pay${Date.now()}`,
date: newPayment.date,
amount: newPayment.amount,
paymentMethod: newPayment.paymentMethod,
transactionRef: newPayment.transactionRef || `AUTO-${Date.now()}`,
status: 'completed',
notes: newPayment.notes
};
setInvestmentPayments([...investmentPayments, payment]);
setNewPayment({ amount: 0, paymentMethod: 'bank', transactionRef: '', date: new Date().toISOString().split('T')[0], notes: '' });
setShowAddPaymentModal(false);
alert('Payment recorded successfully!');
}}
disabled={newPayment.amount <= 0}
className="px-4 py-2 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark disabled:opacity-50"
>
Record Payment
</button>
</div>
</div>
</div>
)}
</div>
);
}