feat: update investment details page with mock data, navigation enhancements, and refined layout
This commit is contained in:
@@ -7,9 +7,9 @@ import {
|
|||||||
ArrowLeft, TrendingUp, Bike, DollarSign, Calendar,
|
ArrowLeft, TrendingUp, Bike, DollarSign, Calendar,
|
||||||
CreditCard, FileText, Download, Check,
|
CreditCard, FileText, Download, Check,
|
||||||
Printer, BarChart3, Wallet, Clock, Shield, Percent, Activity, AlertTriangle,
|
Printer, BarChart3, Wallet, Clock, Shield, Percent, Activity, AlertTriangle,
|
||||||
Receipt, CreditCardIcon, Zap, Smartphone, ChevronRight, Target
|
Receipt, Zap, Smartphone, ChevronRight, Target, Battery, MapPin, Gauge, User
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { investors, bikes, transactions } from '@/data/mockData';
|
import { investors, bikes, transactions, rentalPayments } 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';
|
||||||
|
|
||||||
@@ -18,22 +18,25 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
const { id: investmentId } = resolvedParams;
|
const { id: investmentId } = resolvedParams;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const investor = investors[0]; // mock logged-in investor
|
const investor = investors[0];
|
||||||
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');
|
||||||
|
|
||||||
if (!investment) {
|
if (!investment) {
|
||||||
return (
|
return (
|
||||||
<div className="p-4 lg:p-6">
|
<div className="min-h-screen pb-20 lg:pb-0">
|
||||||
|
<InvestorNotification isMobile />
|
||||||
|
<div className="pt-18 lg:pt-0 p-4 lg:p-6">
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
<h2 className="text-xl font-bold text-slate-800">Investment Not Found</h2>
|
<h2 className="text-xl font-bold text-slate-800">Investment Not Found</h2>
|
||||||
<p className="text-slate-500 mt-2">The investment you're looking for doesn't exist.</p>
|
<p className="text-sm text-slate-500 mt-2">The investment you're looking for doesn't exist.</p>
|
||||||
<Link href="/investor/portfolio" className="mt-4 inline-flex items-center gap-2 text-investor hover:underline">
|
<Link href="/investor/plans" className="mt-4 inline-flex items-center gap-2 text-investor hover:underline">
|
||||||
<ArrowLeft className="w-4 h-4" /> Back to Portfolio
|
<ArrowLeft className="w-4 h-4" /> Back to Investments
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,167 +48,208 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
};
|
};
|
||||||
const style = planConfig[investment.planType] || planConfig.gold;
|
const style = planConfig[investment.planType] || planConfig.gold;
|
||||||
|
|
||||||
const assignedBikes = bikes.filter((b: any) => b.investorId === investor.id && b.id === 'b1'); // mock filtering for this investment
|
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'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const investmentTransactions = transactions.filter((t: any) => t.investorId === investor.id && t.type === 'investment_return');
|
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' },
|
||||||
|
{ id: 'tx2', date: '2024-05-14', description: 'Rental Income - Bike CD-5678', amount: 500, status: 'completed' },
|
||||||
|
{ id: 'tx3', date: '2024-05-13', description: 'Rental Income - Bike AB-1234', amount: 450, status: 'completed' },
|
||||||
|
{ id: 'tx4', date: '2024-05-12', description: 'Rental Income - Bike EF-9012', amount: 350, status: 'completed' },
|
||||||
|
{ id: 'tx5', date: '2024-05-11', description: 'Rental Income - Bike CD-5678', amount: 500, status: 'completed' },
|
||||||
|
{ id: 'tx6', date: '2024-05-10', description: 'Withdrawal to Bank', amount: -10000, status: 'completed' },
|
||||||
|
{ id: 'tx7', date: '2024-05-09', description: 'Rental Income - Bike AB-1234', amount: 450, status: 'completed' },
|
||||||
|
{ id: 'tx8', date: '2024-05-08', description: 'Rental Income - Bike CD-5678', amount: 500, status: 'completed' },
|
||||||
|
];
|
||||||
|
|
||||||
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="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
|
<div className="mb-6">
|
||||||
<div className="flex items-center 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">
|
||||||
<button onClick={() => router.back()} className="p-2 hover:bg-slate-100 rounded-lg transition-colors border border-slate-200">
|
<button onClick={() => router.back()} className="p-2 hover:bg-slate-100 rounded-lg transition-colors border border-slate-200">
|
||||||
<ArrowLeft className="w-5 h-5 text-slate-600" />
|
<ArrowLeft className="w-5 h-5 text-slate-600" />
|
||||||
</button>
|
</button>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-2">
|
||||||
<h1 className="text-xl lg:text-2xl font-extrabold 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}</h1>
|
<Target className="w-5 h-5 lg:w-6 lg:h-6 text-investor" />{investment.planName}
|
||||||
|
</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} Plan
|
{investment.planType}
|
||||||
</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`}>
|
<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}
|
{investment.status}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-slate-500 text-sm mt-1 flex items-center gap-2">
|
<p className="text-sm text-slate-500 mt-1">ID: #{investment.id?.toUpperCase()} • Started: {investment.startDate}</p>
|
||||||
ID: <span className="font-mono text-xs bg-slate-100 px-1.5 py-0.5 rounded">#{investment.id?.toUpperCase()}</span>
|
|
||||||
<span className="text-slate-300">•</span> Started: {investment.startDate}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<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('Statement download started')} className="px-4 py-2 bg-white border border-slate-200 text-slate-700 rounded-xl text-sm font-bold hover:bg-slate-50 flex items-center gap-2 shadow-sm transition-all">
|
<Download className="w-4 h-4" /> Download
|
||||||
<Download className="w-4 h-4 text-slate-400" /> Download Statement
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3 lg:gap-4 mb-6">
|
||||||
<div className="bg-white rounded-2xl 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-3 mb-3">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<div className="w-10 h-10 bg-purple-100 rounded-xl flex items-center justify-center">
|
<div className="w-8 h-8 bg-purple-100 rounded-lg flex items-center justify-center">
|
||||||
<Wallet className="w-5 h-5 text-purple-600" />
|
<Wallet className="w-4 h-4 text-purple-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-500 font-medium">Invested</p>
|
<p className="text-xs text-slate-500 font-medium">Invested</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-2xl font-extrabold text-slate-800">৳{investment.totalInvestment.toLocaleString()}</p>
|
<p className="text-xl lg:text-2xl font-bold text-slate-800">৳{(investment.totalInvestment / 1000).toFixed(0)}k</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-2xl 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-3 mb-3">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<div className="w-10 h-10 bg-green-100 rounded-xl flex items-center justify-center">
|
<div className="w-8 h-8 bg-green-100 rounded-lg flex items-center justify-center">
|
||||||
<TrendingUp className="w-5 h-5 text-green-600" />
|
<TrendingUp className="w-4 h-4 text-green-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-500 font-medium">Total Return</p>
|
<p className="text-xs text-slate-500 font-medium">Total Return</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-2xl font-extrabold text-green-600">৳{investment.actualEarnings.toLocaleString()}</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-2xl 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-3 mb-3">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<div className="w-10 h-10 bg-amber-100 rounded-xl flex items-center justify-center">
|
<div className="w-8 h-8 bg-amber-100 rounded-lg flex items-center justify-center">
|
||||||
<Clock className="w-5 h-5 text-amber-600" />
|
<Clock className="w-4 h-4 text-amber-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-500 font-medium">Pending</p>
|
<p className="text-xs text-slate-500 font-medium">Pending</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-2xl font-extrabold text-amber-600">৳{(investment.totalInvestment * 0.24 - investment.actualEarnings).toLocaleString()}</p>
|
<p className="text-xl lg:text-2xl font-bold text-amber-600">৳{(investment.totalInvestment * 0.24 - investment.actualEarnings).toLocaleString()}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-2xl 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-3 mb-3">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<div className="w-10 h-10 bg-blue-100 rounded-xl flex items-center justify-center">
|
<div className="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center">
|
||||||
<Percent className="w-5 h-5 text-blue-600" />
|
<Percent className="w-4 h-4 text-blue-600" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-slate-500 font-medium">ROI</p>
|
<p className="text-xs text-slate-500 font-medium">ROI</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-2xl font-extrabold text-blue-600">{investment.expectedRoi}%</p>
|
<p className="text-xl lg:text-2xl font-bold text-blue-600">{investment.expectedRoi}%</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-3 gap-6">
|
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
||||||
<div className="lg:col-span-2 space-y-6">
|
<div className="flex overflow-x-auto border-b border-slate-100">
|
||||||
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm overflow-hidden">
|
{['overview', 'bikes', 'transactions', 'statement'].map((tab) => (
|
||||||
<div className="flex overflow-x-auto bg-slate-50 border-b border-slate-100">
|
|
||||||
{['overview', 'bikes', 'pnl', 'transactions'].map((tab) => (
|
|
||||||
<button
|
<button
|
||||||
key={tab}
|
key={tab}
|
||||||
onClick={() => setActiveTab(tab)}
|
onClick={() => setActiveTab(tab)}
|
||||||
className={`px-6 py-4 text-sm font-bold capitalize transition-colors whitespace-nowrap ${activeTab === tab ? 'text-investor bg-white border-b-2 border-investor' : 'text-slate-500 hover:text-slate-700'}`}
|
className={`px-4 lg:px-6 py-3 text-sm font-semibold capitalize whitespace-nowrap transition-colors ${activeTab === tab
|
||||||
|
? 'text-investor bg-investor/5 border-b-2 border-investor'
|
||||||
|
: 'text-slate-500 hover:text-slate-700 hover:bg-slate-50'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-6">
|
<div className="p-4 lg:p-6">
|
||||||
{activeTab === 'overview' && (
|
{activeTab === 'overview' && (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="grid md:grid-cols-2 gap-4">
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
<div className="bg-slate-50 rounded-2xl p-5 border border-slate-200">
|
<div className="bg-slate-50 rounded-xl p-5 border border-slate-200">
|
||||||
<h4 className="font-bold text-slate-800 mb-4 flex items-center gap-2">
|
<h4 className="font-semibold text-slate-800 mb-4 flex items-center gap-2">
|
||||||
<FileText className="w-5 h-5 text-slate-400" /> Investment Details
|
<FileText className="w-4 h-4 text-slate-400" /> Investment Details
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-3 text-sm">
|
<div className="space-y-3 text-sm">
|
||||||
<div className="flex justify-between border-b border-slate-200 pb-2">
|
<div className="flex justify-between border-b border-slate-200 pb-2">
|
||||||
<span className="text-slate-500">Plan Name</span>
|
<span className="text-slate-500">Plan Name</span>
|
||||||
<span className="font-bold text-slate-800">{investment.planName}</span>
|
<span className="font-semibold text-slate-800">{investment.planName}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between border-b border-slate-200 pb-2">
|
<div className="flex justify-between border-b border-slate-200 pb-2">
|
||||||
<span className="text-slate-500">Plan Type</span>
|
<span className="text-slate-500">Plan Type</span>
|
||||||
<span className="font-bold text-slate-800 capitalize">{investment.planType}</span>
|
<span className="font-semibold text-slate-800 capitalize">{investment.planType}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between border-b border-slate-200 pb-2">
|
<div className="flex justify-between border-b border-slate-200 pb-2">
|
||||||
<span className="text-slate-500">Period</span>
|
<span className="text-slate-500">Period</span>
|
||||||
<span className="font-bold text-slate-800">{investment.startDate} - {investment.endDate || 'Ongoing'}</span>
|
<span className="font-semibold text-slate-800">{investment.startDate} - {investment.endDate || 'Ongoing'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-slate-500">Payment Method</span>
|
<span className="text-slate-500">Payment Method</span>
|
||||||
<span className="font-bold text-slate-800 capitalize">{investment.paymentMethod}</span>
|
<span className="font-semibold text-slate-800 capitalize">{investment.paymentMethod}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-slate-50 rounded-2xl p-5 border border-slate-200">
|
<div className="bg-slate-50 rounded-xl p-5 border border-slate-200">
|
||||||
<h4 className="font-bold text-slate-800 mb-4 flex items-center gap-2">
|
<h4 className="font-semibold text-slate-800 mb-4 flex items-center gap-2">
|
||||||
<Shield className="w-5 h-5 text-slate-400" /> Plan Policy
|
<Shield className="w-4 h-4 text-slate-400" /> Plan Policy
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-3 text-sm">
|
<div className="space-y-3 text-sm">
|
||||||
<div className="flex justify-between border-b border-slate-200 pb-2">
|
<div className="flex justify-between border-b border-slate-200 pb-2">
|
||||||
<span className="text-slate-500">Min Duration</span>
|
<span className="text-slate-500">Min Duration</span>
|
||||||
<span className="font-bold text-slate-800">12 Months</span>
|
<span className="font-semibold text-slate-800">12 Months</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between border-b border-slate-200 pb-2">
|
<div className="flex justify-between border-b border-slate-200 pb-2">
|
||||||
<span className="text-slate-500">Lock-in Period</span>
|
<span className="text-slate-500">Lock-in Period</span>
|
||||||
<span className="font-bold text-slate-800">3 Months</span>
|
<span className="font-semibold text-slate-800">3 Months</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between border-b border-slate-200 pb-2">
|
<div className="flex justify-between border-b border-slate-200 pb-2">
|
||||||
<span className="text-slate-500">Exit Penalty</span>
|
<span className="text-slate-500">Exit Penalty</span>
|
||||||
<span className="font-bold text-red-500">10%</span>
|
<span className="font-semibold text-red-500">10%</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-slate-500">Maintenance</span>
|
<span className="text-slate-500">Maintenance</span>
|
||||||
<span className="font-bold text-green-600">Included</span>
|
<span className="font-semibold text-green-600">Included</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-amber-50 border border-amber-200 rounded-2xl p-5">
|
<div className="bg-amber-50 border border-amber-200 rounded-xl p-5">
|
||||||
<h4 className="font-bold text-amber-800 mb-4 flex items-center gap-2">
|
<h4 className="font-semibold text-amber-800 mb-4 flex items-center gap-2">
|
||||||
<Percent className="w-5 h-5 text-amber-600" /> Profit Sharing Configuration
|
<Percent className="w-4 h-4 text-amber-600" /> Profit Sharing
|
||||||
</h4>
|
</h4>
|
||||||
<p className="text-xs text-amber-600 mb-4 uppercase font-bold tracking-wider">Your share based on rental model</p>
|
<p className="text-xs text-amber-600 mb-4 font-medium">Your share based on rental model</p>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-3 gap-3">
|
||||||
<div className="bg-white rounded-xl p-4 text-center border border-amber-200 shadow-sm">
|
<div className="bg-white rounded-lg p-3 text-center border border-amber-200">
|
||||||
<p className="text-xs text-slate-400 mb-1 font-bold uppercase">Single Rent</p>
|
<p className="text-xs text-slate-500 mb-1 font-medium">Single Rent</p>
|
||||||
<p className="text-2xl font-extrabold text-slate-800">55%</p>
|
<p className="text-xl font-bold text-slate-800">55%</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl p-4 text-center border border-amber-200 shadow-sm">
|
<div className="bg-white rounded-lg p-3 text-center border border-amber-200">
|
||||||
<p className="text-xs text-slate-400 mb-1 font-bold uppercase">Rent to Own</p>
|
<p className="text-xs text-slate-500 mb-1 font-medium">Rent to Own</p>
|
||||||
<p className="text-2xl font-extrabold text-slate-800">45%</p>
|
<p className="text-xl font-bold text-slate-800">45%</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white rounded-xl p-4 text-center border border-amber-200 shadow-sm ring-2 ring-amber-500 ring-offset-2">
|
<div className="bg-white rounded-lg p-3 text-center border-2 border-amber-400 ring-2 ring-amber-100">
|
||||||
<p className="text-xs text-slate-400 mb-1 font-bold uppercase">Share EV</p>
|
<p className="text-xs text-slate-500 mb-1 font-medium">Share EV</p>
|
||||||
<p className="text-2xl font-extrabold text-slate-800">40%</p>
|
<p className="text-xl font-bold text-slate-800">40%</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -214,63 +258,67 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
|
|
||||||
{activeTab === 'bikes' && (
|
{activeTab === 'bikes' && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{assignedBikes.length > 0 ? assignedBikes.map(bike => (
|
<div className="flex items-center justify-between">
|
||||||
<div key={bike.id} className="p-5 bg-white rounded-2xl border border-slate-200 flex flex-col md:flex-row items-start md:items-center gap-5 hover:border-investor transition-colors group">
|
<p className="text-sm text-slate-500">{demoBikes.length} bikes assigned to this investment</p>
|
||||||
<div className="w-20 h-20 bg-slate-100 rounded-xl overflow-hidden shrink-0 border border-slate-200">
|
</div>
|
||||||
|
{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 className="w-24 h-20 bg-slate-100 rounded-lg overflow-hidden shrink-0">
|
||||||
<img src={bike.image} alt={bike.model} className="w-full h-full object-cover" />
|
<img src={bike.image} alt={bike.model} className="w-full h-full object-cover" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<h5 className="font-bold text-lg text-slate-800 truncate">{bike.model}</h5>
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<p className="text-sm text-slate-500">{bike.plateNumber} • {bike.brand}</p>
|
<h5 className="font-semibold text-slate-800">{bike.model}</h5>
|
||||||
<div className="mt-3 flex flex-wrap gap-2">
|
<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' : 'bg-blue-100 text-blue-700'}`}>
|
bike.status === 'available' ? 'bg-blue-100 text-blue-700' :
|
||||||
|
'bg-red-100 text-red-700'
|
||||||
|
}`}>
|
||||||
{bike.status}
|
{bike.status}
|
||||||
</span>
|
</span>
|
||||||
<span className="px-2 py-0.5 rounded bg-slate-100 text-slate-600 text-[10px] font-bold uppercase flex items-center gap-1">
|
</div>
|
||||||
Daily: ৳{bike.currentRent}
|
<p className="text-sm text-slate-500">{bike.plateNumber} • {bike.brand}</p>
|
||||||
</span>
|
<div className="mt-2 flex flex-wrap gap-3 text-xs text-slate-500">
|
||||||
|
<span className="flex items-center gap-1"><Battery className="w-3 h-3" /> {bike.batteryLevel}%</span>
|
||||||
|
<span className="flex items-center gap-1"><Gauge className="w-3 h-3" /> {bike.range} km</span>
|
||||||
|
<span className="flex items-center gap-1"><MapPin className="w-3 h-3" /> {bike.location}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right">
|
<div className="text-right shrink-0">
|
||||||
<p className="text-xs text-slate-400 mb-1 uppercase font-bold tracking-wider">Total Earnings</p>
|
<p className="text-xs text-slate-500 mb-1">Daily Rent</p>
|
||||||
<p className="text-xl font-extrabold text-green-600">৳{bike.totalEarnings?.toLocaleString()}</p>
|
<p className="text-lg font-bold text-slate-800">৳{bike.currentRent}</p>
|
||||||
<Link href="/investor/portfolio" className="mt-2 text-xs font-bold text-investor hover:underline flex items-center gap-1 justify-end">
|
<p className="text-xs text-slate-400 mt-1">Total: ৳{bike.totalEarnings.toLocaleString()}</p>
|
||||||
Live Track <ChevronRight className="w-3 h-3" />
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)) : (
|
))}
|
||||||
<div className="text-center py-12 border-2 border-dashed border-slate-200 rounded-2xl">
|
|
||||||
<Bike className="w-12 h-12 mx-auto mb-4 text-slate-300" />
|
|
||||||
<p className="text-slate-500 font-bold">No bikes assigned yet.</p>
|
|
||||||
<p className="text-xs text-slate-400 mt-1">Admin will assign bikes to this investment shortly.</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'pnl' && (
|
{activeTab === 'statement' && (
|
||||||
<div className="max-w-xl mx-auto">
|
<div className="max-w-2xl mx-auto">
|
||||||
<div className="bg-slate-50 rounded-2xl p-6 border border-slate-200">
|
<div className="bg-slate-50 rounded-xl p-5 border border-slate-200">
|
||||||
<h3 className="font-bold text-slate-800 mb-6 text-center text-lg">Detailed P&L Statement</h3>
|
<h3 className="font-semibold text-slate-800 mb-5 text-center text-lg">Profit & Loss Statement</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-between items-center pb-4 border-b border-slate-200">
|
<div className="flex justify-between items-center pb-3 border-b border-slate-200">
|
||||||
<span className="font-bold text-slate-600">Gross Rental Revenue</span>
|
<span className="font-medium text-slate-600">Gross Rental Revenue</span>
|
||||||
<span className="text-xl font-bold text-slate-800">৳{(investment.actualEarnings / 0.55).toFixed(0)}</span>
|
<span className="text-xl font-bold text-slate-800">৳{demoPnl.grossRevenue.toLocaleString()}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3 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 Management Fee (45%)</span>
|
<span className="text-slate-500">Platform Fee (45%)</span>
|
||||||
<span className="text-red-500 font-bold">-৳{((investment.actualEarnings / 0.55) * 0.45).toFixed(0)}</span>
|
<span className="font-medium text-red-500">-৳{demoPnl.platformFee.toLocaleString()}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-sm">
|
<div className="flex justify-between text-sm">
|
||||||
<span className="text-slate-500">Fleet Insurance & Maintenance</span>
|
<span className="text-slate-500">Insurance Coverage</span>
|
||||||
<span className="text-green-600 font-bold tracking-tight uppercase text-[10px]">Included in Platform Fee</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>
|
||||||
<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-extrabold text-slate-800">Net Return to Investor</span>
|
<span className="text-lg font-semibold text-slate-800">Net Return</span>
|
||||||
<span className="text-2xl font-extrabold text-green-600">৳{investment.actualEarnings.toLocaleString()}</span>
|
<span className="text-2xl font-bold text-green-600">৳{demoPnl.netProfit.toLocaleString()}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -282,26 +330,26 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
<table className="w-full text-left">
|
<table className="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-bold text-slate-500 uppercase tracking-wider">Date</th>
|
<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-bold text-slate-500 uppercase tracking-wider">Description</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-bold text-slate-500 uppercase tracking-wider text-right">Amount</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-bold text-slate-500 uppercase tracking-wider">Status</th>
|
<th className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase">Status</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-slate-100">
|
<tbody className="divide-y divide-slate-100">
|
||||||
{investmentTransactions.map(t => (
|
{demoTransactions.map((tx) => (
|
||||||
<tr key={t.id} className="hover:bg-slate-50 transition-colors">
|
<tr key={tx.id} className="hover:bg-slate-50 transition-colors">
|
||||||
<td className="px-4 py-4 text-sm text-slate-600 whitespace-nowrap">{t.createdAt}</td>
|
<td className="px-4 py-3 text-sm text-slate-600 whitespace-nowrap">{tx.date}</td>
|
||||||
<td className="px-4 py-4">
|
<td className="px-4 py-3">
|
||||||
<p className="text-sm font-bold text-slate-800">{t.description}</p>
|
<p className="text-sm font-medium text-slate-800">{tx.description}</p>
|
||||||
<p className="text-xs text-slate-400">Ref: {t.id}</p>
|
<p className="text-xs text-slate-400">Ref: {tx.id}</p>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-4 text-sm font-extrabold text-green-600 text-right">
|
<td className={`px-4 py-3 text-sm font-bold text-right ${tx.amount > 0 ? 'text-green-600' : 'text-red-500'}`}>
|
||||||
+৳{t.amount.toLocaleString()}
|
{tx.amount > 0 ? '+' : ''}৳{tx.amount.toLocaleString()}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-4">
|
<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">
|
<span className="inline-flex px-2 py-0.5 rounded text-[10px] font-bold uppercase bg-green-100 text-green-700">
|
||||||
Completed
|
{tx.status}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -313,39 +361,6 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div className="bg-white rounded-2xl border border-slate-200 p-5 shadow-sm">
|
|
||||||
<h4 className="font-bold text-slate-800 mb-4 flex items-center gap-2">
|
|
||||||
<Zap className="w-5 h-5 text-amber-500" /> Quick Actions
|
|
||||||
</h4>
|
|
||||||
<div className="space-y-3">
|
|
||||||
<button onClick={() => toast.success('Printing report...')} className="w-full px-4 py-3 border border-slate-200 text-slate-700 rounded-xl text-sm font-bold hover:bg-slate-50 flex items-center gap-3 transition-all">
|
|
||||||
<Printer className="w-5 h-5 text-slate-400" /> Print Summary
|
|
||||||
</button>
|
|
||||||
<button onClick={() => toast.success('Exporting to Excel...')} className="w-full px-4 py-3 border border-slate-200 text-slate-700 rounded-xl text-sm font-bold hover:bg-slate-50 flex items-center gap-3 transition-all">
|
|
||||||
<BarChart3 className="w-5 h-5 text-slate-400" /> Export Data
|
|
||||||
</button>
|
|
||||||
<button onClick={() => router.push('/investor/withdraw')} className="w-full px-4 py-3 bg-investor text-white rounded-xl text-sm font-bold hover:bg-investor-dark flex items-center gap-3 shadow-md shadow-investor/20 transition-all">
|
|
||||||
<DollarSign className="w-5 h-5" /> Withdraw Earnings
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-5">
|
|
||||||
<h4 className="font-bold text-blue-800 mb-3 flex items-center gap-2">
|
|
||||||
<Smartphone className="w-5 h-5 text-blue-600" /> Support Desk
|
|
||||||
</h4>
|
|
||||||
<p className="text-xs text-blue-700 mb-4 font-medium leading-relaxed">
|
|
||||||
Need help with this investment or bike assignment? Our team is available 24/7.
|
|
||||||
</p>
|
|
||||||
<button onClick={() => toast.success('Connecting to support...')} className="w-full py-2.5 bg-blue-600 text-white rounded-xl font-bold text-sm hover:bg-blue-700 transition-colors">
|
|
||||||
Contact Support
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user