- {/* Header */}
-
-
-
My Relocation Requests
-
- Submit and track requests for relocating your dealership
-
+ {/* Loading Overlay */}
+ {loading && (
+
+
-
-
+
+
+ {/* Stats */}
+
+ {stats.map((stat, index) => {
+ const Icon = stat.icon;
+ return (
+
+
+ {stat.title}
+
+
+
+
+
+ {stat.value}
+
+
+ );
+ })}
+
+
+ {/* Requests Table */}
+
+
+ My Relocation Requests
+
+ Track the status of your relocation applications
+
+
+
+
+
+
+ Request ID
+ Outlet
+ Target Location
+ Submitted On
+ Current Status
+ Progress
+ Actions
+
+
+
+ {requests.length === 0 ? (
+
+
+ No relocation requests found
+
+
+ ) : (
+ requests.map((request) => (
+
+
+ {request.requestId}
+
+
+ {request.outlet?.name}
+
+
+
+
{request.currentCity}
+
+
{request.newCity}
+
+
+
+ {new Date(request.createdAt).toLocaleDateString()}
+
+
+
+ {request.status}
+
+
+
+
+
+
{request.progressPercentage || 0}%
+
+
+
+ onViewDetails && onViewDetails(request.requestId)}
+ >
+
+ View
+
+
+
+ ))
+ )}
+
+
+
+
+ >
+ )}
);
}
diff --git a/src/components/dealer/DealerResignationPage.tsx b/src/components/dealer/DealerResignationPage.tsx
index 2a5cdbf..d2789a6 100644
--- a/src/components/dealer/DealerResignationPage.tsx
+++ b/src/components/dealer/DealerResignationPage.tsx
@@ -1,4 +1,4 @@
-import { FileText, Plus, Eye, Calendar, User, Building2, Store, MapPin, CheckCircle, Clock } from 'lucide-react';
+import { FileText, Plus, Eye, Calendar, User, Building2, Store, MapPin, CheckCircle, Clock, RefreshCcw, Loader2 } from 'lucide-react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card';
import { Badge } from '../ui/badge';
import { Button } from '../ui/button';
@@ -8,107 +8,17 @@ import { Input } from '../ui/input';
import { Label } from '../ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
import { Textarea } from '../ui/textarea';
-import { useState } from 'react';
+import { useState, useEffect } from 'react';
import { User as UserType } from '../../lib/mock-data';
import { toast } from 'sonner';
+import { dealerService } from '../../services/dealer.service';
+import { resignationService } from '../../services/resignation.service';
interface DealerResignationPageProps {
currentUser: UserType | null;
onViewDetails?: (id: string) => void;
}
-// Mock outlets owned by dealer
-interface Outlet {
- id: string;
- code: string;
- name: string;
- type: 'Dealership' | 'Studio';
- address: string;
- city: string;
- state: string;
- status: 'Active' | 'Pending Resignation' | 'Closed';
- establishedDate: string;
- hasActiveResignation?: boolean;
- resignationId?: string;
-}
-
-const mockOutlets: Outlet[] = [
- {
- id: 'OUT-001',
- code: 'DL-MH-001',
- name: 'Royal Enfield Mumbai',
- type: 'Dealership',
- address: 'Plot No. 45, Linking Road, Bandra West',
- city: 'Mumbai',
- state: 'Maharashtra',
- status: 'Active',
- establishedDate: '2018-06-15',
- hasActiveResignation: true,
- resignationId: 'RES-001'
- },
- {
- id: 'OUT-002',
- code: 'ST-MH-002',
- name: 'Royal Enfield Andheri Studio',
- type: 'Studio',
- address: 'Shop 12, Phoenix Market City, Kurla',
- city: 'Mumbai',
- state: 'Maharashtra',
- status: 'Active',
- establishedDate: '2020-03-20'
- },
- {
- id: 'OUT-003',
- code: 'DL-MH-003',
- name: 'Royal Enfield Thane Dealership',
- type: 'Dealership',
- address: 'Eastern Express Highway, Thane West',
- city: 'Thane',
- state: 'Maharashtra',
- status: 'Active',
- establishedDate: '2019-09-10'
- },
- {
- id: 'OUT-004',
- code: 'ST-MH-004',
- name: 'Royal Enfield Pune Studio',
- type: 'Studio',
- address: 'FC Road, Deccan Gymkhana',
- city: 'Pune',
- state: 'Maharashtra',
- status: 'Active',
- establishedDate: '2021-01-05'
- }
-];
-
-// Mock resignation requests for this dealer
-const mockDealerResignations = [
- {
- id: 'RES-001',
- dealerCode: 'DL-MH-001',
- dealerName: 'Amit Sharma Motors',
- resignationType: 'Voluntary',
- lastOperationalDate: '2026-02-28',
- reason: 'Personal health issues',
- status: 'ASM Review',
- submittedOn: '2025-12-20',
- currentStage: 'ASM',
- progressPercentage: 15
- },
- {
- id: 'RES-005',
- dealerCode: 'DL-MH-001',
- dealerName: 'Amit Sharma Motors',
- resignationType: 'Voluntary',
- lastOperationalDate: '2025-06-30',
- reason: 'Relocation to different city',
- status: 'Completed',
- submittedOn: '2025-04-15',
- currentStage: 'Closed',
- progressPercentage: 100
- },
-];
-
const getStatusColor = (status: string) => {
if (status === 'Completed') return 'bg-green-100 text-green-700 border-green-300';
if (status.includes('Review') || status.includes('Pending')) return 'bg-yellow-100 text-yellow-700 border-yellow-300';
@@ -118,19 +28,46 @@ const getStatusColor = (status: string) => {
export function DealerResignationPage({ currentUser, onViewDetails }: DealerResignationPageProps) {
const [isDialogOpen, setIsDialogOpen] = useState(false);
- const [selectedOutlet, setSelectedOutlet] = useState
(null);
+ const [selectedOutlet, setSelectedOutlet] = useState(null);
const [resignationType, setResignationType] = useState('');
const [lastOperationalDateSales, setLastOperationalDateSales] = useState('');
const [lastOperationalDateServices, setLastOperationalDateServices] = useState('');
const [reason, setReason] = useState('');
const [additionalInfo, setAdditionalInfo] = useState('');
+
+ const [outlets, setOutlets] = useState([]);
+ const [resignations, setResignations] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [submitting, setSubmitting] = useState(false);
+ const [profile, setProfile] = useState(null);
- const handleOpenResignationDialog = (outlet: Outlet) => {
+ useEffect(() => {
+ fetchData();
+ }, []);
+
+ const fetchData = async () => {
+ try {
+ setLoading(true);
+ const dashboard = await dealerService.getDashboardData();
+ const resignationsRes = await resignationService.getResignations();
+
+ setOutlets(dashboard.outlets || []);
+ setProfile(dashboard.profile);
+ setResignations(resignationsRes.resignations || []);
+ } catch (error) {
+ console.error('Fetch resignation data error:', error);
+ toast.error('Failed to load outlets and requests');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleOpenResignationDialog = (outlet: any) => {
setSelectedOutlet(outlet);
setIsDialogOpen(true);
};
- const handleSubmitRequest = (e: React.FormEvent) => {
+ const handleSubmitRequest = async (e: React.FormEvent) => {
e.preventDefault();
if (!resignationType) {
@@ -148,34 +85,53 @@ export function DealerResignationPage({ currentUser, onViewDetails }: DealerResi
return;
}
- toast.success(`Resignation request submitted successfully for ${selectedOutlet?.name}`);
- setIsDialogOpen(false);
-
- // Reset form
- setSelectedOutlet(null);
- setResignationType('');
- setLastOperationalDateSales('');
- setLastOperationalDateServices('');
- setReason('');
- setAdditionalInfo('');
+ try {
+ setSubmitting(true);
+ const payload = {
+ outletId: selectedOutlet?.id,
+ resignationType,
+ lastOperationalDateSales,
+ lastOperationalDateServices,
+ reason,
+ additionalInfo
+ };
+
+ await resignationService.createResignation(payload);
+ toast.success(`Resignation request submitted successfully for ${selectedOutlet?.name}`);
+ setIsDialogOpen(false);
+ fetchData(); // Refresh data
+
+ // Reset form
+ setSelectedOutlet(null);
+ setResignationType('');
+ setLastOperationalDateSales('');
+ setLastOperationalDateServices('');
+ setReason('');
+ setAdditionalInfo('');
+ } catch (error) {
+ console.error('Submit resignation error:', error);
+ toast.error('Failed to submit resignation request');
+ } finally {
+ setSubmitting(false);
+ }
};
const stats = [
{
title: 'Total Outlets',
- value: mockOutlets.length,
+ value: outlets.length,
icon: Building2,
color: 'bg-blue-500',
},
{
title: 'Active Outlets',
- value: mockOutlets.filter(o => o.status === 'Active').length,
+ value: outlets.filter(o => o.status === 'Active').length,
icon: CheckCircle,
color: 'bg-green-500',
},
{
title: 'Pending Resignations',
- value: mockOutlets.filter(o => o.hasActiveResignation).length,
+ value: outlets.filter(o => o.status === 'Pending Resignation').length,
icon: Clock,
color: 'bg-amber-500',
},
@@ -183,254 +139,338 @@ export function DealerResignationPage({ currentUser, onViewDetails }: DealerResi
return (
- {/* Header */}
-
-
Dealership Resignation Management
-
- Manage resignation requests for your dealerships and studios
-
-
+ {/* Loading Overlay */}
+ {loading && (
+
+
+
+ )}
- {/* Stats */}
-
- {stats.map((stat, index) => {
- const Icon = stat.icon;
- return (
-
-
- {stat.title}
-
-
-
-
-
- {stat.value}
-
-
- );
- })}
-
+ {!loading && (
+ <>
+ {/* Header */}
+
+
Dealership Resignation Management
+
+ Manage resignation requests for your dealerships and studios
+
+
- {/* My Outlets Section */}
-
-
- My Outlets
-
- Select an outlet to request resignation
-
-
-
-
- {mockOutlets.map((outlet) => {
- const OutletIcon = outlet.type === 'Dealership' ? Building2 : Store;
+ {/* Stats */}
+
+ {stats.map((stat, index) => {
+ const Icon = stat.icon;
return (
-
-
-
-
-
-
-
-
{outlet.name}
-
{outlet.code}
-
+
+
+ {stat.title}
+
+
-
- {outlet.status}
-
-
-
-
-
-
-
-
{outlet.address}
-
{outlet.city}, {outlet.state}
-
-
-
-
-
- Established: {new Date(outlet.establishedDate).toLocaleDateString('en-GB', {
- day: '2-digit',
- month: 'short',
- year: 'numeric'
- })}
-
-
-
-
- {outlet.hasActiveResignation ? (
-
-
- Resignation in progress - onViewDetails && outlet.resignationId && onViewDetails(outlet.resignationId)}>View Request
-
-
- ) : (
-
handleOpenResignationDialog(outlet)}
- >
-
- Request Resignation
-
- )}
-
+
+
+ {stat.value}
+
+
);
})}
-
-
- {/* Resignation Request Dialog */}
-