Add full FOCO investor management system with CRUD, investments, and transactions

This commit is contained in:
sazzadulalambd
2026-04-22 01:02:45 +06:00
parent 5338038ea2
commit dab0c11b15
32 changed files with 7673 additions and 89 deletions

211
src/app/admin/page.tsx Normal file
View File

@@ -0,0 +1,211 @@
import {
Users,
Bike,
DollarSign,
TrendingUp,
Activity,
ArrowUpRight,
ArrowDownRight,
Clock,
Shield,
AlertTriangle,
CheckCircle,
XCircle
} from 'lucide-react';
import { kycRequests, bikes, rentals, transactions } from '@/data/mockData';
const stats = [
{ label: 'Total Bikers', value: '156', change: '+12%', trend: 'up', icon: Users, color: 'text-blue-600', bg: 'bg-blue-50' },
{ label: 'Active Rentals', value: '89', change: '+8%', trend: 'up', icon: Bike, color: 'text-green-600', bg: 'bg-green-50' },
{ label: 'Daily Revenue', value: '৳45.6k', change: '+23%', trend: 'up', icon: DollarSign, color: 'text-purple-600', bg: 'bg-purple-50' },
{ label: 'Fleet Utilization', value: '78%', change: '-2%', trend: 'down', icon: TrendingUp, color: 'text-amber-600', bg: 'bg-amber-50' },
];
const pendingKYCs = kycRequests.filter(k => k.status === 'pending');
const activeRentals = rentals.filter(r => r.status === 'active');
export default function AdminDashboard() {
return (
<div className="p-4 lg:p-6">
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-6">
<div>
<h1 className="text-2xl lg:text-3xl font-extrabold text-slate-800">Admin Dashboard</h1>
<p className="text-sm text-slate-500 mt-1">Manage fleet, users, and operations</p>
</div>
<div className="flex items-center gap-2">
<span className="text-sm text-slate-500">Last updated:</span>
<span className="text-sm font-medium text-slate-700">Just now</span>
</div>
</div>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
{stats.map((stat, index) => {
const Icon = stat.icon;
return (
<div key={index} className="bg-white rounded-xl p-5 shadow-sm border border-slate-100 hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-3">
<div className={`w-12 h-12 rounded-xl ${stat.bg} flex items-center justify-center`}>
<Icon className={`w-6 h-6 ${stat.color}`} />
</div>
<span className={`text-xs font-semibold px-2 py-1 rounded-full flex items-center gap-1 ${
stat.trend === 'up' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'
}`}>
{stat.trend === 'up' ? <ArrowUpRight className="w-3 h-3" /> : <ArrowDownRight className="w-3 h-3" />}
{stat.change}
</span>
</div>
<p className="text-2xl font-extrabold text-slate-800">{stat.value}</p>
<p className="text-sm text-slate-500 mt-1">{stat.label}</p>
</div>
);
})}
</div>
<div className="grid lg:grid-cols-3 gap-6 mb-8">
<div className="lg:col-span-2 bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden">
<div className="px-5 py-4 border-b border-slate-100 flex items-center justify-between">
<h2 className="font-bold text-slate-800">Recent Rentals</h2>
<button className="text-sm text-blue-600 font-medium hover:underline">View All</button>
</div>
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-slate-50">
<tr>
<th className="px-4 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Rental ID</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Bike</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">User</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Type</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Status</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Daily Rate</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-50">
{activeRentals.map(rental => {
const bike = bikes.find(b => b.id === rental.bikeId);
return (
<tr key={rental.id} className="hover:bg-slate-50 transition-colors">
<td className="px-4 py-3">
<span className="text-sm font-medium text-slate-700">{rental.id}</span>
</td>
<td className="px-4 py-3">
<span className="text-sm text-slate-600">{bike?.model}</span>
<span className="text-xs text-slate-400 block">{bike?.plateNumber}</span>
</td>
<td className="px-4 py-3">
<span className="text-sm text-slate-600">{rental.userId}</span>
</td>
<td className="px-4 py-3">
<span className="text-sm text-slate-600 capitalize">{rental.type}</span>
</td>
<td className="px-4 py-3">
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${
rental.status === 'active' ? 'bg-green-100 text-green-700' :
rental.status === 'pending' ? 'bg-amber-100 text-amber-700' :
'bg-slate-100 text-slate-500'
}`}>
<Activity className="w-3 h-3" />
{rental.status}
</span>
</td>
<td className="px-4 py-3">
<span className="text-sm font-semibold text-slate-700">{rental.dailyRate}</span>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden">
<div className="px-5 py-4 border-b border-slate-100 flex items-center justify-between">
<h2 className="font-bold text-slate-800">KYC Requests</h2>
<span className="text-xs font-semibold px-2 py-1 bg-amber-100 text-amber-700 rounded-full">
{pendingKYCs.length} pending
</span>
</div>
<div className="divide-y divide-slate-50">
{pendingKYCs.map(kyc => (
<div key={kyc.id} className="p-4 hover:bg-slate-50 transition-colors">
<div className="flex items-start justify-between mb-3">
<div>
<p className="font-medium text-slate-700">{kyc.userName}</p>
<p className="text-sm text-slate-400">{kyc.phone}</p>
<p className="text-xs text-slate-400 mt-1 flex items-center gap-1">
<Clock className="w-3 h-3" /> {kyc.submittedAt}
</p>
</div>
<span className="p-1.5 bg-amber-100 rounded-lg">
<Shield className="w-4 h-4 text-amber-600" />
</span>
</div>
<div className="flex gap-2">
<button className="flex-1 py-2 bg-green-600 text-white text-sm font-semibold rounded-lg hover:bg-green-700 flex items-center justify-center gap-1">
<CheckCircle className="w-4 h-4" /> Approve
</button>
<button className="flex-1 py-2 border border-red-200 text-red-600 text-sm font-semibold rounded-lg hover:bg-red-50 flex items-center justify-center gap-1">
<XCircle className="w-4 h-4" /> Reject
</button>
</div>
</div>
))}
{pendingKYCs.length === 0 && (
<div className="p-8 text-center">
<CheckCircle className="w-12 h-12 text-green-500 mx-auto mb-2" />
<p className="text-sm text-slate-500">No pending KYC requests</p>
</div>
)}
</div>
</div>
</div>
<div className="grid lg:grid-cols-2 gap-6">
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-5">
<h2 className="font-bold text-slate-800 mb-4">Quick Actions</h2>
<div className="grid grid-cols-2 gap-3">
<button className="py-3 px-4 bg-accent text-white rounded-lg font-semibold text-sm hover:bg-accent-dark transition-colors">
+ Add New Bike
</button>
<button className="py-3 px-4 bg-blue-600 text-white rounded-lg font-semibold text-sm hover:bg-blue-700 transition-colors">
Manage Users
</button>
<button className="py-3 px-4 bg-purple-600 text-white rounded-lg font-semibold text-sm hover:bg-purple-700 transition-colors">
View Reports
</button>
<button className="py-3 px-4 border border-slate-200 text-slate-600 rounded-lg font-semibold text-sm hover:bg-slate-50 transition-colors">
Settings
</button>
</div>
</div>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-5">
<h2 className="font-bold text-slate-800 mb-4">System Alerts</h2>
<div className="space-y-3">
<div className="flex items-center gap-3 p-3 bg-red-50 rounded-lg border border-red-100">
<AlertTriangle className="w-5 h-5 text-red-500" />
<div>
<p className="text-sm font-medium text-red-700">3 bikes overdue maintenance</p>
<p className="text-xs text-red-500">Action required</p>
</div>
</div>
<div className="flex items-center gap-3 p-3 bg-amber-50 rounded-lg border border-amber-100">
<Clock className="w-5 h-5 text-amber-500" />
<div>
<p className="text-sm font-medium text-amber-700">5 pending KYC verifications</p>
<p className="text-xs text-amber-500">Review needed</p>
</div>
</div>
<div className="flex items-center gap-3 p-3 bg-green-50 rounded-lg border border-green-100">
<CheckCircle className="w-5 h-5 text-green-500" />
<div>
<p className="text-sm font-medium text-green-700">System running smoothly</p>
<p className="text-xs text-green-500">All services operational</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}