refactor: rename investment plans to EV investment plans across UI components
This commit is contained in:
@@ -5,9 +5,9 @@ import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { investors as initialInvestors, bikes as initialBikes, transactions as initialTransactions } from '@/data/mockData';
|
||||
import type { Investor } from '@/data/mockData';
|
||||
import {
|
||||
ArrowLeft, Wallet, TrendingUp, Banknote, Calendar, Phone, Mail, MapPin, Edit, Trash2, Plus, X, Bike,
|
||||
User, FileText, CreditCard, DollarSign, Clock, ChevronDown, ExternalLink, Download, Upload,
|
||||
import {
|
||||
ArrowLeft, Wallet, TrendingUp, Banknote, Calendar, Phone, Mail, MapPin, Edit, Trash2, Plus, X, Bike,
|
||||
User, FileText, CreditCard, DollarSign, Clock, ChevronDown, ExternalLink, Download, Upload,
|
||||
AlertTriangle, Shield, Star, CheckCircle, XCircle, Search, Filter, BookOpen, ArrowRight, Printer
|
||||
} from 'lucide-react';
|
||||
|
||||
@@ -42,13 +42,13 @@ const bikeStatusColors: Record<string, string> = {
|
||||
export default function InvestorDetailPage() {
|
||||
const params = useParams();
|
||||
const investorId = params.id as string;
|
||||
|
||||
|
||||
const [investors] = useState<Investor[]>(initialInvestors);
|
||||
const investor = investors.find(i => i.id === investorId);
|
||||
|
||||
|
||||
const assignedBikes = initialBikes.filter(b => b.investorId === investorId);
|
||||
// Investor transactions are filtered below
|
||||
|
||||
|
||||
const [activeTab, setActiveTab] = useState('overview');
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [showAssignBikeModal, setShowAssignBikeModal] = useState(false);
|
||||
@@ -108,7 +108,7 @@ export default function InvestorDetailPage() {
|
||||
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' };
|
||||
@@ -118,9 +118,9 @@ export default function InvestorDetailPage() {
|
||||
default: return { code: '1200', name: 'Bank - City Bank' };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const debitAccount = getDebitAccount(newInvestment.paymentMethod);
|
||||
|
||||
|
||||
const journalEntry = {
|
||||
entryId: `JE-${Date.now()}`,
|
||||
date: newInvestment.startDate,
|
||||
@@ -137,9 +137,9 @@ export default function InvestorDetailPage() {
|
||||
amount: newInvestment.totalInvestment,
|
||||
paymentMethod: newInvestment.paymentMethod
|
||||
};
|
||||
|
||||
|
||||
setInvestorJournals([journalEntry, ...investorJournals]);
|
||||
|
||||
|
||||
console.log('Creating Investment:', {
|
||||
id: invId,
|
||||
investorId: investor.id,
|
||||
@@ -149,7 +149,7 @@ export default function InvestorDetailPage() {
|
||||
transactionId: transactionRef,
|
||||
createdAt: new Date().toISOString()
|
||||
});
|
||||
|
||||
|
||||
alert(`Investment created successfully!
|
||||
|
||||
Investor: ${investor.name}
|
||||
@@ -424,7 +424,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-semibold text-slate-800">Assigned Bikes</h3>
|
||||
<button
|
||||
<button
|
||||
onClick={() => setShowAssignBikeModal(true)}
|
||||
className="py-2 px-3 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-1"
|
||||
>
|
||||
@@ -485,7 +485,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
{activeTab === 'investments' && (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="font-semibold text-slate-800">Investment Plans</h3>
|
||||
<h3 className="font-semibold text-slate-800">EV Investment Plans</h3>
|
||||
<button onClick={() => setShowCreateInvestmentModal(true)} className="py-2 px-3 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-1">
|
||||
<Plus className="w-4 h-4" /> Add Investment
|
||||
</button>
|
||||
@@ -767,27 +767,25 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
{investorTransactions.map(tx => (
|
||||
<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 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
|
||||
<button
|
||||
onClick={() => {
|
||||
const getAccountingInfo = (type: string, amount: number) => {
|
||||
if (type === 'investment') {
|
||||
@@ -840,17 +838,15 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className={`text-sm font-medium ${
|
||||
tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' || tx.type === 'referral_bonus' ? 'text-green-600' :
|
||||
<p className={`text-sm font-medium ${tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' || tx.type === 'referral_bonus' ? 'text-green-600' :
|
||||
tx.type === 'withdrawal' || tx.type === 'penalty' || tx.type === 'adjustment' ? 'text-red-600' : 'text-blue-600'
|
||||
}`}>
|
||||
}`}>
|
||||
{tx.type === 'earning' || tx.type === 'bike_earning' || tx.type === 'investment_return' || tx.type === 'referral_bonus' ? '+' : tx.type === 'withdrawal' || tx.type === 'penalty' || tx.type === 'adjustment' ? '-' : '+'}৳{tx.amount.toLocaleString()}
|
||||
</p>
|
||||
<span className={`text-xs font-medium px-2 py-0.5 rounded-full ${
|
||||
tx.status === 'completed' ? 'bg-green-100 text-green-700' :
|
||||
tx.status === 'pending' ? 'bg-amber-100 text-amber-700' :
|
||||
tx.status === 'cancelled' ? 'bg-red-100 text-red-700' : 'bg-slate-100 text-slate-700'
|
||||
}`}>
|
||||
<span className={`text-xs font-medium px-2 py-0.5 rounded-full ${tx.status === 'completed' ? 'bg-green-100 text-green-700' :
|
||||
tx.status === 'pending' ? 'bg-amber-100 text-amber-700' :
|
||||
tx.status === 'cancelled' ? 'bg-red-100 text-red-700' : 'bg-slate-100 text-slate-700'
|
||||
}`}>
|
||||
{tx.status}
|
||||
</span>
|
||||
</div>
|
||||
@@ -875,23 +871,21 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<Plus className="w-4 h-4" /> Upload Document
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="space-y-2 mb-6">
|
||||
{investor.kycDocuments?.map((doc, idx) => (
|
||||
<div key={idx} className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
|
||||
<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' :
|
||||
<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 === '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'
|
||||
}`} />
|
||||
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>
|
||||
@@ -911,7 +905,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<button onClick={() => alert('Edit document')} className="p-2 hover:bg-slate-200 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">
|
||||
<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>
|
||||
@@ -928,11 +922,11 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<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'
|
||||
{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.'}
|
||||
? 'Documents are under review. Verification typically takes 24-48 hours.'
|
||||
: 'Please upload required documents for verification.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -952,7 +946,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
|
||||
<div className="p-5">
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Select Bike</label>
|
||||
<select
|
||||
<select
|
||||
value={selectedBikeId}
|
||||
onChange={(e) => setSelectedBikeId(e.target.value)}
|
||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||
@@ -988,8 +982,8 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<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"
|
||||
<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"
|
||||
@@ -998,7 +992,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Plan Type *</label>
|
||||
<select
|
||||
<select
|
||||
value={newInvestment.planType}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, planType: e.target.value as any, expectedRoi: e.target.value === 'silver' ? 12 : e.target.value === 'gold' ? 15 : e.target.value === 'platinum' ? 18 : 20 })}
|
||||
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||
@@ -1016,7 +1010,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<div className="grid grid-cols-2 gap-2 max-h-32 overflow-y-auto border border-slate-200 rounded-lg p-2">
|
||||
{availableBikesForAssignment.map(bike => (
|
||||
<label key={bike.id} className="flex items-center gap-2 p-2 hover:bg-slate-50 rounded cursor-pointer">
|
||||
<input
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={newInvestment.selectedBikeIds.includes(bike.id)}
|
||||
onChange={(e) => {
|
||||
@@ -1037,7 +1031,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Investment Amount (৳) *</label>
|
||||
<input
|
||||
<input
|
||||
type="number"
|
||||
value={newInvestment.totalInvestment}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, totalInvestment: Number(e.target.value), monthlyReturn: Math.round(Number(e.target.value) * newInvestment.expectedRoi / 100 / 12) })}
|
||||
@@ -1047,7 +1041,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Monthly Return (৳)</label>
|
||||
<input
|
||||
<input
|
||||
type="number"
|
||||
value={newInvestment.monthlyReturn}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, monthlyReturn: Number(e.target.value) })}
|
||||
@@ -1057,7 +1051,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Expected ROI (%)</label>
|
||||
<input
|
||||
<input
|
||||
type="number"
|
||||
value={newInvestment.expectedRoi}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, expectedRoi: Number(e.target.value) })}
|
||||
@@ -1070,7 +1064,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<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
|
||||
<input
|
||||
type="date"
|
||||
value={newInvestment.startDate}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, startDate: e.target.value })}
|
||||
@@ -1079,7 +1073,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">End Date</label>
|
||||
<input
|
||||
<input
|
||||
type="date"
|
||||
value={newInvestment.endDate}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, endDate: e.target.value })}
|
||||
@@ -1091,7 +1085,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<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
|
||||
<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"
|
||||
@@ -1104,7 +1098,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Transaction Reference</label>
|
||||
<input
|
||||
<input
|
||||
type="text"
|
||||
value={newInvestment.transactionReference}
|
||||
onChange={(e) => setNewInvestment({ ...newInvestment, transactionReference: e.target.value })}
|
||||
@@ -1116,7 +1110,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
|
||||
<div>
|
||||
<label className="text-sm font-medium text-slate-600 mb-1 block">Notes</label>
|
||||
<textarea
|
||||
<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"
|
||||
@@ -1136,7 +1130,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
}
|
||||
};
|
||||
const debitDisplay = getDebitAccountDisplay(newInvestment.paymentMethod);
|
||||
|
||||
|
||||
return (
|
||||
<div className="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
@@ -1175,8 +1169,8 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
|
||||
<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}
|
||||
<button
|
||||
onClick={handleCreateInvestment}
|
||||
disabled={!newInvestment.planName || !newInvestment.totalInvestment}
|
||||
className="px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark disabled:opacity-50 flex items-center gap-2"
|
||||
>
|
||||
@@ -1409,13 +1403,13 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<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>
|
||||
@@ -1426,13 +1420,13 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
<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">
|
||||
@@ -1453,17 +1447,16 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</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' :
|
||||
<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">
|
||||
@@ -1486,21 +1479,21 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
</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()}
|
||||
<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
|
||||
<button
|
||||
onClick={() => {
|
||||
import('jspdf').then(jsPDF => {
|
||||
const doc = new jsPDF.default();
|
||||
@@ -1527,7 +1520,7 @@ Credit (Cr): Investor Liability ৳${newInvestment.totalInvestment.toLocaleStri
|
||||
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
|
||||
|
||||
@@ -946,7 +946,7 @@ export default function InvestorDetailPage() {
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h3 className="font-semibold text-slate-800">Assigned Bikes</h3>
|
||||
<p className="text-sm text-slate-500">{assignedBikes.length} bikes across {investor.investments?.length || 0} investment plans</p>
|
||||
<p className="text-sm text-slate-500">{assignedBikes.length} bikes across {investor.investments?.length || 0} EV Investment Plans</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
@@ -1060,7 +1060,7 @@ export default function InvestorDetailPage() {
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 className="font-semibold text-slate-800">Investment Plans</h3>
|
||||
<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">
|
||||
@@ -1871,7 +1871,7 @@ export default function InvestorDetailPage() {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-800 mb-3">Select Investment Plans & Bikes</h4>
|
||||
<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
|
||||
@@ -1896,7 +1896,7 @@ export default function InvestorDetailPage() {
|
||||
|
||||
<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">Investment Plans</p>
|
||||
<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) => {
|
||||
|
||||
Reference in New Issue
Block a user