2026-04-22 01:02:45 +06:00
'use client' ;
import { useState } from 'react' ;
import Link from 'next/link' ;
2026-05-14 13:54:02 +06:00
import { useParams , useRouter } from 'next/navigation' ;
2026-05-14 22:25:24 +06:00
import { investors as initialInvestors , bikes as initialBikes , transactions as initialTransactions , rentalPayments as initialRentalPayments } from '@/data/mockData' ;
2026-04-22 01:02:45 +06:00
import type { Investor } from '@/data/mockData' ;
2026-05-14 13:54:02 +06:00
import toast from 'react-hot-toast' ;
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 ,
UserCircle , Home , Briefcase , CreditCardIcon , Heart , PhoneCall , PhoneOutgoing , MessageSquare , Save ,
2026-05-14 22:25:24 +06:00
ShieldCheck , Building2 , Users , Check , AlertOctagon , Activity , Award , Camera , History , Settings
2026-04-22 01:02:45 +06:00
} from 'lucide-react' ;
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' ,
} ;
2026-05-14 13:54:02 +06:00
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 >
) ;
}
2026-04-22 01:02:45 +06:00
export default function InvestorDetailPage() {
const params = useParams ( ) ;
2026-05-14 13:54:02 +06:00
const router = useRouter ( ) ;
2026-04-22 01:02:45 +06:00
const investorId = params . id as string ;
2026-05-14 13:54:02 +06:00
2026-04-22 01:02:45 +06:00
const [ investors ] = useState < Investor [ ] > ( initialInvestors ) ;
const investor = investors . find ( i = > i . id === investorId ) ;
2026-05-14 13:54:02 +06:00
2026-04-22 01:02:45 +06:00
const assignedBikes = initialBikes . filter ( b = > b . investorId === investorId ) ;
2026-04-22 01:18:03 +06:00
// Investor transactions are filtered below
2026-05-14 13:54:02 +06:00
2026-04-22 01:02:45 +06:00
const [ activeTab , setActiveTab ] = useState ( 'overview' ) ;
const [ showEditModal , setShowEditModal ] = useState ( false ) ;
const [ showAssignBikeModal , setShowAssignBikeModal ] = useState ( false ) ;
const [ selectedBikeId , setSelectedBikeId ] = useState ( '' ) ;
2026-04-22 01:09:51 +06:00
const [ showCreateInvestmentModal , setShowCreateInvestmentModal ] = useState ( false ) ;
2026-05-14 19:49:57 +06:00
const [ showInvestmentSuccessModal , setShowInvestmentSuccessModal ] = useState ( false ) ;
const [ lastCreatedInvestment , setLastCreatedInvestment ] = useState < any > ( null ) ;
2026-04-26 14:56:12 +06:00
const [ showInvoiceModal , setShowInvoiceModal ] = useState ( false ) ;
const [ showJournalModal , setShowJournalModal ] = useState ( false ) ;
const [ selectedInvoice , setSelectedInvoice ] = useState < any > ( null ) ;
const [ investorJournals , setInvestorJournals ] = useState < any [ ] > ( [ ] ) ;
2026-04-22 01:18:03 +06:00
const [ showBankModal , setShowBankModal ] = useState ( false ) ;
2026-05-14 13:54:02 +06:00
const [ editingSection , setEditingSection ] = useState < string | null > ( null ) ;
const [ editForm , setEditForm ] = useState < any > ( { } ) ;
2026-04-22 01:18:03 +06:00
const [ showMobileBankingModal , setShowMobileBankingModal ] = useState ( false ) ;
const [ showTaxModal , setShowTaxModal ] = useState ( false ) ;
const [ showDocModal , setShowDocModal ] = useState ( false ) ;
2026-05-14 20:15:39 +06:00
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 } > ( { } ) ;
2026-04-22 01:18:03 +06:00
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 investorTransactions = initialTransactions . filter ( t = > t . investorId === investorId ) ;
2026-05-14 22:25:24 +06:00
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 : ''
} ) ;
2026-04-22 01:09:51 +06:00
const [ newInvestment , setNewInvestment ] = useState ( {
planName : '' ,
planType : 'gold' as 'silver' | 'gold' | 'platinum' | 'diamond' ,
selectedBikeIds : [ ] as string [ ] ,
totalInvestment : 0 ,
2026-05-15 03:10:37 +06:00
paidAmount : 0 ,
2026-05-15 12:25:24 +06:00
paymentType : 'full' as 'full' | 'partial' ,
2026-04-22 01:09:51 +06:00
monthlyReturn : 0 ,
expectedRoi : 15 ,
startDate : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ,
endDate : '' ,
paymentMethod : 'bank' as 'bank' | 'mobile' | 'cash' | 'cheque' ,
transactionReference : '' ,
notes : ''
} ) ;
2026-05-14 23:15:10 +06:00
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' }
] ) ;
2026-04-22 01:02:45 +06:00
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 = initialBikes . filter ( b = > ! b . investorId && b . status === 'available' ) ;
const handleAssignBike = ( ) = > {
alert ( 'Bike assignment functionality - would update bike investorId here' ) ;
setShowAssignBikeModal ( false ) ;
setSelectedBikeId ( '' ) ;
} ;
2026-04-22 01:09:51 +06:00
const handleCreateInvestment = ( ) = > {
2026-04-26 14:56:12 +06:00
const invId = ` INV- ${ Date . now ( ) } ` ;
const year = new Date ( ) . getFullYear ( ) ;
const transactionRef = newInvestment . transactionReference || ` INV/ ${ year } / ${ String ( investor . investments . length + 1 ) . padStart ( 4 , '0' ) } ` ;
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
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' } ;
}
} ;
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
const debitAccount = getDebitAccount ( newInvestment . paymentMethod ) ;
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
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' ,
2026-05-15 03:10:37 +06:00
amount : newInvestment.paidAmount ,
2026-04-26 14:56:12 +06:00
paymentMethod : newInvestment.paymentMethod
} ;
2026-05-14 13:54:02 +06:00
2026-05-14 22:25:24 +06:00
setInvestorJournals ( [ journalEntry , . . . investorJournals ] ) ;
2026-05-14 13:54:02 +06:00
2026-05-14 19:49:57 +06:00
setLastCreatedInvestment ( {
2026-04-22 01:09:51 +06:00
id : invId ,
investorId : investor.id ,
. . . newInvestment ,
actualEarnings : 0 ,
2026-05-14 19:49:57 +06:00
status : 'active' ,
2026-04-26 14:56:12 +06:00
transactionId : transactionRef ,
2026-05-14 19:49:57 +06:00
createdAt : new Date ( ) . toISOString ( ) ,
debitAccount ,
journalEntry
2026-04-22 01:09:51 +06:00
} ) ;
2026-05-14 13:54:02 +06:00
2026-04-22 01:09:51 +06:00
setShowCreateInvestmentModal ( false ) ;
2026-05-14 19:49:57 +06:00
setShowInvestmentSuccessModal ( true ) ;
2026-04-22 01:09:51 +06:00
setNewInvestment ( {
planName : '' ,
planType : 'gold' ,
selectedBikeIds : [ ] ,
totalInvestment : 0 ,
2026-05-15 03:10:37 +06:00
paidAmount : 0 ,
2026-05-15 12:25:24 +06:00
paymentType : 'full' ,
2026-04-22 01:09:51 +06:00
monthlyReturn : 0 ,
expectedRoi : 15 ,
startDate : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ,
endDate : '' ,
paymentMethod : 'bank' ,
transactionReference : '' ,
notes : ''
} ) ;
} ;
2026-04-22 01:02:45 +06:00
return (
< div className = "p-4 lg:p-6" >
2026-05-14 13:54:02 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
2026-05-14 13:54:02 +06:00
{ /* 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 >
2026-05-14 22:28:46 +06:00
{ / * < d i v c l a s s N a m e = " f l e x i t e m s - c e n t e r g a p - 2 f l e x - s h r i n k - 0 " >
2026-05-14 13:54:02 +06:00
< 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 >
2026-05-14 22:28:46 +06:00
< / div > * / }
2026-05-14 13:54:02 +06:00
< / div >
2026-04-22 01:02:45 +06:00
2026-05-14 13:54:02 +06:00
{ /* Stats Row */ }
< div className = "grid grid-cols-3 lg:grid-cols-6 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 >
2026-05-14 22:25:24 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
< div className = "p-3 bg-blue-50 rounded-lg border border-blue-100" >
2026-05-14 22:25:24 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
< / 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-red-50 rounded-lg border border-red-100" >
2026-05-14 22:25:24 +06:00
< p className = "text-xs text-red-600 font-medium" > Pending Request < / p >
2026-05-14 13:54:02 +06:00
< p className = "text-sm font-bold text-red-700" > ৳ { investor . pendingEarnings . toLocaleString ( ) } < / p >
< / div >
2026-05-14 22:25:24 +06:00
2026-05-14 13:54:02 +06:00
< / div >
2026-04-22 01:02:45 +06:00
< / 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 ( 'financial' ) }
className = { ` px-4 py-3 text-sm font-medium whitespace-nowrap ${ activeTab === 'financial' ? 'border-b-2 border-investor text-investor' : 'text-slate-500' } ` }
>
2026-05-14 22:25:24 +06:00
< 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
2026-04-22 01:02:45 +06:00
< / 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 >
2026-05-14 22:25:24 +06:00
2026-04-22 01:02:45 +06:00
< / div >
< div className = "p-5" >
{ activeTab === 'overview' && (
2026-05-14 13:54:02 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 13:54:02 +06:00
) : (
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 13:54:02 +06:00
) }
< / 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 13:54:02 +06:00
) : (
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 13:54:02 +06:00
) }
< / 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" >
2026-04-22 01:02:45 +06:00
< div >
2026-05-14 13:54:02 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) }
2026-05-14 13:54:02 +06:00
< / 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 >
2026-04-22 01:02:45 +06:00
< div >
2026-05-14 13:54:02 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) }
2026-05-14 13:54:02 +06:00
< / 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 >
2026-04-22 01:02:45 +06:00
< div >
2026-05-14 13:54:02 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) }
2026-05-14 13:54:02 +06:00
< / SectionCard >
2026-04-22 01:02:45 +06:00
2026-05-14 13:54:02 +06:00
< 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' ? (
2026-04-22 01:02:45 +06:00
< div >
2026-05-14 13:54:02 +06:00
< 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 >
) }
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 13:54:02 +06:00
) : (
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) }
2026-05-14 13:54:02 +06:00
< / SectionCard >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 13:54:02 +06:00
< / div >
2026-04-22 01:02:45 +06:00
{ 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 items-center justify-between mb-4" >
2026-05-14 19:49:57 +06:00
< div >
< h3 className = "font-semibold text-slate-800" > Assigned Bikes < / h3 >
2026-05-19 16:20:31 +06:00
< p className = "text-sm text-slate-500" > { assignedBikes . length } bikes across { investor . investments ? . length || 0 } EV Investment Plans < / p >
2026-05-14 19:49:57 +06:00
< / div >
2026-04-22 01:02:45 +06:00
< / div >
< div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" >
2026-05-14 19:49:57 +06:00
{ 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' ] ;
const planType = investment ? . planType || 'gold' ;
const status = statusConfig [ bike . status ] || statusConfig . available ;
return (
< Link
key = { bike . id }
href = { ` /bikes?bike= ${ bike . id } ` }
className = { ` block bg-white rounded-xl border ${ planBg [ planType ] } overflow-hidden hover:shadow-lg transition-all hover:scale-[1.02] cursor-pointer group ` }
>
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 19:49:57 +06:00
< 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 ` } >
2026-05-14 22:25:24 +06:00
< span className = { ` w-2 h-2 rounded-full ${ planType === 'silver' ? 'bg-slate-500' :
2026-05-14 19:49:57 +06:00
planType === 'gold' ? 'bg-amber-500' :
2026-05-14 22:25:24 +06:00
planType === 'platinum' ? 'bg-purple-500' : 'bg-blue-500'
} ` } />
2026-05-14 19:49:57 +06:00
{ 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 >
2026-05-14 22:25:24 +06:00
< span className = { ` text-xs font-medium ${ bike . batteryLevel > 50 ? 'text-green-600' :
2026-05-14 19:49:57 +06:00
bike . batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'
2026-05-14 22:25:24 +06:00
} ` }>{bike.batteryLevel}%</span>
2026-05-14 19:49:57 +06:00
< / div >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
2026-05-14 19:49:57 +06:00
< / Link >
) ;
} ) }
2026-04-22 01:02:45 +06:00
{ assignedBikes . length === 0 && (
2026-05-14 19:49:57 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
) }
< / div >
< / div >
) }
{ activeTab === 'investments' && (
< div className = "space-y-6" >
< div className = "flex items-center justify-between" >
2026-05-14 19:49:57 +06:00
< div >
2026-05-19 16:20:31 +06:00
< h3 className = "font-semibold text-slate-800" > EV Investment Plans < / h3 >
2026-05-14 19:49:57 +06:00
< 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
2026-04-22 01:02:45 +06:00
< / button >
< / div >
2026-05-14 19:49:57 +06:00
< 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 ;
2026-05-14 22:25:24 +06:00
2026-05-14 19:49:57 +06:00
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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 19:49:57 +06:00
< 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 >
2026-05-14 22:25:24 +06:00
2026-05-14 19:49:57 +06:00
< 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 >
2026-05-14 22:30:13 +06:00
{ / * < L i n k h r e f = { ` / a d m i n / i n v e s t o r s / $ { i n v e s t o r . i d } / i n v e s t m e n t s / $ { i n v . i d } / s t a t e m e n t ` } c l a s s N a m e = " f l e x - 1 p y - 2 t e x t - s m f o n t - m e d i u m t e x t - i n v e s t o r h o v e r : b g - i n v e s t o r / 1 0 r o u n d e d - l g b o r d e r b o r d e r - i n v e s t o r / 3 0 t e x t - c e n t e r f l e x i t e m s - c e n t e r j u s t i f y - c e n t e r g a p - 1 " >
2026-05-14 22:28:46 +06:00
< Printer className = "w-4 h-4" / > Statement
2026-05-14 22:30:13 +06:00
< / Link > * / }
2026-05-14 19:49:57 +06:00
< / div >
< / div >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
2026-05-14 19:49:57 +06:00
) ;
} ) }
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 19:49:57 +06:00
{ ( ! 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 >
) }
2026-04-22 01:02:45 +06:00
< / div >
) }
{ activeTab === 'financial' && (
< div className = "space-y-6" >
< div className = "grid lg:grid-cols-2 gap-6" >
< div >
2026-04-22 01:18:03 +06:00
< div className = "flex items-center justify-between mb-4" >
2026-05-14 20:15:39 +06:00
< h3 className = "font-semibold text-slate-800" > Bank Accounts ( { investor . bankAccounts ? . length || 0 } ) < / h3 >
2026-04-22 01:18:03 +06:00
< button onClick = { ( ) = > {
2026-05-14 20:15:39 +06:00
setEditingBankAccount ( { id : '' , bankName : '' , accountName : '' , accountNumber : '' , branch : '' , routing : '' , isPrimary : false } ) ;
2026-04-22 01:18:03 +06:00
setShowBankModal ( true ) ;
} } className = "text-sm text-investor hover:underline flex items-center gap-1" >
2026-05-14 20:15:39 +06:00
< Plus className = "w-4 h-4" / > Add Account
2026-04-22 01:18:03 +06:00
< / button >
< / div >
2026-04-22 01:02:45 +06:00
< div className = "space-y-3" >
2026-05-14 20:15:39 +06:00
{ 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" >
2026-05-15 01:31:21 +06:00
< 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" / >
2026-05-14 20:15:39 +06:00
< / div >
< div >
< p className = "font-semibold text-slate-800" > { account . bankName } < / p >
< p className = "text-xs text-slate-500" > { account . branch } < / p >
< / div >
< / div >
2026-05-15 01:31:21 +06:00
< 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 >
2026-04-22 01:18:03 +06:00
< / div >
2026-05-14 20:15:39 +06:00
< 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 >
) }
2026-04-22 01:18:03 +06:00
< / div >
2026-04-22 01:02:45 +06:00
< / div >
2026-05-14 20:15:39 +06:00
) )
2026-04-22 01:18:03 +06:00
) : (
2026-05-14 20:15:39 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
) }
< / div >
< / div >
< div >
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< div className = "space-y-3" >
2026-04-22 01:18:03 +06:00
{ 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" >
2026-05-15 01:31:21 +06:00
< p className = "text-xs text-purple-600 font-medium" > { investor . mobileBanking } < / p >
2026-04-22 01:18:03 +06:00
< p className = "text-xs text-slate-400" > { investor . mobileBankingNumber } < / p >
2026-04-22 01:02:45 +06:00
< / div >
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-04-22 01:18:03 +06:00
) : null }
2026-04-22 01:02:45 +06:00
{ 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 >
2026-04-22 01:18:03 +06:00
{ mb . verified ? (
2026-04-22 01:02:45 +06:00
< span className = "text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full" > Verified < / span >
2026-04-22 01:18:03 +06:00
) : (
< span className = "text-xs bg-amber-100 text-amber-700 px-2 py-1 rounded-full" > Pending < / span >
2026-04-22 01:02:45 +06:00
) }
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
) ) }
2026-04-22 01:18:03 +06:00
{ ( ! 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 >
) }
2026-04-22 01:02:45 +06:00
< / div >
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< div className = "space-y-3" >
2026-04-22 01:18:03 +06:00
{ 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 >
2026-04-22 01:02:45 +06:00
< / 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" >
2026-04-22 01:18:03 +06:00
< h3 className = "font-semibold text-slate-800" > All Transactions < / h3 >
< div className = "flex gap-2" >
2026-05-14 22:25:24 +06:00
< 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" >
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-04-22 01:18:03 +06:00
< 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 >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
2026-04-22 01:18:03 +06:00
) ) }
{ 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 >
2026-04-22 01:02:45 +06:00
< / div >
2026-04-22 01:18:03 +06:00
) }
< / div >
< / div >
< div >
< h4 className = "font-semibold text-slate-700 mb-3" > Transaction History < / h4 >
< div className = "space-y-2" >
2026-05-14 22:25:24 +06:00
{ 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 >
2026-04-22 01:18:03 +06:00
< / div >
2026-05-14 22:25:24 +06:00
< 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 >
2026-04-26 14:56:12 +06:00
< / div >
2026-04-22 01:18:03 +06:00
< / div >
< / div >
2026-05-14 22:25:24 +06:00
) ;
} ) }
2026-04-22 01:18:03 +06:00
< / div >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) }
{ activeTab === 'documents' && (
2026-05-14 22:25:24 +06:00
< 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" >
2026-04-22 01:18:03 +06:00
< Plus className = "w-4 h-4" / > Upload Document
< / button >
< / div >
2026-05-14 13:54:02 +06:00
2026-05-14 22:25:24 +06:00
< div className = "space-y-2" >
2026-04-22 01:02:45 +06:00
{ investor . kycDocuments ? . map ( ( doc , idx ) = > (
2026-05-14 22:25:24 +06:00
< div key = { idx } className = "flex items-center justify-between p-4 bg-white border border-slate-200 rounded-xl" >
2026-04-22 01:02:45 +06:00
< div className = "flex items-center gap-3" >
2026-05-14 13:54:02 +06:00
< div className = { ` w-12 h-12 rounded-lg flex items-center justify-center ${ doc . type === 'nid' ? 'bg-blue-100' :
2026-04-22 01:18:03 +06:00
doc . type === 'passport' ? 'bg-purple-100' :
2026-05-14 13:54:02 +06:00
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' :
2026-04-22 01:18:03 +06:00
doc . type === 'passport' ? 'text-purple-600' :
2026-05-14 13:54:02 +06:00
doc . type === 'bank_statement' ? 'text-green-600' :
doc . type === 'tin_certificate' ? 'text-amber-600' : 'text-slate-600'
} ` } />
2026-04-22 01:18:03 +06:00
< / div >
2026-04-22 01:02:45 +06:00
< div >
< p className = "text-sm font-medium text-slate-700 capitalize" > { doc . type . replace ( '_' , ' ' ) } < / p >
2026-04-22 01:18:03 +06:00
< p className = "text-xs text-slate-400" > { doc . number || 'No document number' } • Uploaded : { doc . uploadedAt || 'N/A' } < / p >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
< div className = "flex items-center gap-2" >
{ doc . verified ? (
2026-04-22 01:18:03 +06:00
< span className = "flex items-center gap-1 text-xs font-medium px-3 py-1.5 rounded-full bg-green-100 text-green-700" >
2026-04-22 01:02:45 +06:00
< CheckCircle className = "w-3 h-3" / > Verified
< / span >
) : (
2026-04-22 01:18:03 +06:00
< 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
2026-04-22 01:02:45 +06:00
< / span >
) }
2026-05-14 22:25:24 +06:00
< button onClick = { ( ) = > alert ( 'Edit document' ) } className = "p-2 hover:bg-slate-100 rounded-lg" >
2026-04-22 01:18:03 +06:00
< Edit className = "w-4 h-4 text-slate-400" / >
< / button >
2026-05-14 13:54:02 +06:00
< button onClick = { ( ) = > { if ( confirm ( 'Delete this document?' ) ) alert ( 'Document deleted' ) ; } } className = "p-2 hover:bg-red-50 rounded-lg" >
2026-04-22 01:18:03 +06:00
< Trash2 className = "w-4 h-4 text-red-400" / >
< / button >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) ) }
2026-05-14 22:25:24 +06:00
2026-04-22 01:02:45 +06:00
{ ( ! investor . kycDocuments || investor . kycDocuments . length === 0 ) && (
2026-04-22 01:18:03 +06:00
< div className = "text-center py-12 text-slate-400 border-2 border-dashed border-slate-200 rounded-lg" >
2026-04-22 01:02:45 +06:00
< FileText className = "w-12 h-12 mx-auto mb-2 opacity-50" / >
2026-04-22 01:18:03 +06:00
< p > No documents uploaded yet < / p >
2026-04-22 01:02:45 +06:00
< / div >
) }
< / div >
2026-04-22 01:18:03 +06:00
< 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" >
2026-05-14 13:54:02 +06:00
{ investor . kycStatus === 'verified'
2026-04-22 01:18:03 +06:00
? 'All documents have been verified. Investor is fully verified.'
: investor . kycStatus === 'pending'
2026-05-14 13:54:02 +06:00
? 'Documents are under review. Verification typically takes 24-48 hours.'
: 'Please upload required documents for verification.' }
2026-04-22 01:18:03 +06:00
< / p >
2026-04-22 01:02:45 +06:00
< / div >
< / div >
) }
2026-05-14 22:25:24 +06:00
{ 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 >
) }
2026-04-22 01:02:45 +06:00
< / div >
< / div >
2026-05-14 22:25:24 +06:00
{ 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 >
2026-05-19 16:20:31 +06:00
< h4 className = "font-semibold text-slate-800 mb-3" > Select EV Investment Plans & Bikes < / h4 >
2026-05-14 22:25:24 +06:00
< 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" >
2026-05-19 16:20:31 +06:00
< p className = "text-sm font-medium text-slate-700" > EV Investment Plans < / p >
2026-05-14 22:25:24 +06:00
< / 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 >
) }
2026-04-22 01:02:45 +06:00
{ showAssignBikeModal && (
< 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" > Assign Bike to Investor < / h2 >
< button onClick = { ( ) = > setShowAssignBikeModal ( 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" >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Select Bike < / label >
2026-05-14 13:54:02 +06:00
< select
2026-04-22 01:02:45 +06:00
value = { selectedBikeId }
onChange = { ( e ) = > setSelectedBikeId ( e . target . value ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
< option value = "" > Select a bike < / option >
{ availableBikesForAssignment . map ( bike = > (
< option key = { bike . id } value = { bike . id } >
{ bike . model } - { bike . plateNumber } ( ৳ { bike . purchasePrice ? . toLocaleString ( ) || 0 } )
< / option >
) ) }
< / select >
< / div >
< div className = "p-5 border-t border-slate-100 flex justify-end gap-3" >
< button onClick = { ( ) = > setShowAssignBikeModal ( 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 = { handleAssignBike } disabled = { ! selectedBikeId } className = "px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark disabled:opacity-50" > Assign Bike < / button >
< / div >
< / div >
< / div >
) }
2026-04-22 01:09:51 +06:00
{ showCreateInvestmentModal && (
< div className = "fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4" >
2026-05-14 19:49:57 +06:00
< div className = "bg-white rounded-xl shadow-xl w-full max-w-3xl max-h-[90vh] overflow-hidden flex flex-col" >
2026-04-22 01:09:51 +06:00
< div className = "p-5 border-b border-slate-100 flex items-center justify-between" >
2026-05-14 19:49:57 +06:00
< 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 >
2026-04-22 01:09:51 +06:00
< button onClick = { ( ) = > setShowCreateInvestmentModal ( false ) } className = "p-2 hover:bg-slate-100 rounded-lg" >
< X className = "w-5 h-5 text-slate-400" / >
< / button >
< / div >
2026-05-14 19:49:57 +06:00
< div className = "p-5 overflow-y-auto flex-1 space-y-5" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-2 block" > Select Plan Template < / label >
< div className = "grid grid-cols-2 gap-3" >
{ [
{ id : 'inv_demo_1' , name : '1 Bike Plan' , tier : 'Economy' , evBasePrice : 200000 , minQuantity : 1 , duration : 12 , maxInvestment : 1000000 } ,
{ id : 'inv_demo_2' , name : '5 Bike Plan' , tier : 'Standard' , evBasePrice : 180000 , minQuantity : 5 , duration : 24 , maxInvestment : 5000000 } ,
] . map ( plan = > (
< button
key = { plan . id }
onClick = { ( ) = > {
setNewInvestment ( {
. . . newInvestment ,
planName : plan.name ,
planType : plan.tier.toLowerCase ( ) as any ,
totalInvestment : plan.evBasePrice * plan . minQuantity ,
2026-05-15 03:10:37 +06:00
paidAmount : plan.evBasePrice * plan . minQuantity ,
2026-05-15 12:25:24 +06:00
paymentType : 'full' ,
2026-05-14 19:49:57 +06:00
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 } bikes < / p >
< p className = "text-sm text-slate-600 mt-1" > Duration : { plan . duration } months < / p >
< / button >
) ) }
< / div >
< / div >
2026-04-22 01:09:51 +06:00
< div className = "grid grid-cols-2 gap-4" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Plan Name * < / label >
2026-05-14 13:54:02 +06:00
< input
type = "text"
2026-04-22 01:09:51 +06:00
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"
2026-05-14 19:49:57 +06:00
placeholder = "Plan name"
2026-04-22 01:09:51 +06:00
/ >
< / div >
< div >
2026-05-14 19:49:57 +06:00
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Plan Type < / label >
2026-05-14 13:54:02 +06:00
< select
2026-04-22 01:09:51 +06:00
value = { newInvestment . planType }
2026-05-14 19:49:57 +06:00
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , planType : e.target.value as any } ) }
2026-04-22 01:09:51 +06:00
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
2026-05-14 19:49:57 +06:00
< option value = "silver" > Silver < / option >
< option value = "gold" > Gold < / option >
< option value = "platinum" > Platinum < / option >
< option value = "diamond" > Diamond < / option >
2026-04-22 01:09:51 +06:00
< / select >
< / div >
< / div >
2026-05-14 19:49:57 +06:00
< div className = "grid grid-cols-3 gap-4" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > EV Base Price ( ৳ ) < / label >
< input type = "number" value = { 200000 } className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-50" / >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Minimum Quantity ( Bikes ) < / label >
< input type = "number" value = { 1 } className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-50" / >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Min Investment ( ৳ ) < / label >
< input type = "number" value = { 200000 } disabled className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed" / >
< p className = "text-xs text-slate-400 mt-1" > = Qty × Base Price < / p >
2026-04-22 01:09:51 +06:00
< / div >
< / div >
2026-05-14 19:49:57 +06:00
< div className = "grid grid-cols-2 gap-4" >
2026-04-22 01:09:51 +06:00
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Investment Amount ( ৳ ) * < / label >
2026-05-14 13:54:02 +06:00
< input
2026-04-22 01:09:51 +06:00
type = "number"
value = { newInvestment . totalInvestment }
2026-05-15 03:10:37 +06:00
onChange = { ( e ) = > {
const val = Number ( e . target . value ) ;
setNewInvestment ( {
. . . newInvestment ,
totalInvestment : val ,
2026-05-15 12:25:24 +06:00
paidAmount : newInvestment.paymentType === 'full' ? val : Math.max ( val * 0.5 , newInvestment . paidAmount )
2026-05-15 03:10:37 +06:00
} ) ;
} }
2026-05-14 19:49:57 +06:00
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-yellow-50"
2026-04-22 01:09:51 +06:00
/ >
< / div >
< div >
2026-05-14 19:49:57 +06:00
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Max Investment ( ৳ ) < / label >
< input type = "number" value = { 1000000 } disabled className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed" / >
< / 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 = "number" value = { 12 } disabled className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed" / >
2026-04-22 01:09:51 +06:00
< / div >
< div >
2026-05-14 19:49:57 +06:00
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Lock - in Period ( Months ) < / label >
< input type = "number" value = { 3 } disabled className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed" / >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Early Exit Penalty ( % ) < / label >
< input type = "number" value = { 10 } disabled className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100 cursor-not-allowed" / >
< / div >
< / div >
2026-05-15 12:25:24 +06:00
2026-05-14 19:49:57 +06:00
< div className = "bg-amber-50 border border-amber-200 rounded-xl p-4" >
< h4 className = "text-sm font-semibold text-amber-800 mb-3 flex items-center gap-2" >
< TrendingUp className = "w-4 h-4" / >
FICO Share - Jaiben ' s Profit per Ride
< / h4 >
< p className = "text-xs text-amber-600 mb-3" > Profit sharing when bikes are rented to end customers < / p >
< div className = "grid grid-cols-3 gap-4" >
< div >
< label className = "text-xs text-slate-500 mb-1 block" > Single Rent ( % ) < / label >
< input type = "number" value = { 45 } disabled className = "w-full px-3 py-2 border border-amber-200 rounded-lg text-sm bg-white cursor-not-allowed" / >
< / div >
< div >
< label className = "text-xs text-slate-500 mb-1 block" > Rent to Own ( % ) < / label >
< input type = "number" value = { 55 } disabled className = "w-full px-3 py-2 border border-amber-200 rounded-lg text-sm bg-white cursor-not-allowed" / >
< / div >
< div >
< label className = "text-xs text-slate-500 mb-1 block" > Share an EV ( % ) < / label >
< input type = "number" value = { 60 } disabled className = "w-full px-3 py-2 border border-amber-200 rounded-lg text-sm bg-white cursor-not-allowed" / >
< / div >
2026-04-22 01:09:51 +06:00
< / 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 >
2026-05-14 13:54:02 +06:00
< input
2026-04-22 01:09:51 +06:00
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 >
2026-05-14 13:54:02 +06:00
< input
2026-04-22 01:09:51 +06:00
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 >
2026-05-15 12:25:24 +06:00
< div className = "bg-slate-50 rounded-xl p-4 border border-slate-200" >
< h4 className = "text-sm font-semibold text-slate-800 mb-3 flex items-center gap-2" >
< CreditCard className = "w-4 h-4 text-investor" / > Payment Options
< / h4 >
< div className = "grid grid-cols-1 sm:grid-cols-2 gap-3 mb-4" >
< label className = { ` flex items-center gap-3 p-3 rounded-lg border-2 cursor-pointer transition-all ${ newInvestment . paymentType === 'full' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300' } ` } >
< input
type = "radio"
name = "paymentType"
value = "full"
checked = { newInvestment . paymentType === 'full' }
onChange = { ( ) = > setNewInvestment ( { . . . newInvestment , paymentType : 'full' , paidAmount : newInvestment.totalInvestment } ) }
className = "w-4 h-4 text-investor"
/ >
< div className = "flex-1" >
< p className = "font-medium text-slate-800 text-sm" > Full Payment < / p >
< p className = "text-xs text-slate-500" > Pay total amount at once < / p >
< / div >
< span className = "text-lg font-bold text-green-600" > ৳ { newInvestment . totalInvestment . toLocaleString ( ) } < / span >
< / label >
< label className = { ` flex items-center gap-3 p-3 rounded-lg border-2 cursor-pointer transition-all ${ newInvestment . paymentType === 'partial' ? 'border-investor bg-investor/5' : 'border-slate-200 hover:border-slate-300' } ` } >
< input
type = "radio"
name = "paymentType"
value = "partial"
checked = { newInvestment . paymentType === 'partial' }
onChange = { ( ) = > setNewInvestment ( { . . . newInvestment , paymentType : 'partial' , paidAmount : Math.floor ( newInvestment . totalInvestment * 0.5 ) } ) }
className = "w-4 h-4 text-investor"
/ >
< div className = "flex-1" >
< p className = "font-medium text-slate-800 text-sm" > Partial Payment < / p >
< p className = "text-xs text-slate-500" > Pay initial amount ( 50 % min ) < / p >
< / div >
< span className = "text-sm font-bold text-amber-600" > Min ৳ { Math . floor ( newInvestment . totalInvestment * 0.5 ) . toLocaleString ( ) } < / span >
< / label >
< / div >
{ newInvestment . paymentType === 'partial' && (
< div className = "border-t border-slate-200 pt-4 mt-4" >
< label className = "text-sm font-medium text-slate-600 mb-2 block" > Initial Payment ( ৳ ) * < / label >
< input
type = "number"
value = { newInvestment . paidAmount }
onChange = { ( e ) = > {
const val = Number ( e . target . value ) ;
if ( val >= newInvestment . totalInvestment * 0.5 && val <= newInvestment . totalInvestment ) {
setNewInvestment ( { . . . newInvestment , paidAmount : val } ) ;
}
} }
className = "w-full px-3 py-2 border border-investor rounded-lg text-sm bg-white"
/ >
< p className = "text-xs text-slate-500 mt-2" > Balance : ৳ { ( newInvestment . totalInvestment - newInvestment . paidAmount ) . toLocaleString ( ) } < / p >
< / div >
) }
< / div >
2026-04-22 01:09:51 +06:00
< div className = "grid grid-cols-2 gap-4" >
< div >
2026-05-14 19:49:57 +06:00
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Payment Method < / label >
2026-05-14 13:54:02 +06:00
< select
2026-04-22 01:09:51 +06:00
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 >
2026-05-14 13:54:02 +06:00
< input
2026-04-22 01:09:51 +06:00
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 >
2026-05-14 19:49:57 +06:00
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Description < / label >
2026-05-14 13:54:02 +06:00
< textarea
2026-04-22 01:09:51 +06:00
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 >
2026-05-14 19:49:57 +06:00
< 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 >
2026-04-26 14:56:12 +06:00
< / div >
2026-05-15 03:10:37 +06:00
< p className = "font-bold text-green-700" > ৳ { newInvestment . paidAmount . toLocaleString ( ) } < / p >
2026-05-14 19:49:57 +06:00
< / 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 >
2026-04-26 14:56:12 +06:00
< / div >
2026-05-14 19:49:57 +06:00
< / 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 >
2026-04-26 14:56:12 +06:00
< / div >
2026-05-15 03:10:37 +06:00
< p className = "font-bold text-blue-700" > ৳ { newInvestment . paidAmount . toLocaleString ( ) } < / p >
2026-04-26 14:56:12 +06:00
< / div >
< / div >
2026-05-14 19:49:57 +06:00
< / div >
< / div >
2026-05-15 03:10:37 +06:00
2026-04-22 01:09:51 +06:00
< / div >
< div className = "p-5 border-t border-slate-100 flex justify-end gap-3" >
2026-05-14 19:49:57 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
< button
onClick = { handleCreateInvestment }
2026-04-22 01:09:51 +06:00
disabled = { ! newInvestment . planName || ! newInvestment . totalInvestment }
2026-05-14 19:49:57 +06:00
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"
2026-04-22 01:09:51 +06:00
>
2026-05-14 19:49:57 +06:00
< Plus className = "w-4 h-4" / > Create Investment
2026-04-22 01:09:51 +06:00
< / button >
< / div >
< / div >
< / div >
) }
2026-04-22 01:18:03 +06:00
{ 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" >
2026-05-14 20:15:39 +06:00
< h2 className = "text-lg font-bold text-slate-800" > { editingBankAccount . id ? 'Edit' : 'Add' } Bank Account < / h2 >
2026-04-22 01:18:03 +06:00
< 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" >
2026-05-14 20:15:39 +06:00
{ 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 >
< / >
) }
2026-04-22 01:18:03 +06:00
< / div >
< div className = "p-5 border-t border-slate-100 flex justify-between" >
2026-05-14 20:15:39 +06:00
{ 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 >
< / >
2026-04-22 01:18:03 +06:00
) }
< / 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 >
) }
2026-05-14 20:15:39 +06:00
{ 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 >
) }
2026-04-22 01:18:03 +06:00
{ 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 10 MB < / 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 >
) }
2026-04-26 14:56:12 +06:00
{ 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< div className = "flex justify-between mb-2" >
< span className = "text-xs text-slate-500" > Status < / span >
2026-05-14 13:54:02 +06:00
< span className = { ` text-xs px-2 py-1 rounded-full ${ selectedInvoice . status === 'completed' ? 'bg-green-100 text-green-700' :
2026-04-26 14:56:12 +06:00
selectedInvoice . status === 'pending' ? 'bg-amber-100 text-amber-700' : 'bg-slate-100 text-slate-700'
2026-05-14 13:54:02 +06:00
} ` }>
2026-04-26 14:56:12 +06:00
{ selectedInvoice . status }
< / span >
< / div >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< 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 >
2026-05-14 13:54:02 +06:00
2026-04-26 14:56:12 +06:00
< div className = "p-5 border-t border-slate-100 flex justify-between" >
2026-05-14 13:54:02 +06:00
< button
onClick = { ( ) = > window . print ( ) }
2026-04-26 14:56:12 +06:00
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 >
2026-05-14 13:54:02 +06:00
< button
2026-04-26 14:56:12 +06:00
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 ` ) ;
} ) ;
2026-05-14 13:54:02 +06:00
} }
2026-04-26 14:56:12 +06:00
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 >
) }
2026-05-14 19:49:57 +06:00
{ 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 >
) }
2026-05-14 23:15:10 +06:00
{ 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 >
) }
2026-04-22 01:02:45 +06:00
< / div >
) ;
}