From 5e59909e8e1200d7ef03bb86237dbb289ea1000e Mon Sep 17 00:00:00 2001 From: sazzadulalambd Date: Fri, 15 May 2026 22:37:42 +0600 Subject: [PATCH] feat: add payment modal and due amount functionality to investment details page --- src/app/investor/investments/[id]/page.tsx | 313 ++++++++++++--------- 1 file changed, 182 insertions(+), 131 deletions(-) diff --git a/src/app/investor/investments/[id]/page.tsx b/src/app/investor/investments/[id]/page.tsx index 0f5c7d4..26ab247 100644 --- a/src/app/investor/investments/[id]/page.tsx +++ b/src/app/investor/investments/[id]/page.tsx @@ -5,11 +5,11 @@ import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { ArrowLeft, TrendingUp, Bike, DollarSign, Calendar, - CreditCard, FileText, Download, Check, - Printer, BarChart3, Wallet, Clock, Shield, Percent, Activity, AlertTriangle, - Receipt, Zap, Smartphone, ChevronRight, Target, Battery, MapPin, Gauge, User + CreditCard, FileText, Download, Check, X, + Printer, BarChart3, Wallet, Clock, Shield, + Receipt, Zap, Smartphone, ChevronRight, Target, Battery, MapPin, Gauge, Building2 } from 'lucide-react'; -import { investors, bikes, transactions, rentalPayments } from '@/data/mockData'; +import { investors } from '@/data/mockData'; import toast from 'react-hot-toast'; import InvestorNotification from '@/components/InvestorNotification'; @@ -22,6 +22,8 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi const investment = investor.investments?.find((inv: any) => inv.id === investmentId); const [activeTab, setActiveTab] = useState('overview'); + const [showPaymentModal, setShowPaymentModal] = useState(false); + const [selectedInstallment, setSelectedInstallment] = useState<'full' | '2' | '3'>('3'); if (!investment) { return ( @@ -40,48 +42,22 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi ); } - const planConfig: Record = { - silver: { bg: 'bg-slate-50', border: 'border-slate-200', text: 'text-slate-700', badge: 'bg-slate-200 text-slate-700', icon: Zap }, - gold: { bg: 'bg-amber-50', border: 'border-amber-200', text: 'text-amber-700', badge: 'bg-amber-100 text-amber-700', icon: Shield }, - platinum: { bg: 'bg-purple-50', border: 'border-purple-200', text: 'text-purple-700', badge: 'bg-purple-100 text-purple-700', icon: TrendingUp }, - diamond: { bg: 'bg-blue-50', border: 'border-blue-200', text: 'text-blue-700', badge: 'bg-blue-100 text-blue-700', icon: Zap }, + const planConfig: Record = { + silver: { badge: 'bg-slate-200 text-slate-700' }, + gold: { badge: 'bg-amber-100 text-amber-700' }, + platinum: { badge: 'bg-purple-100 text-purple-700' }, + diamond: { badge: 'bg-blue-100 text-blue-700' }, }; const style = planConfig[investment.planType] || planConfig.gold; const demoBikes = [ - { - id: 'b1', model: 'Yadea DT3', brand: 'Yadea', plateNumber: 'AB-1234', - image: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop', - status: 'rented', currentRent: 450, totalEarnings: 45000, - batteryLevel: 85, range: 60, location: 'Dhaka Central Hub' - }, - { - id: 'b2', model: 'Apex E-Bike Pro', brand: 'Apex', plateNumber: 'CD-5678', - image: 'https://images.unsplash.com/photo-1622185135505-2d795043906a?w=400&h=300&fit=crop', - status: 'rented', currentRent: 500, totalEarnings: 52000, - batteryLevel: 72, range: 55, location: 'Gulshan Area' - }, - { - id: 'b3', model: 'Niu NQi Sport', brand: 'Niu', plateNumber: 'EF-9012', - image: 'https://images.unsplash.com/photo-1591353230407-2b14a8e4c8d3?w=400&h=300&fit=crop', - status: 'available', currentRent: 0, totalEarnings: 28000, - batteryLevel: 95, range: 70, location: 'Mirpur Depot' - }, - { - id: 'b4', model: 'Yadea DT3', brand: 'Yadea', plateNumber: 'GH-3456', - image: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop', - status: 'maintenance', currentRent: 0, totalEarnings: 15000, - batteryLevel: 0, range: 0, location: 'Service Center' - }, + { id: 'b1', model: 'Yadea DT3', brand: 'Yadea', plateNumber: 'AB-1234', image: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop', status: 'rented', currentRent: 450, totalEarnings: 45000, batteryLevel: 85, range: 60, location: 'Dhaka Central Hub' }, + { id: 'b2', model: 'Apex E-Bike Pro', brand: 'Apex', plateNumber: 'CD-5678', image: 'https://images.unsplash.com/photo-1622185135505-2d795043906a?w=400&h=300&fit=crop', status: 'rented', currentRent: 500, totalEarnings: 52000, batteryLevel: 72, range: 55, location: 'Gulshan Area' }, + { id: 'b3', model: 'Niu NQi Sport', brand: 'Niu', plateNumber: 'EF-9012', image: 'https://images.unsplash.com/photo-1591353230407-2b14a8e4c8d3?w=400&h=300&fit=crop', status: 'available', currentRent: 0, totalEarnings: 28000, batteryLevel: 95, range: 70, location: 'Mirpur Depot' }, + { id: 'b4', model: 'Yadea DT3', brand: 'Yadea', plateNumber: 'GH-3456', image: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop', status: 'maintenance', currentRent: 0, totalEarnings: 15000, batteryLevel: 0, range: 0, location: 'Service Center' }, ]; - const demoPnl = { - grossRevenue: 185000, - platformFee: 83250, - insurance: 15000, - maintenance: 8500, - netProfit: 78250, - }; + const demoPnl = { grossRevenue: 185000, platformFee: 83250, insurance: 15000, maintenance: 8500, netProfit: 78250 }; const demoTransactions = [ { id: 'tx1', date: '2024-05-15', description: 'Rental Income - Bike AB-1234', amount: 450, status: 'completed' }, @@ -94,10 +70,18 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi { id: 'tx8', date: '2024-05-08', description: 'Rental Income - Bike CD-5678', amount: 500, status: 'completed' }, ]; + const dueAmount = investment.totalInvestment * 0.33; + const paidAmount = investment.totalInvestment * 0.67; + + const handlePaymentSubmit = () => { + toast.success(`Payment of ৳${(dueAmount / (selectedInstallment === '2' ? 2 : 3)).toLocaleString()} initiated successfully!`); + setShowPaymentModal(false); + }; + return (
-
+
@@ -109,17 +93,13 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi

{investment.planName}

- - {investment.planType} - - - {investment.status} - + {investment.planType} + {investment.status}

ID: #{investment.id?.toUpperCase()} • Started: {investment.startDate}

-
@@ -131,9 +111,9 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
-

Invested

+

Total Investment

-

৳{(investment.totalInvestment / 1000).toFixed(0)}k

+

৳{investment.totalInvestment.toLocaleString()}

@@ -144,52 +124,48 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi

৳{(investment.actualEarnings / 1000).toFixed(0)}k

-
+
-
+
-

Pending

+

Due Amount

-

৳{(investment.totalInvestment * 0.24 - investment.actualEarnings).toLocaleString()}

+

৳{dueAmount.toLocaleString()}

+
-

Total Bikes

+

Bikes

{demoBikes.length}

-
{[ - { key: 'overview', label: 'Overview', count: null }, - { key: 'bikes', label: 'Bikes', count: demoBikes.length }, + { key: 'overview', label: 'Overview', icon: FileText, count: null }, + { key: 'bikes', label: 'Bikes', icon: Bike, count: demoBikes.length }, + { key: 'transactions', label: 'Transactions', icon: CreditCard, count: demoTransactions.length }, + { key: 'statement', label: 'Statement', icon: Receipt, count: null }, - { key: 'transactions', label: 'Transactions', count: demoTransactions.length }, - { key: 'statement', label: 'Statement', count: null }, - ].map((tab) => ( - - ))} + ].map((tab) => { + const Icon = tab.icon; + return ( + + ); + })}
@@ -259,7 +235,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi

Rent to Own

45%

-
+

Share EV

40%

@@ -270,9 +246,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi {activeTab === 'bikes' && (
-
-

{demoBikes.length} bikes assigned to this investment

-
+

{demoBikes.length} bikes assigned to this investment

{demoBikes.map((bike) => (
@@ -281,12 +255,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
{bike.model}
- - {bike.status} - + {bike.status}

{bike.plateNumber} • {bike.brand}

@@ -315,21 +284,12 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi ৳{demoPnl.grossRevenue.toLocaleString()}
-
- Platform Fee (45%) - -৳{demoPnl.platformFee.toLocaleString()} -
-
- Insurance Coverage - -৳{demoPnl.insurance.toLocaleString()} -
-
- Maintenance - -৳{demoPnl.maintenance.toLocaleString()} -
+
Platform Fee (45%)-৳{demoPnl.platformFee.toLocaleString()}
+
Insurance Coverage-৳{demoPnl.insurance.toLocaleString()}
+
Maintenance-৳{demoPnl.maintenance.toLocaleString()}
- Net Return + Your Share (55%) ৳{demoPnl.netProfit.toLocaleString()}
@@ -338,41 +298,132 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi )} {activeTab === 'transactions' && ( -
- - - - - - - - - - - {demoTransactions.map((tx) => ( - - - - - - - ))} - -
DateDescriptionAmountStatus
{tx.date} -

{tx.description}

-

Ref: {tx.id}

-
0 ? 'text-green-600' : 'text-red-500'}`}> - {tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()} - - - {tx.status} - -
+
+
+

{demoTransactions.length} transactions found

+
+ + +
+
+ +
+ + + + + + {demoTransactions.map((tx) => ( + + + + + + + ))} + +
DateDescriptionAmountStatus
{tx.date}

{tx.description}

Ref: {tx.id}

0 ? 'text-green-600' : 'text-red-500'}`}>{tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()}{tx.status}
+
+ +
+ {demoTransactions.map((tx) => ( +
+
+

{tx.description}

Ref: {tx.id} • {tx.date}

+ {tx.status} +
+

0 ? 'text-green-600' : 'text-red-500'}`}>{tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()}

+
+ ))} +
+ +
+

Showing 1-8 of 8

+
+ + +
+
)}
+ + {showPaymentModal && ( +
+
+
+

Pay Due Amount

+ +
+
+
+

Total Due

+

৳{dueAmount.toLocaleString()}

+
+ +
+

Installment List

+
+
+
+ +
+

Installment 1

+

Paid on Jan 15, 2024

+
+
+ ৳{(investment.totalInvestment * 0.4).toLocaleString()} +
+
+
+ +
+

Installment 2

+

Due: Jun 15, 2024

+
+
+ ৳{(investment.totalInvestment * 0.3).toLocaleString()} +
+
+
+ +
+

Installment 3

+

Due: Jul 15, 2024

+
+
+ ৳{(investment.totalInvestment * 0.3).toLocaleString()} +
+
+
+ +
+

Select Payment

+
+ + +
+
+ + +
+
+
+ )}
); -} \ No newline at end of file +} + +import { Percent } from 'lucide-react'; \ No newline at end of file