feat: add payment modal and due amount functionality to investment details page
This commit is contained in:
@@ -5,11 +5,11 @@ import Link from 'next/link';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import {
|
import {
|
||||||
ArrowLeft, TrendingUp, Bike, DollarSign, Calendar,
|
ArrowLeft, TrendingUp, Bike, DollarSign, Calendar,
|
||||||
CreditCard, FileText, Download, Check,
|
CreditCard, FileText, Download, Check, X,
|
||||||
Printer, BarChart3, Wallet, Clock, Shield, Percent, Activity, AlertTriangle,
|
Printer, BarChart3, Wallet, Clock, Shield,
|
||||||
Receipt, Zap, Smartphone, ChevronRight, Target, Battery, MapPin, Gauge, User
|
Receipt, Zap, Smartphone, ChevronRight, Target, Battery, MapPin, Gauge, Building2
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { investors, bikes, transactions, rentalPayments } from '@/data/mockData';
|
import { investors } from '@/data/mockData';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import InvestorNotification from '@/components/InvestorNotification';
|
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 investment = investor.investments?.find((inv: any) => inv.id === investmentId);
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState('overview');
|
const [activeTab, setActiveTab] = useState('overview');
|
||||||
|
const [showPaymentModal, setShowPaymentModal] = useState(false);
|
||||||
|
const [selectedInstallment, setSelectedInstallment] = useState<'full' | '2' | '3'>('3');
|
||||||
|
|
||||||
if (!investment) {
|
if (!investment) {
|
||||||
return (
|
return (
|
||||||
@@ -40,48 +42,22 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const planConfig: Record<string, { bg: string; border: string; text: string; badge: string; icon: any }> = {
|
const planConfig: Record<string, { badge: string }> = {
|
||||||
silver: { bg: 'bg-slate-50', border: 'border-slate-200', text: 'text-slate-700', badge: 'bg-slate-200 text-slate-700', icon: Zap },
|
silver: { badge: 'bg-slate-200 text-slate-700' },
|
||||||
gold: { bg: 'bg-amber-50', border: 'border-amber-200', text: 'text-amber-700', badge: 'bg-amber-100 text-amber-700', icon: Shield },
|
gold: { badge: 'bg-amber-100 text-amber-700' },
|
||||||
platinum: { bg: 'bg-purple-50', border: 'border-purple-200', text: 'text-purple-700', badge: 'bg-purple-100 text-purple-700', icon: TrendingUp },
|
platinum: { badge: 'bg-purple-100 text-purple-700' },
|
||||||
diamond: { bg: 'bg-blue-50', border: 'border-blue-200', text: 'text-blue-700', badge: 'bg-blue-100 text-blue-700', icon: Zap },
|
diamond: { badge: 'bg-blue-100 text-blue-700' },
|
||||||
};
|
};
|
||||||
const style = planConfig[investment.planType] || planConfig.gold;
|
const style = planConfig[investment.planType] || planConfig.gold;
|
||||||
|
|
||||||
const demoBikes = [
|
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: 'b1', model: 'Yadea DT3', brand: 'Yadea', plateNumber: 'AB-1234',
|
{ 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' },
|
||||||
image: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
|
{ 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' },
|
||||||
status: 'rented', currentRent: 450, totalEarnings: 45000,
|
{ 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' },
|
||||||
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 = {
|
const demoPnl = { grossRevenue: 185000, platformFee: 83250, insurance: 15000, maintenance: 8500, netProfit: 78250 };
|
||||||
grossRevenue: 185000,
|
|
||||||
platformFee: 83250,
|
|
||||||
insurance: 15000,
|
|
||||||
maintenance: 8500,
|
|
||||||
netProfit: 78250,
|
|
||||||
};
|
|
||||||
|
|
||||||
const demoTransactions = [
|
const demoTransactions = [
|
||||||
{ id: 'tx1', date: '2024-05-15', description: 'Rental Income - Bike AB-1234', amount: 450, status: 'completed' },
|
{ 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' },
|
{ 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 (
|
return (
|
||||||
<div className="min-h-screen lg:pt-6 pt-0 ">
|
<div className="min-h-screen lg:pt-6 pt-0 ">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto mb-12 lg:mb-0">
|
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto mb-20 lg:mb-0">
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -109,17 +93,13 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
<h1 className="text-xl lg:text-2xl font-bold text-slate-800 flex items-center gap-2">
|
<h1 className="text-xl lg:text-2xl font-bold text-slate-800 flex items-center gap-2">
|
||||||
<Target className="w-5 h-5 lg:w-6 lg:h-6 text-investor" />{investment.planName}
|
<Target className="w-5 h-5 lg:w-6 lg:h-6 text-investor" />{investment.planName}
|
||||||
</h1>
|
</h1>
|
||||||
<span className={`px-2.5 py-1 rounded-full text-xs font-bold ${style.badge} capitalize`}>
|
<span className={`px-2.5 py-1 rounded-full text-xs font-bold ${style.badge} capitalize`}>{investment.planType}</span>
|
||||||
{investment.planType}
|
<span className={`px-2.5 py-1 rounded-full text-xs font-bold ${investment.status === 'active' ? 'bg-green-100 text-green-700' : 'bg-slate-100 text-slate-600'} capitalize`}>{investment.status}</span>
|
||||||
</span>
|
|
||||||
<span className={`px-2.5 py-1 rounded-full text-xs font-bold ${investment.status === 'active' ? 'bg-green-100 text-green-700' : 'bg-slate-100 text-slate-600'} capitalize`}>
|
|
||||||
{investment.status}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-500 mt-1">ID: #{investment.id?.toUpperCase()} • Started: {investment.startDate}</p>
|
<p className="text-sm text-slate-500 mt-1">ID: #{investment.id?.toUpperCase()} • Started: {investment.startDate}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button onClick={() => toast.success('Statement download started')} className="px-4 py-2.5 bg-white border border-slate-200 text-slate-700 rounded-lg text-sm font-medium hover:bg-slate-50 flex items-center gap-2 shadow-sm">
|
<button onClick={() => toast.success('Download started')} className="px-4 py-2.5 bg-white border border-slate-200 text-slate-700 rounded-lg text-sm font-medium hover:bg-slate-50 flex items-center gap-2 shadow-sm">
|
||||||
<Download className="w-4 h-4" /> Download
|
<Download className="w-4 h-4" /> Download
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -131,9 +111,9 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
<div className="w-8 h-8 bg-purple-100 rounded-lg flex items-center justify-center">
|
<div className="w-8 h-8 bg-purple-100 rounded-lg flex items-center justify-center">
|
||||||
<Wallet className="w-4 h-4 text-purple-600" />
|
<Wallet className="w-4 h-4 text-purple-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-slate-500 font-medium">Invested</p>
|
<p className="text-xs text-slate-500 font-medium">Total Investment</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xl lg:text-2xl font-bold text-slate-800">৳{(investment.totalInvestment / 1000).toFixed(0)}k</p>
|
<p className="text-xl lg:text-2xl font-bold text-slate-800">৳{investment.totalInvestment.toLocaleString()}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl p-4 lg:p-5 border border-slate-200 shadow-sm">
|
<div className="bg-white rounded-xl p-4 lg:p-5 border border-slate-200 shadow-sm">
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
@@ -144,52 +124,48 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
</div>
|
</div>
|
||||||
<p className="text-xl lg:text-2xl font-bold text-green-600">৳{(investment.actualEarnings / 1000).toFixed(0)}k</p>
|
<p className="text-xl lg:text-2xl font-bold text-green-600">৳{(investment.actualEarnings / 1000).toFixed(0)}k</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl p-4 lg:p-5 border border-slate-200 shadow-sm">
|
<div className="bg-white rounded-xl p-4 lg:p-5 border border-amber-200 shadow-sm bg-amber-50/50">
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<div className="w-8 h-8 bg-amber-100 rounded-lg flex items-center justify-center">
|
<div className="w-8 h-8 bg-amber-200 rounded-lg flex items-center justify-center">
|
||||||
<Clock className="w-4 h-4 text-amber-600" />
|
<Clock className="w-4 h-4 text-amber-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-slate-500 font-medium">Pending</p>
|
<p className="text-xs text-amber-700 font-medium">Due Amount</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xl lg:text-2xl font-bold text-amber-600">৳{(investment.totalInvestment * 0.24 - investment.actualEarnings).toLocaleString()}</p>
|
<p className="text-xl lg:text-2xl font-bold text-amber-600">৳{dueAmount.toLocaleString()}</p>
|
||||||
|
<button onClick={() => setShowPaymentModal(true)} className="mt-2 w-full py-1.5 bg-amber-500 text-white text-xs font-bold rounded-lg hover:bg-amber-600 transition-colors">
|
||||||
|
Pay Now
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl p-4 lg:p-5 border border-slate-200 shadow-sm">
|
<div className="bg-white rounded-xl p-4 lg:p-5 border border-slate-200 shadow-sm">
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<div className="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center">
|
<div className="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center">
|
||||||
<Bike className="w-4 h-4 text-blue-600" />
|
<Bike className="w-4 h-4 text-blue-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-slate-500 font-medium">Total Bikes</p>
|
<p className="text-xs text-slate-500 font-medium">Bikes</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xl lg:text-2xl font-bold text-blue-600">{demoBikes.length}</p>
|
<p className="text-xl lg:text-2xl font-bold text-blue-600">{demoBikes.length}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
||||||
<div className="flex overflow-x-auto border-b border-slate-100">
|
<div className="flex overflow-x-auto border-b border-slate-100">
|
||||||
{[
|
{[
|
||||||
{ key: 'overview', label: 'Overview', count: null },
|
{ key: 'overview', label: 'Overview', icon: FileText, count: null },
|
||||||
{ key: 'bikes', label: 'Bikes', count: demoBikes.length },
|
{ 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 },
|
].map((tab) => {
|
||||||
{ key: 'statement', label: 'Statement', count: null },
|
const Icon = tab.icon;
|
||||||
].map((tab) => (
|
return (
|
||||||
<button
|
<button key={tab.key} onClick={() => setActiveTab(tab.key)}
|
||||||
key={tab.key}
|
className={`px-3 lg:px-6 py-3 text-sm font-semibold capitalize whitespace-nowrap transition-colors flex items-center gap-2 ${activeTab === tab.key ? 'text-investor bg-investor/5 border-b-2 border-investor' : 'text-slate-500 hover:text-slate-700 hover:bg-slate-50'}`}>
|
||||||
onClick={() => setActiveTab(tab.key)}
|
<Icon className="w-4 h-4" />
|
||||||
className={`px-4 lg:px-6 py-3 text-sm font-semibold capitalize whitespace-nowrap transition-colors flex items-center gap-2 ${activeTab === tab.key
|
<span className="hidden lg:inline">{tab.label}</span>
|
||||||
? 'text-investor bg-investor/5 border-b-2 border-investor'
|
{tab.count !== null && <span className={`px-1.5 py-0.5 rounded text-[10px] font-bold ${activeTab === tab.key ? 'bg-investor text-white' : 'bg-slate-200 text-slate-600'}`}>{tab.count}</span>}
|
||||||
: 'text-slate-500 hover:text-slate-700 hover:bg-slate-50'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{tab.label}
|
|
||||||
{tab.count !== null && (
|
|
||||||
<span className={`px-1.5 py-0.5 rounded text-[10px] font-bold ${activeTab === tab.key ? 'bg-investor text-white' : 'bg-slate-200 text-slate-600'}`}>
|
|
||||||
{tab.count}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 lg:p-6">
|
<div className="p-4 lg:p-6">
|
||||||
@@ -259,7 +235,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
<p className="text-xs text-slate-500 mb-1 font-medium">Rent to Own</p>
|
<p className="text-xs text-slate-500 mb-1 font-medium">Rent to Own</p>
|
||||||
<p className="text-xl font-bold text-slate-800">45%</p>
|
<p className="text-xl font-bold text-slate-800">45%</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-lg p-3 text-center border-2 border-amber-400 ring-2 ring-amber-100">
|
<div className="bg-white rounded-lg p-3 text-center border border-amber-200">
|
||||||
<p className="text-xs text-slate-500 mb-1 font-medium">Share EV</p>
|
<p className="text-xs text-slate-500 mb-1 font-medium">Share EV</p>
|
||||||
<p className="text-xl font-bold text-slate-800">40%</p>
|
<p className="text-xl font-bold text-slate-800">40%</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -270,9 +246,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
|
|
||||||
{activeTab === 'bikes' && (
|
{activeTab === 'bikes' && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<p className="text-sm text-slate-500">{demoBikes.length} bikes assigned to this investment</p>
|
<p className="text-sm text-slate-500">{demoBikes.length} bikes assigned to this investment</p>
|
||||||
</div>
|
|
||||||
{demoBikes.map((bike) => (
|
{demoBikes.map((bike) => (
|
||||||
<div key={bike.id} className="p-4 bg-white rounded-xl border border-slate-200 flex flex-col md:flex-row items-start gap-4 hover:border-investor/30 transition-colors">
|
<div key={bike.id} className="p-4 bg-white rounded-xl border border-slate-200 flex flex-col md:flex-row items-start gap-4 hover:border-investor/30 transition-colors">
|
||||||
<div className="w-24 h-20 bg-slate-100 rounded-lg overflow-hidden shrink-0">
|
<div className="w-24 h-20 bg-slate-100 rounded-lg overflow-hidden shrink-0">
|
||||||
@@ -281,12 +255,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<h5 className="font-semibold text-slate-800">{bike.model}</h5>
|
<h5 className="font-semibold text-slate-800">{bike.model}</h5>
|
||||||
<span className={`px-2 py-0.5 rounded text-[10px] font-bold uppercase ${bike.status === 'rented' ? 'bg-green-100 text-green-700' :
|
<span className={`px-2 py-0.5 rounded text-[10px] font-bold uppercase ${bike.status === 'rented' ? 'bg-green-100 text-green-700' : bike.status === 'available' ? 'bg-blue-100 text-blue-700' : 'bg-red-100 text-red-700'}`}>{bike.status}</span>
|
||||||
bike.status === 'available' ? 'bg-blue-100 text-blue-700' :
|
|
||||||
'bg-red-100 text-red-700'
|
|
||||||
}`}>
|
|
||||||
{bike.status}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-500">{bike.plateNumber} • {bike.brand}</p>
|
<p className="text-sm text-slate-500">{bike.plateNumber} • {bike.brand}</p>
|
||||||
<div className="mt-2 flex flex-wrap gap-3 text-xs text-slate-500">
|
<div className="mt-2 flex flex-wrap gap-3 text-xs text-slate-500">
|
||||||
@@ -315,21 +284,12 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
<span className="text-xl font-bold text-slate-800">৳{demoPnl.grossRevenue.toLocaleString()}</span>
|
<span className="text-xl font-bold text-slate-800">৳{demoPnl.grossRevenue.toLocaleString()}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2 py-2">
|
<div className="space-y-2 py-2">
|
||||||
<div className="flex justify-between text-sm">
|
<div className="flex justify-between text-sm"><span className="text-slate-500">Platform Fee (45%)</span><span className="font-medium text-red-500">-৳{demoPnl.platformFee.toLocaleString()}</span></div>
|
||||||
<span className="text-slate-500">Platform Fee (45%)</span>
|
<div className="flex justify-between text-sm"><span className="text-slate-500">Insurance Coverage</span><span className="font-medium text-slate-600">-৳{demoPnl.insurance.toLocaleString()}</span></div>
|
||||||
<span className="font-medium text-red-500">-৳{demoPnl.platformFee.toLocaleString()}</span>
|
<div className="flex justify-between text-sm"><span className="text-slate-500">Maintenance</span><span className="font-medium text-slate-600">-৳{demoPnl.maintenance.toLocaleString()}</span></div>
|
||||||
</div>
|
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-slate-500">Insurance Coverage</span>
|
|
||||||
<span className="font-medium text-slate-600">-৳{demoPnl.insurance.toLocaleString()}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-slate-500">Maintenance</span>
|
|
||||||
<span className="font-medium text-slate-600">-৳{demoPnl.maintenance.toLocaleString()}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center pt-4 border-t-2 border-slate-300">
|
<div className="flex justify-between items-center pt-4 border-t-2 border-slate-300">
|
||||||
<span className="text-lg font-semibold text-slate-800">Net Return</span>
|
<span className="text-lg font-semibold text-slate-800">Your Share (55%)</span>
|
||||||
<span className="text-2xl font-bold text-green-600">৳{demoPnl.netProfit.toLocaleString()}</span>
|
<span className="text-2xl font-bold text-green-600">৳{demoPnl.netProfit.toLocaleString()}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -338,41 +298,132 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'transactions' && (
|
{activeTab === 'transactions' && (
|
||||||
<div className="overflow-x-auto">
|
<div className="space-y-4">
|
||||||
<table className="w-full text-left">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
|
||||||
|
<p className="text-sm text-slate-500">{demoTransactions.length} transactions found</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<select className="px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white"><option>All Types</option><option>Income</option><option>Withdrawal</option></select>
|
||||||
|
<select className="px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white"><option>Last 30 Days</option><option>Last 7 Days</option><option>This Month</option><option>All Time</option></select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="lg:overflow-x-auto">
|
||||||
|
<table className="hidden lg:table w-full text-left">
|
||||||
<thead className="bg-slate-50">
|
<thead className="bg-slate-50">
|
||||||
<tr>
|
<tr><th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Date</th><th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Description</th><th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase text-right">Amount</th><th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Status</th></tr>
|
||||||
<th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Date</th>
|
|
||||||
<th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Description</th>
|
|
||||||
<th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase text-right">Amount</th>
|
|
||||||
<th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-slate-100">
|
<tbody className="divide-y divide-slate-100">
|
||||||
{demoTransactions.map((tx) => (
|
{demoTransactions.map((tx) => (
|
||||||
<tr key={tx.id} className="hover:bg-slate-50 transition-colors">
|
<tr key={tx.id} className="hover:bg-slate-50 transition-colors">
|
||||||
<td className="px-4 py-3 text-sm text-slate-600 whitespace-nowrap">{tx.date}</td>
|
<td className="px-4 py-3 text-sm text-slate-600 whitespace-nowrap">{tx.date}</td>
|
||||||
<td className="px-4 py-3">
|
<td className="px-4 py-3"><p className="text-sm font-medium text-slate-800">{tx.description}</p><p className="text-xs text-slate-400">Ref: {tx.id}</p></td>
|
||||||
<p className="text-sm font-medium text-slate-800">{tx.description}</p>
|
<td className={`px-4 py-3 text-sm font-bold text-right ${tx.amount > 0 ? 'text-green-600' : 'text-red-500'}`}>{tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()}</td>
|
||||||
<p className="text-xs text-slate-400">Ref: {tx.id}</p>
|
<td className="px-4 py-3"><span className="inline-flex px-2 py-0.5 rounded text-[10px] font-bold uppercase bg-green-100 text-green-700">{tx.status}</span></td>
|
||||||
</td>
|
|
||||||
<td className={`px-4 py-3 text-sm font-bold text-right ${tx.amount > 0 ? 'text-green-600' : 'text-red-500'}`}>
|
|
||||||
{tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-3">
|
|
||||||
<span className="inline-flex px-2 py-0.5 rounded text-[10px] font-bold uppercase bg-green-100 text-green-700">
|
|
||||||
{tx.status}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="lg:hidden space-y-3">
|
||||||
|
{demoTransactions.map((tx) => (
|
||||||
|
<div key={tx.id} className="p-4 bg-white rounded-xl border border-slate-200">
|
||||||
|
<div className="flex items-start justify-between mb-2">
|
||||||
|
<div><p className="text-sm font-medium text-slate-800">{tx.description}</p><p className="text-xs text-slate-400">Ref: {tx.id} • {tx.date}</p></div>
|
||||||
|
<span className={`px-2 py-0.5 rounded text-[10px] font-bold uppercase ${tx.status === 'completed' ? 'bg-green-100 text-green-700' : 'bg-amber-100 text-amber-700'}`}>{tx.status}</span>
|
||||||
|
</div>
|
||||||
|
<p className={`text-lg font-bold text-right ${tx.amount > 0 ? 'text-green-600' : 'text-red-500'}`}>{tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between pt-4 border-t border-slate-100">
|
||||||
|
<p className="text-sm text-slate-500">Showing 1-8 of 8</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm text-slate-600 hover:bg-slate-50 disabled:opacity-50" disabled>Previous</button>
|
||||||
|
<button className="px-3 py-1.5 border border-slate-200 rounded-lg text-sm text-slate-600 hover:bg-slate-50 disabled:opacity-50" disabled>Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showPaymentModal && (
|
||||||
|
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
||||||
|
<div className="bg-white rounded-2xl w-full max-w-md shadow-2xl">
|
||||||
|
<div className="flex items-center justify-between p-5 border-b border-slate-100">
|
||||||
|
<h3 className="text-lg font-bold text-slate-800">Pay Due Amount</h3>
|
||||||
|
<button onClick={() => setShowPaymentModal(false)} className="p-1 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 className="bg-amber-50 border border-amber-200 rounded-xl p-4 text-center">
|
||||||
|
<p className="text-sm text-amber-700 mb-1">Total Due</p>
|
||||||
|
<p className="text-3xl font-bold text-amber-600">৳{dueAmount.toLocaleString()}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-semibold text-slate-700 mb-3">Installment List</p>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="p-3 bg-green-50 border border-green-200 rounded-lg flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-semibold text-slate-800">Installment 1</p>
|
||||||
|
<p className="text-xs text-slate-500">Paid on Jan 15, 2024</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm font-bold text-green-600">৳{(investment.totalInvestment * 0.4).toLocaleString()}</span>
|
||||||
|
</div>
|
||||||
|
<div className="p-3 bg-amber-50 border border-amber-300 rounded-lg flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Clock className="w-4 h-4 text-amber-600" />
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-semibold text-slate-800">Installment 2</p>
|
||||||
|
<p className="text-xs text-amber-600">Due: Jun 15, 2024</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm font-bold text-amber-600">৳{(investment.totalInvestment * 0.3).toLocaleString()}</span>
|
||||||
|
</div>
|
||||||
|
<div className="p-3 bg-amber-50 border border-amber-300 rounded-lg flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Clock className="w-4 h-4 text-amber-600" />
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-semibold text-slate-800">Installment 3</p>
|
||||||
|
<p className="text-xs text-amber-600">Due: Jul 15, 2024</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm font-bold text-amber-600">৳{(investment.totalInvestment * 0.3).toLocaleString()}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pt-2">
|
||||||
|
<p className="text-sm font-semibold text-slate-700 mb-2">Select Payment</p>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<button className="flex-1 p-3 border border-slate-200 rounded-lg text-center hover:border-investor hover:bg-investor/5 transition-colors">
|
||||||
|
<Building2 className="w-5 h-5 mx-auto text-slate-600 mb-1" />
|
||||||
|
<span className="text-xs font-medium text-slate-700">Bank</span>
|
||||||
|
</button>
|
||||||
|
<button className="flex-1 p-3 border border-slate-200 rounded-lg text-center hover:border-investor hover:bg-investor/5 transition-colors">
|
||||||
|
<Smartphone className="w-5 h-5 mx-auto text-slate-600 mb-1" />
|
||||||
|
<span className="text-xs font-medium text-slate-700">bKash</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onClick={handlePaymentSubmit} className="w-full py-3 bg-investor text-white rounded-xl font-bold hover:bg-investor-dark transition-colors">
|
||||||
|
Pay Now ৳{(investment.totalInvestment * 0.3).toLocaleString()}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { Percent } from 'lucide-react';
|
||||||
Reference in New Issue
Block a user