290 lines
10 KiB
TypeScript
290 lines
10 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { RefreshCcw, MapPin, Users, TrendingUp, Clock, CheckCircle, AlertCircle, ShoppingBag, Loader2 } from 'lucide-react';
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { User } from '@/lib/mock-data';
|
|
import { dealerService } from '@/services/dealer.service';
|
|
|
|
interface DealerDashboardProps {
|
|
currentUser: User | null;
|
|
onNavigate: (view: string) => void;
|
|
}
|
|
|
|
export function DealerDashboard({ currentUser, onNavigate }: DealerDashboardProps) {
|
|
const [loading, setLoading] = useState(true);
|
|
const [data, setData] = useState<any>(null);
|
|
|
|
useEffect(() => {
|
|
const fetchDashboard = async () => {
|
|
try {
|
|
const dashboardData = await dealerService.getDashboardData();
|
|
setData(dashboardData);
|
|
} catch (error) {
|
|
console.error('Failed to fetch dashboard:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
fetchDashboard();
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="flex flex-col items-center justify-center min-h-[400px]">
|
|
<Loader2 className="w-10 h-10 text-amber-600 animate-spin mb-4" />
|
|
<p className="text-slate-600">Loading your dashboard...</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const dashboardData = data || {};
|
|
const profile = dashboardData.profile || {};
|
|
const statsSummary = dashboardData.stats || { constitutional: 0, relocation: 0, resignation: 0, total: 0 };
|
|
const recentRequests = dashboardData.recentRequests || [];
|
|
const primaryOutlet = dashboardData.outlets?.[0] || {};
|
|
|
|
// Dealer stats
|
|
const stats = [
|
|
{
|
|
title: 'Constitutional Changes',
|
|
value: statsSummary.constitutional,
|
|
icon: RefreshCcw,
|
|
color: 'bg-blue-500',
|
|
change: 'Active Requests',
|
|
onClick: () => onNavigate('dealer-constitutional')
|
|
},
|
|
{
|
|
title: 'Relocation Requests',
|
|
value: statsSummary.relocation,
|
|
icon: MapPin,
|
|
color: 'bg-amber-500',
|
|
change: 'Active Requests',
|
|
onClick: () => onNavigate('dealer-relocation')
|
|
},
|
|
{
|
|
title: 'My Outlets',
|
|
value: dashboardData.outlets?.length || 0,
|
|
icon: ShoppingBag,
|
|
color: 'bg-purple-500',
|
|
change: 'Registered',
|
|
onClick: () => {}
|
|
},
|
|
{
|
|
title: 'Total Requests',
|
|
value: statsSummary.total,
|
|
icon: TrendingUp,
|
|
color: 'bg-green-500',
|
|
change: 'All time',
|
|
onClick: () => {}
|
|
},
|
|
];
|
|
|
|
// Recent requests by the dealer
|
|
|
|
// Quick actions for dealer
|
|
const quickActions = [
|
|
{
|
|
title: 'Constitutional Change',
|
|
description: 'Request change in business structure',
|
|
icon: RefreshCcw,
|
|
color: 'bg-blue-50 hover:bg-blue-100 border-blue-200',
|
|
textColor: 'text-blue-700',
|
|
onClick: () => onNavigate('dealer-constitutional')
|
|
},
|
|
{
|
|
title: 'Request Relocation',
|
|
description: 'Move dealership to new location',
|
|
icon: MapPin,
|
|
color: 'bg-amber-50 hover:bg-amber-100 border-amber-200',
|
|
textColor: 'text-amber-700',
|
|
onClick: () => onNavigate('dealer-relocation')
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Welcome Section */}
|
|
<div className="bg-gradient-to-r from-amber-500 to-amber-600 rounded-lg p-6 text-white">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-white mb-2">Welcome back, {profile.name || currentUser?.name}!</h1>
|
|
<p className="text-amber-100">
|
|
Dealer Code: {profile.dealerCode} • {profile.businessName}
|
|
</p>
|
|
<p className="text-amber-100 text-sm mt-1">
|
|
{primaryOutlet.name} • {primaryOutlet.location}
|
|
</p>
|
|
</div>
|
|
<div className="text-right">
|
|
<div className="text-white">Active Dealership</div>
|
|
<Badge className="bg-green-500 text-white border-0 mt-2">
|
|
<CheckCircle className="w-3 h-3 mr-1" />
|
|
Operational
|
|
</Badge>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Stats Grid */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
{stats.map((stat, index) => {
|
|
const Icon = stat.icon;
|
|
return (
|
|
<Card
|
|
key={index}
|
|
className="cursor-pointer hover:shadow-lg transition-shadow"
|
|
onClick={stat.onClick}
|
|
>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm">{stat.title}</CardTitle>
|
|
<div className={`${stat.color} p-2 rounded-lg`}>
|
|
<Icon className="h-4 w-4 text-white" />
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-slate-900 text-2xl">{stat.value}</div>
|
|
<p className="text-xs text-slate-600 mt-1">{stat.change}</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
{/* Quick Actions */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Quick Actions</CardTitle>
|
|
<CardDescription>Submit new requests and manage your dealership</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
{quickActions.map((action, index) => {
|
|
const Icon = action.icon;
|
|
return (
|
|
<button
|
|
key={index}
|
|
onClick={action.onClick}
|
|
className={`${action.color} border-2 rounded-lg p-4 text-left transition-all`}
|
|
>
|
|
<div className="flex items-start gap-3">
|
|
<div className={`${action.textColor} p-2 bg-white rounded-lg`}>
|
|
<Icon className="w-5 h-5" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className={`${action.textColor} mb-1`}>{action.title}</h3>
|
|
<p className="text-slate-600 text-sm">{action.description}</p>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Recent Requests */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>My Recent Requests</CardTitle>
|
|
<CardDescription>Track the status of your submitted requests</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-3">
|
|
{recentRequests.map((request: any) => (
|
|
<div
|
|
key={request.id}
|
|
className="flex items-center justify-between p-4 border border-slate-200 rounded-lg hover:bg-slate-50 transition-colors"
|
|
>
|
|
<div className="flex-1">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<span className="text-slate-900">{request.id}</span>
|
|
<Badge variant="outline" className="text-xs">
|
|
{request.type}
|
|
</Badge>
|
|
</div>
|
|
<p className="text-slate-600 text-sm">{request.title}</p>
|
|
<p className="text-slate-500 text-xs mt-1">Submitted on {request.date}</p>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<Badge className={`border ${request.color}`}>
|
|
{request.status}
|
|
</Badge>
|
|
<Button variant="ghost" size="sm">
|
|
View
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Information Cards */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Clock className="w-5 h-5 text-amber-600" />
|
|
Important Reminders
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-3">
|
|
<div className="flex items-start gap-2">
|
|
<AlertCircle className="w-4 h-4 text-amber-600 mt-0.5" />
|
|
<div>
|
|
<p className="text-slate-900 text-sm">GST Filing Due</p>
|
|
<p className="text-slate-600 text-xs">Due by Jan 15, 2026</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-2">
|
|
<AlertCircle className="w-4 h-4 text-amber-600 mt-0.5" />
|
|
<div>
|
|
<p className="text-slate-900 text-sm">Inventory Audit Scheduled</p>
|
|
<p className="text-slate-600 text-xs">Jan 20, 2026</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-2">
|
|
<CheckCircle className="w-4 h-4 text-green-600 mt-0.5" />
|
|
<div>
|
|
<p className="text-slate-900 text-sm">Compliance Report Submitted</p>
|
|
<p className="text-slate-600 text-xs">Jan 2, 2026</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Users className="w-5 h-5 text-blue-600" />
|
|
Support & Help
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-3">
|
|
<div>
|
|
<p className="text-slate-900 text-sm mb-1">Regional Manager</p>
|
|
<p className="text-slate-600 text-xs">Rajesh Kumar - +91 98765 43210</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-slate-900 text-sm mb-1">Zonal Business Head</p>
|
|
<p className="text-slate-600 text-xs">Priya Sharma - +91 98765 43211</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-slate-900 text-sm mb-1">Support Email</p>
|
|
<p className="text-slate-600 text-xs">dealer.support@royalenfield.com</p>
|
|
</div>
|
|
<Button variant="outline" className="w-full mt-2">
|
|
Contact Support
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|