2026-04-22 01:02:45 +06:00
'use client' ;
import { useState } from 'react' ;
import Link from 'next/link' ;
import { useParams } from 'next/navigation' ;
import { investors as initialInvestors , bikes as initialBikes , transactions as initialTransactions } from '@/data/mockData' ;
import type { Investor } from '@/data/mockData' ;
import {
ArrowLeft , Wallet , TrendingUp , Banknote , Calendar , Phone , Mail , MapPin , Edit , Trash2 , Plus , X , Bike ,
User , FileText , CreditCard , DollarSign , Clock , ChevronDown , ExternalLink , Download , Upload ,
AlertTriangle , Shield , Star , CheckCircle , XCircle , Search , Filter
} 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' ,
} ;
export default function InvestorDetailPage() {
const params = useParams ( ) ;
const investorId = params . id as string ;
const [ investors ] = useState < Investor [ ] > ( initialInvestors ) ;
const investor = investors . find ( i = > i . id === investorId ) ;
const assignedBikes = initialBikes . filter ( b = > b . investorId === investorId ) ;
const investorTransactions = initialTransactions . filter ( t = > t . userId === investor ? . userId ) ;
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 ) ;
const [ newInvestment , setNewInvestment ] = useState ( {
planName : '' ,
planType : 'gold' as 'silver' | 'gold' | 'platinum' | 'diamond' ,
selectedBikeIds : [ ] as string [ ] ,
totalInvestment : 0 ,
monthlyReturn : 0 ,
expectedRoi : 15 ,
startDate : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ,
endDate : '' ,
paymentMethod : 'bank' as 'bank' | 'mobile' | 'cash' | 'cheque' ,
transactionReference : '' ,
notes : ''
} ) ;
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 = ( ) = > {
const invId = ` ip ${ Date . now ( ) } ` ;
const transactionId = ` INV/ ${ new Date ( ) . getFullYear ( ) } / ${ String ( Math . floor ( Math . random ( ) * 1000 ) ) . padStart ( 3 , '0' ) } ` ;
console . log ( 'Creating Investment:' , {
id : invId ,
investorId : investor.id ,
. . . newInvestment ,
actualEarnings : 0 ,
status : 'active' as const ,
transactionId : transactionId ,
createdAt : new Date ( ) . toISOString ( )
} ) ;
console . log ( 'Accounting Entry:' , {
entryId : ` AC- ${ Date . now ( ) } ` ,
type : 'investment_created' ,
investorId : investor.id ,
investmentId : invId ,
amount : newInvestment.totalInvestment ,
debitAccount : 'Investment Asset - Investor' ,
creditAccount : newInvestment.paymentMethod === 'bank' ? 'Bank Account' : 'Cash Account' ,
transactionRef : transactionId ,
createdAt : new Date ( ) . toISOString ( )
} ) ;
alert ( ` Investment created successfully! \ n \ nInvestment ID: ${ invId } \ nTransaction Ref: ${ transactionId } \ nAmount: ৳ ${ newInvestment . totalInvestment . toLocaleString ( ) } \ n \ nAccounting entries have been logged. ` ) ;
setShowCreateInvestmentModal ( false ) ;
setNewInvestment ( {
planName : '' ,
planType : 'gold' ,
selectedBikeIds : [ ] ,
totalInvestment : 0 ,
monthlyReturn : 0 ,
expectedRoi : 15 ,
startDate : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ,
endDate : '' ,
paymentMethod : 'bank' ,
transactionReference : '' ,
notes : ''
} ) ;
} ;
2026-04-22 01:02:45 +06:00
return (
< div className = "p-4 lg:p-6" >
< div className = "flex items-center justify-between mb-6" >
< div className = "flex items-center gap-4" >
< Link href = "/admin/investors" className = "p-2 hover:bg-slate-100 rounded-lg" >
< ArrowLeft className = "w-5 h-5 text-slate-600" / >
< / Link >
< div >
< h1 className = "text-2xl lg:text-3xl font-extrabold text-slate-800" > { investor . name } < / h1 >
< p className = "text-sm text-slate-500" > { investor . id } • { investor . email } < / p >
< / div >
< / div >
< div className = "flex items-center gap-2" >
< button onClick = { ( ) = > setShowEditModal ( true ) } className = "py-2.5 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.5 px-4 bg-red-500 text-white rounded-lg font-semibold text-sm hover:bg-red-600 flex items-center gap-2" >
< Trash2 className = "w-4 h-4" / > Delete
< / button >
< / div >
< / div >
< div className = "flex flex-wrap gap-2 mb-6" >
< span className = { ` inline-flex items-center gap-1 text-sm font-medium px-3 py-1.5 rounded-full ${ statusColors [ investor . status ] } ` } >
{ investor . status }
< / span >
{ investor . investments && investor . investments . length > 0 && (
< span className = { ` inline-flex items-center gap-1 text-sm font-medium px-3 py-1.5 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-sm font-medium px-3 py-1.5 rounded-full ${ kycColors [ investor . kycStatus ] } ` } >
< Shield className = "w-4 h-4" / > KYC { investor . kycStatus }
< / span >
< span className = { ` inline-flex items-center gap-1 text-sm font-medium px-3 py-1.5 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 className = "grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6" >
< div className = "bg-white rounded-xl p-5 shadow-sm border border-slate-100" >
< div className = "flex items-center gap-3" >
< div className = "w-12 h-12 rounded-xl bg-purple-50 flex items-center justify-center" >
< Wallet className = "w-6 h-6 text-purple-600" / >
< / div >
< div >
< p className = "text-2xl font-extrabold text-slate-800" > ৳ { investor . totalInvested . toLocaleString ( ) } < / p >
< p className = "text-sm text-slate-500" > Total Invested < / p >
< / div >
< / div >
< / div >
< div className = "bg-white rounded-xl p-5 shadow-sm border border-slate-100" >
< div className = "flex items-center gap-3" >
< div className = "w-12 h-12 rounded-xl bg-green-50 flex items-center justify-center" >
< TrendingUp className = "w-6 h-6 text-green-600" / >
< / div >
< div >
< p className = "text-2xl font-extrabold text-slate-800" > ৳ { investor . totalEarnings . toLocaleString ( ) } < / p >
< p className = "text-sm text-slate-500" > Total Earnings < / p >
< / div >
< / div >
< / div >
< div className = "bg-white rounded-xl p-5 shadow-sm border border-slate-100" >
< div className = "flex items-center gap-3" >
< div className = "w-12 h-12 rounded-xl bg-blue-50 flex items-center justify-center" >
< Bike className = "w-6 h-6 text-blue-600" / >
< / div >
< div >
< p className = "text-2xl font-extrabold text-slate-800" > { investor . activeBikes } < / p >
< p className = "text-sm text-slate-500" > Active Bikes < / p >
< / div >
< / div >
< / div >
< div className = "bg-white rounded-xl p-5 shadow-sm border border-slate-100" >
< div className = "flex items-center gap-3" >
< div className = "w-12 h-12 rounded-xl bg-amber-50 flex items-center justify-center" >
< Calendar className = "w-6 h-6 text-amber-600" / >
< / div >
< div >
< p className = "text-2xl font-extrabold text-slate-800" > { investor . roi } % < / p >
< p className = "text-sm text-slate-500" > ROI < / p >
< / 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' } ` }
>
< Banknote className = "w-4 h-4 inline mr-1" / > Financial
< / button >
< button
onClick = { ( ) = > setActiveTab ( 'transactions' ) }
className = { ` px-4 py-3 text-sm font-medium whitespace-nowrap ${ activeTab === 'transactions' ? 'border-b-2 border-investor text-investor' : 'text-slate-500' } ` }
>
< DollarSign className = "w-4 h-4 inline mr-1" / > Transactions
< / button >
< button
onClick = { ( ) = > setActiveTab ( 'documents' ) }
className = { ` px-4 py-3 text-sm font-medium whitespace-nowrap ${ activeTab === 'documents' ? 'border-b-2 border-investor text-investor' : 'text-slate-500' } ` }
>
< FileText className = "w-4 h-4 inline mr-1" / > Documents
< / button >
< / div >
< div className = "p-5" >
{ activeTab === 'overview' && (
< div className = "space-y-6" >
< div className = "grid lg:grid-cols-2 gap-6" >
< div >
< h3 className = "font-semibold text-slate-800 mb-4" > Personal Information < / h3 >
< div className = "space-y-3" >
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< User className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Full Name < / p >
< p className = "font-medium text-slate-700" > { investor . name } < / p >
< / div >
< / div >
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Phone className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Phone < / p >
< p className = "font-medium text-slate-700" > { investor . phone } < / p >
< / div >
< / div >
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Mail className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Email < / p >
< p className = "font-medium text-slate-700" > { investor . email } < / p >
< / div >
< / div >
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< MapPin className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Address < / p >
< p className = "font-medium text-slate-700" > { investor . address } < / p >
< / div >
< / div >
{ investor . dateOfBirth && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Calendar className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Date of Birth < / p >
< p className = "font-medium text-slate-700" > { investor . dateOfBirth } < / p >
< / div >
< / div >
) }
{ investor . nidNumber && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Shield className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > NID Number < / p >
< p className = "font-medium text-slate-700" > { investor . nidNumber } < / p >
< / div >
< / div >
) }
< / div >
< / div >
< div >
< h3 className = "font-semibold text-slate-800 mb-4" > Emergency Contact < / h3 >
< div className = "space-y-3" >
{ investor . emergencyContactName && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Phone className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Contact < / p >
< p className = "font-medium text-slate-700" > { investor . emergencyContactName } < / p >
< p className = "text-xs text-slate-400" > { investor . emergencyContactRelation } • { investor . emergencyContactPhone } < / p >
< / div >
< / div >
) }
< / div >
< h3 className = "font-semibold text-slate-800 mb-4 mt-6" > Investment Details < / h3 >
< div className = "space-y-3" >
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Calendar className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Total Investments < / p >
< p className = "font-medium text-slate-700" >
{ investor . investments ? . length || 0 } active investments
< / p >
< / div >
< / div >
< 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" > Overall Status < / p >
< p className = "font-medium text-slate-700 capitalize" > { investor . status } < / p >
< / div >
< / div >
{ investor . referralCode && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Star className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Referral Code < / p >
< p className = "font-medium text-slate-700" > { investor . referralCode } < / p >
< p className = "text-xs text-slate-400" > Referrals : { investor . totalReferrals } • Earnings : ৳ { investor . referralEarnings } < / p >
< / div >
< / div >
) }
< / div >
< / div >
< / div >
{ investor . notes && (
< div className = "mt-6" >
< h3 className = "font-semibold text-slate-800 mb-2" > Notes < / h3 >
< p className = "text-sm text-slate-600 bg-slate-50 p-3 rounded-lg" > { investor . notes } < / p >
< / div >
) }
< / div >
) }
{ activeTab === 'bikes' && (
< div >
< div className = "flex items-center justify-between mb-4" >
< h3 className = "font-semibold text-slate-800" > Assigned Bikes < / h3 >
< button
onClick = { ( ) = > setShowAssignBikeModal ( true ) }
className = "py-2 px-3 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-1"
>
< Plus className = "w-4 h-4" / > Assign Bike
< / button >
< / div >
< div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" >
{ assignedBikes . map ( bike = > (
< div key = { bike . id } className = "bg-slate-50 rounded-xl p-4" >
< div className = "flex items-start justify-between mb-3" >
< div className = "flex items-center gap-3" >
< div className = "w-12 h-12 rounded-xl bg-white flex items-center justify-center shadow-sm" >
< Bike className = "w-6 h-6 text-blue-600" / >
< / div >
< div >
< p className = "font-semibold text-slate-700" > { bike . model } < / p >
< p className = "text-xs text-slate-400" > { bike . brand } < / p >
< / div >
< / div >
< span className = { ` text-xs font-medium px-2.5 py-1 rounded-full ${ bikeStatusColors [ bike . status ] } ` } >
{ bike . status }
< / span >
< / div >
< div className = "space-y-2 text-xs" >
< div className = "flex justify-between" >
< span className = "text-slate-500" > Plate < / span >
< span className = "font-medium" > { bike . plateNumber } < / span >
< / div >
< div className = "flex justify-between" >
< span className = "text-slate-500" > Location < / span >
< span className = "font-medium" > { bike . location } < / span >
< / div >
< div className = "flex justify-between" >
< span className = "text-slate-500" > Battery < / span >
< span className = { ` font-medium ${ bike . batteryLevel > 50 ? 'text-green-600' : bike . batteryLevel > 20 ? 'text-amber-600' : 'text-red-600' } ` } > { bike . batteryLevel } % < / span >
< / div >
< div className = "flex justify-between" >
< span className = "text-slate-500" > Purchase Price < / span >
< span className = "font-medium text-purple-600" > ৳ { bike . purchasePrice ? . toLocaleString ( ) || 0 } < / span >
< / div >
< div className = "flex justify-between" >
< span className = "text-slate-500" > Total Earnings < / span >
< span className = "font-medium text-green-600" > ৳ { bike . totalEarnings ? . toLocaleString ( ) || 0 } < / span >
< / div >
< / div >
< / div >
) ) }
{ assignedBikes . length === 0 && (
< div className = "col-span-full text-center py-8 text-slate-400" >
< Bike className = "w-12 h-12 mx-auto mb-2 opacity-50" / >
< p > No bikes assigned yet < / p >
< / div >
) }
< / div >
< / div >
) }
{ activeTab === 'investments' && (
< div className = "space-y-6" >
< div className = "flex items-center justify-between" >
< h3 className = "font-semibold text-slate-800" > Investment Plans < / h3 >
2026-04-22 01:09:51 +06:00
< button onClick = { ( ) = > setShowCreateInvestmentModal ( true ) } className = "py-2 px-3 bg-investor text-white rounded-lg text-sm font-medium hover:bg-investor-dark flex items-center gap-1" >
2026-04-22 01:02:45 +06:00
< Plus className = "w-4 h-4" / > Add Investment
< / button >
< / div >
< div className = "grid grid-cols-1 md:grid-cols-2 gap-4" >
{ investor . investments ? . map ( ( inv ) = > (
< div key = { inv . id } className = "bg-slate-50 rounded-xl p-4" >
< div className = "flex items-start justify-between mb-3" >
< div >
< p className = "font-semibold text-slate-700" > { inv . planName } < / p >
< p className = "text-xs text-slate-400" > { inv . planType } Plan < / p >
< / div >
< span className = { ` text-xs font-medium px-2.5 py-1 rounded-full ${ planColors [ inv . planType ] } ` } >
{ inv . status }
< / span >
< / div >
< div className = "grid grid-cols-2 gap-2 text-xs mb-3" >
< div className = "bg-white rounded-lg p-2" >
< p className = "text-slate-400" > Investment < / p >
< p className = "font-medium text-purple-600" > ৳ { inv . totalInvestment . toLocaleString ( ) } < / p >
< / div >
< div className = "bg-white rounded-lg p-2" >
< p className = "text-slate-400" > Monthly Return < / p >
< p className = "font-medium text-green-600" > ৳ { inv . monthlyReturn . toLocaleString ( ) } < / p >
< / div >
< div className = "bg-white rounded-lg p-2" >
< p className = "text-slate-400" > Expected ROI < / p >
< p className = "font-medium text-slate-700" > { inv . expectedRoi } % < / p >
< / div >
< div className = "bg-white rounded-lg p-2" >
< p className = "text-slate-400" > Actual Earned < / p >
< p className = "font-medium text-green-600" > ৳ { inv . actualEarnings . toLocaleString ( ) } < / p >
< / div >
< / div >
< div className = "flex items-center justify-between text-xs" >
< span className = "text-slate-400" > { inv . startDate } to { inv . endDate || 'Ongoing' } < / span >
< span className = "capitalize" > { inv . paymentMethod } < / span >
< / div >
< / div >
) ) }
{ ( ! investor . investments || investor . investments . length === 0 ) && (
< div className = "col-span-full text-center py-8 text-slate-400" >
< TrendingUp className = "w-12 h-12 mx-auto mb-2 opacity-50" / >
< p > No investments yet < / p >
< button className = "mt-2 px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark" >
Create First Investment
< / button >
< / div >
) }
< / div >
< / div >
) }
{ activeTab === 'financial' && (
< div className = "space-y-6" >
< div className = "grid lg:grid-cols-2 gap-6" >
< div >
< h3 className = "font-semibold text-slate-800 mb-4" > Bank Details < / h3 >
< div className = "space-y-3" >
{ investor . bankName && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Banknote className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Bank < / p >
< p className = "font-medium text-slate-700" > { investor . bankName } < / p >
< p className = "text-xs text-slate-400" > { investor . bankBranch } < / p >
< / div >
< / div >
) }
{ investor . bankAccountNumber && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< CreditCard className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > Account < / p >
< p className = "font-medium text-slate-700" > { investor . bankAccountName } < / p >
< p className = "text-xs text-slate-400" > { investor . bankAccountNumber } < / p >
< / div >
< / div >
) }
< / div >
< / div >
< div >
< h3 className = "font-semibold text-slate-800 mb-4" > Mobile Banking < / h3 >
< div className = "space-y-3" >
{ investor . mobileBanking && (
< div className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Phone className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-xs text-slate-500" > { investor . mobileBanking } ( Primary ) < / p >
< p className = "font-medium text-slate-700" > { investor . mobileBankingNumber } < / p >
< / div >
< / div >
) }
{ investor . additionalMobileBanking ? . map ( ( mb , idx ) = > (
< div key = { idx } className = "flex items-center gap-3 p-3 bg-slate-50 rounded-lg" >
< Phone className = "w-5 h-5 text-slate-400" / >
< div className = "flex-1" >
< p className = "text-xs text-slate-500" > { mb . provider } < / p >
< p className = "font-medium text-slate-700" > { mb . number } < / p >
< / div >
{ mb . verified && (
< span className = "text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full" > Verified < / span >
) }
< / div >
) ) }
< / div >
< h3 className = "font-semibold text-slate-800 mb-4 mt-6" > Tax Information < / h3 >
< div className = "space-y-3" >
{ 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 >
< / div >
< / div >
< div >
< h3 className = "font-semibold text-slate-800 mb-4" > Investment Summary < / h3 >
< div className = "grid grid-cols-2 lg:grid-cols-4 gap-4" >
< div className = "bg-purple-50 rounded-lg p-4" >
< p className = "text-sm text-purple-600" > Total Invested < / p >
< p className = "text-xl font-bold text-purple-700" > ৳ { investor . totalInvested . toLocaleString ( ) } < / p >
< / div >
< div className = "bg-green-50 rounded-lg p-4" >
< p className = "text-sm text-green-600" > Total Earnings < / p >
< p className = "text-xl font-bold text-green-700" > ৳ { investor . totalEarnings . toLocaleString ( ) } < / p >
< / div >
< div className = "bg-amber-50 rounded-lg p-4" >
< p className = "text-sm text-amber-600" > Pending Earnings < / p >
< p className = "text-xl font-bold text-amber-700" > ৳ { investor . pendingEarnings . toLocaleString ( ) } < / p >
< / div >
< div className = "bg-slate-50 rounded-lg p-4" >
< p className = "text-sm text-slate-600" > Total Withdrawn < / p >
< p className = "text-xl font-bold text-slate-700" > ৳ { investor . totalWithdrawn . toLocaleString ( ) } < / p >
< / div >
< / div >
< / div >
< / div >
) }
{ activeTab === 'transactions' && (
< div >
< div className = "flex items-center justify-between mb-4" >
< h3 className = "font-semibold text-slate-800" > Transactions < / h3 >
< button className = "py-2 px-3 border border-slate-200 text-slate-600 rounded-lg text-sm font-medium hover:bg-slate-50 flex items-center gap-1" >
< Download className = "w-4 h-4" / > Export
< / button >
< / div >
< div className = "space-y-2" >
{ investorTransactions . map ( tx = > (
< div key = { tx . id } className = "flex items-center justify-between p-3 bg-slate-50 rounded-lg" >
< div className = "flex items-center gap-3" >
< div className = { ` w-10 h-10 rounded-full flex items-center justify-center ${
tx . type === 'earning' ? 'bg-green-100' :
tx . type === 'withdrawal' ? 'bg-red-100' : 'bg-blue-100'
} ` }>
< DollarSign className = { ` w-5 h-5 ${
tx . type === 'earning' ? 'text-green-600' :
tx . type === 'withdrawal' ? 'text-red-600' : 'text-blue-600'
} ` } />
< / div >
< div >
< p className = "text-sm font-medium text-slate-700" > { tx . description } < / p >
< p className = "text-xs text-slate-400" > { tx . createdAt } < / p >
< / div >
< / div >
< div className = "text-right" >
< p className = { ` text-sm font-medium ${
tx . type === 'earning' ? 'text-green-600' :
tx . type === 'withdrawal' ? 'text-red-600' : 'text-blue-600'
} ` }>
{ tx . type === 'earning' ? '+' : tx . type === 'withdrawal' ? '-' : '+' } ৳ { tx . amount . toLocaleString ( ) }
< / p >
< span className = { ` text-xs font-medium px-2 py-0.5 rounded-full ${
tx . status === 'completed' ? 'bg-green-100 text-green-700' :
tx . status === 'pending' ? 'bg-amber-100 text-amber-700' : 'bg-red-100 text-red-700'
} ` }>
{ tx . status }
< / span >
< / div >
< / div >
) ) }
{ investorTransactions . length === 0 && (
< div className = "text-center py-8 text-slate-400" >
< DollarSign className = "w-12 h-12 mx-auto mb-2 opacity-50" / >
< p > No transactions yet < / p >
< / div >
) }
< / div >
< / div >
) }
{ activeTab === 'documents' && (
< div >
< h3 className = "font-semibold text-slate-800 mb-4" > Uploaded Documents < / h3 >
< div className = "space-y-2" >
{ investor . kycDocuments ? . map ( ( doc , idx ) = > (
< div key = { idx } className = "flex items-center justify-between p-3 bg-slate-50 rounded-lg" >
< div className = "flex items-center gap-3" >
< FileText className = "w-5 h-5 text-slate-400" / >
< div >
< p className = "text-sm font-medium text-slate-700 capitalize" > { doc . type . replace ( '_' , ' ' ) } < / p >
< p className = "text-xs text-slate-400" > { doc . number || 'No number' } < / p >
< / div >
< / div >
< div className = "flex items-center gap-2" >
{ doc . verified ? (
< span className = "flex items-center gap-1 text-xs font-medium px-2 py-1 rounded-full bg-green-100 text-green-700" >
< CheckCircle className = "w-3 h-3" / > Verified
< / span >
) : (
< span className = "flex items-center gap-1 text-xs font-medium px-2 py-1 rounded-full bg-amber-100 text-amber-700" >
< Clock className = "w-3 h-3" / > Pending
< / span >
) }
< / div >
< / div >
) ) }
{ ( ! investor . kycDocuments || investor . kycDocuments . length === 0 ) && (
< div className = "text-center py-8 text-slate-400" >
< FileText className = "w-12 h-12 mx-auto mb-2 opacity-50" / >
< p > No documents uploaded < / p >
< / div >
) }
< / div >
< div className = "mt-4 border-2 border-dashed border-slate-200 rounded-lg p-8 text-center" >
< FileText className = "w-12 h-12 text-slate-300 mx-auto mb-2" / >
< p className = "text-sm text-slate-500" > Drag and drop files here , or click to browse < / p >
< button className = "mt-2 px-4 py-2 bg-slate-100 text-slate-600 rounded-lg text-sm hover:bg-slate-200" > Browse Files < / button >
< / div >
< / div >
) }
< / div >
< / div >
{ 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 >
< select
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" >
< 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" > Create New Investment < / h2 >
< button onClick = { ( ) = > setShowCreateInvestmentModal ( false ) } className = "p-2 hover:bg-slate-100 rounded-lg" >
< X className = "w-5 h-5 text-slate-400" / >
< / button >
< / div >
< div className = "p-5 overflow-y-auto flex-1 space-y-4" >
< div className = "grid grid-cols-2 gap-4" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Plan Name * < / label >
< input
type = "text"
value = { newInvestment . planName }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , planName : e.target.value } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder = "e.g., Gold EV Fleet 2024"
/ >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Plan Type * < / label >
< select
value = { newInvestment . planType }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , planType : e.target.value as any , expectedRoi : e.target.value === 'silver' ? 12 : e.target.value === 'gold' ? 15 : e.target.value === 'platinum' ? 18 : 20 } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
< option value = "silver" > Silver ( 12 % ROI ) < / option >
< option value = "gold" > Gold ( 15 % ROI ) < / option >
< option value = "platinum" > Platinum ( 18 % ROI ) < / option >
< option value = "diamond" > Diamond ( 20 % ROI ) < / option >
< / select >
< / div >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Select Bikes < / label >
< div className = "grid grid-cols-2 gap-2 max-h-32 overflow-y-auto border border-slate-200 rounded-lg p-2" >
{ availableBikesForAssignment . map ( bike = > (
< label key = { bike . id } className = "flex items-center gap-2 p-2 hover:bg-slate-50 rounded cursor-pointer" >
< input
type = "checkbox"
checked = { newInvestment . selectedBikeIds . includes ( bike . id ) }
onChange = { ( e ) = > {
if ( e . target . checked ) {
setNewInvestment ( { . . . newInvestment , selectedBikeIds : [ . . . newInvestment . selectedBikeIds , bike . id ] } ) ;
} else {
setNewInvestment ( { . . . newInvestment , selectedBikeIds : newInvestment.selectedBikeIds.filter ( id = > id !== bike . id ) } ) ;
}
} }
className = "rounded text-investor"
/ >
< span className = "text-sm" > { bike . model } ( { bike . plateNumber } ) < / span >
< / label >
) ) }
< / div >
< / div >
< div className = "grid grid-cols-3 gap-4" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Investment Amount ( ৳ ) * < / label >
< input
type = "number"
value = { newInvestment . totalInvestment }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , totalInvestment : Number ( e . target . value ) , monthlyReturn : Math.round ( Number ( e . target . value ) * newInvestment . expectedRoi / 100 / 12 ) } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder = "0"
/ >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Monthly Return ( ৳ ) < / label >
< input
type = "number"
value = { newInvestment . monthlyReturn }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , monthlyReturn : Number ( e . target . value ) } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder = "0"
/ >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Expected ROI ( % ) < / label >
< input
type = "number"
value = { newInvestment . expectedRoi }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , expectedRoi : Number ( e . target . value ) } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder = "15"
/ >
< / div >
< / div >
< div className = "grid grid-cols-2 gap-4" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Start Date * < / label >
< input
type = "date"
value = { newInvestment . startDate }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , startDate : e.target.value } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/ >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > End Date < / label >
< input
type = "date"
value = { newInvestment . endDate }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , endDate : e.target.value } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
/ >
< / div >
< / div >
< div className = "grid grid-cols-2 gap-4" >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Payment Method * < / label >
< select
value = { newInvestment . paymentMethod }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , paymentMethod : e.target.value as any } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
>
< option value = "bank" > Bank Transfer < / option >
< option value = "mobile" > Mobile Banking < / option >
< option value = "cash" > Cash < / option >
< option value = "cheque" > Cheque < / option >
< / select >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Transaction Reference < / label >
< input
type = "text"
value = { newInvestment . transactionReference }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , transactionReference : e.target.value } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder = "Auto-generated if empty"
/ >
< / div >
< / div >
< div >
< label className = "text-sm font-medium text-slate-600 mb-1 block" > Notes < / label >
< textarea
value = { newInvestment . notes }
onChange = { ( e ) = > setNewInvestment ( { . . . newInvestment , notes : e.target.value } ) }
className = "w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
rows = { 2 }
placeholder = "Additional notes..."
/ >
< / div >
< div className = "bg-blue-50 border border-blue-200 rounded-lg p-4" >
< h4 className = "font-semibold text-blue-800 mb-2" > Accounting Entries to be Created : < / h4 >
< div className = "text-sm text-blue-700 space-y-1" >
< p > • Debit : Investment Asset - Investor ( { newInvestment . totalInvestment ? ` ৳ ${ newInvestment . totalInvestment . toLocaleString ( ) } ` : '৳0' } ) < / p >
< p > • Credit : { newInvestment . paymentMethod === 'bank' ? 'Bank Account' : newInvestment . paymentMethod === 'mobile' ? 'Mobile Wallet' : newInvestment . paymentMethod === 'cash' ? 'Cash Account' : 'Cheque Receivable' } ( { newInvestment . totalInvestment ? ` ৳ ${ newInvestment . totalInvestment . toLocaleString ( ) } ` : '৳0' } ) < / p >
< p > • Transaction ID will be auto - generated < / p >
< / div >
< / div >
< / div >
< div className = "p-5 border-t border-slate-100 flex justify-end gap-3" >
< button onClick = { ( ) = > setShowCreateInvestmentModal ( false ) } className = "px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50" > Cancel < / button >
< button
onClick = { handleCreateInvestment }
disabled = { ! newInvestment . planName || ! newInvestment . totalInvestment }
className = "px-4 py-2 bg-investor text-white rounded-lg text-sm hover:bg-investor-dark disabled:opacity-50 flex items-center gap-2"
>
< TrendingUp className = "w-4 h-4" / > Create Investment
< / button >
< / div >
< / div >
< / div >
) }
2026-04-22 01:02:45 +06:00
< / div >
) ;
}