import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { useSelector } from 'react-redux'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'; import { Globe, Shield, Clock, Mail, MapPin, SlidersHorizontal } from 'lucide-react'; import { Badge } from '../ui/badge'; import { toast } from 'sonner'; // Services & Hooks import { masterService } from '../../services/master.service'; import { useMasterData } from '../../hooks/useMasterData'; // Sub-components import { ZonesOverview } from './MasterPage/ZonesOverview'; import { ZoneDetails } from './MasterPage/ZoneDetails'; import { RegionalManagement } from './MasterPage/RegionalManagement'; import { ASMManagement } from './MasterPage/ASMManagement'; import { ZMManagement } from './MasterPage/ZMManagement'; import { UserManagementTable } from './MasterPage/UserManagementTable'; import { SLAConfiguration } from './MasterPage/SLAConfiguration'; import { RolePermissions } from './MasterPage/RolePermissions'; import { EmailTemplates } from './MasterPage/EmailTemplates'; import { LocationManagement } from './MasterPage/LocationManagement'; import { ASMDialog } from './MasterPage/ASMDialog'; import { ZMDialog } from './MasterPage/ZMDialog'; import { ZoneDialog } from './MasterPage/ZoneDialog'; import { RegionDialog } from './MasterPage/RegionDialog'; import { TemplateDialog } from './MasterPage/TemplateDialog'; import { LocationDialog } from './MasterPage/LocationDialog'; import { ApprovalPoliciesPage } from '../admin/ApprovalPoliciesPage'; import { RootState } from '../../store'; export const MasterPage: React.FC = () => { const { fetchInitialData } = useMasterData(); const { asms, zonalManagerMappings, allDistricts, users, loading } = useSelector((state: RootState) => state.master); // Tab & Selection State const [activeTab, setActiveTab] = useState('hierarchy'); const [selectedZone, setSelectedZone] = useState('all'); // Dialog Visibility const [showASMDialog, setShowASMDialog] = useState(false); const [showZoneDialog, setShowZoneDialog] = useState(false); const [showRegionDialog, setShowRegionDialog] = useState(false); const [showTemplateDialog, setShowTemplateDialog] = useState(false); const [showLocationDialog, setShowLocationDialog] = useState(false); // Form State (ASM) const [editingASMId, setEditingASMId] = useState(null); const [asmManagerId, setAsmManagerId] = useState(''); const [asmName, setAsmName] = useState(''); const [asmCode, setAsmCode] = useState(''); const [asmEmployeeId, setAsmEmployeeId] = useState(''); const [asmStatus, setAsmStatus] = useState<'active' | 'inactive'>('active'); const [selectedASMZone, setSelectedASMZone] = useState(''); const [selectedASMRegion, setSelectedASMRegion] = useState(''); const [selectedASMStates, setSelectedASMStates] = useState([]); const [selectedASMDistricts, setSelectedASMDistricts] = useState([]); // ZM Management State const [showZMDialog, setShowZMDialog] = useState(false); const [editingZMId, setEditingZMId] = useState(null); const [zmManagerId, setZmManagerId] = useState(''); const [zmName, setZmName] = useState(''); const [zmCode, setZmCode] = useState(''); const [zmEmployeeId, setZmEmployeeId] = useState(''); const [zmStatus, setZmStatus] = useState<'active' | 'inactive'>('active'); const [selectedZMZone, setSelectedZMZone] = useState(''); const [selectedZMStates, setSelectedZMStates] = useState([]); const [selectedZMDistricts, setSelectedZMDistricts] = useState([]); // Form State (Zone) const [editingZoneId, setEditingZoneId] = useState(null); const [zoneName, setZoneName] = useState(''); const [zoneCode, setZoneCode] = useState(''); const [zoneDescription, setZoneDescription] = useState(''); const [zonalBusinessHeadId, setZonalBusinessHeadId] = useState(''); // Form State (Region) const [editingRegionId, setEditingRegionId] = useState(null); const [regionName, setRegionName] = useState(''); const [regionCode, setRegionCode] = useState(''); const [regionDescription, setRegionDescription] = useState(''); const [selectedRegionZone, setSelectedRegionZone] = useState(''); const [regionalManagerId, setRegionalManagerId] = useState(''); const [selectedRegionDistricts, setSelectedRegionDistricts] = useState([]); // Form State (Template) const [editingTemplate, setEditingTemplate] = useState(null); const [testDataInput, setTestDataInput] = useState('{"applicant_name": "John Doe"}'); const [previewLoading, setPreviewLoading] = useState(false); const [previewContent, setPreviewContent] = useState(null); // Form State (Location) const [editingLocationId] = useState(null); const [locationState, setLocationState] = useState(''); const [locationDistrict, setLocationDistrict] = useState(''); const [locationCity, setLocationCity] = useState(''); const [locationPincode, setLocationPincode] = useState(''); const [locationActiveFrom, setLocationActiveFrom] = useState(''); const [locationActiveTo, setLocationActiveTo] = useState(''); const [locationStatus, setLocationStatus] = useState('active'); // Initial Load useEffect(() => { fetchInitialData(); }, [fetchInitialData]); // Shared Data Helpers const districtsAssignedToOthers = useMemo(() => { const map: Record = {}; [...asms, ...zonalManagerMappings].forEach(m => { const dists = (m as any).areasManaged || (m as any).districts || []; dists.forEach((d: any) => { const id = typeof d === 'string' ? d : d.id; if (!map[id]) map[id] = []; if (!map[id].includes(m.name)) map[id].push(m.name); }); }); return map; }, [asms, zonalManagerMappings]); const getDistrictsForSelectedState = useCallback((stateName: string) => { return allDistricts .filter(d => d.stateName?.toUpperCase() === stateName?.toUpperCase()) .map(d => ({ id: d.id, name: d.name })); }, [allDistricts]); // Handlers const handleSaveASM = async () => { if (!asmManagerId) { toast.error('Please select an ASM user'); return; } try { const payload = { userId: asmManagerId, asmCode, districts: selectedASMDistricts, status: asmStatus }; const res = await masterService.saveASM(payload) as any; if (res.success) { toast.success(`ASM ${editingASMId ? 'updated' : 'assigned'} successfully`); setShowASMDialog(false); fetchInitialData(); } } catch (error) { toast.error('Failed to save ASM'); } }; const handleEditASM = (asm: any) => { setEditingASMId(asm.id); setAsmManagerId(asm.id); setAsmName(asm.name); setAsmCode(asm.asmCode); setAsmEmployeeId(asm.employeeId); setAsmStatus(asm.status.toLowerCase() as 'active' | 'inactive'); setSelectedASMZone(asm.zoneId); setSelectedASMRegion(asm.regionId); setSelectedASMStates(asm.stateNames || []); setSelectedASMDistricts(asm.areasManaged?.map((a: any) => a.id) || []); setShowASMDialog(true); }; const handleEditZM = (zm: any) => { setEditingZMId(zm.id); setZmManagerId(zm.id); setZmName(zm.name); setZmCode(zm.code === 'N/A' ? '' : zm.code); setZmEmployeeId(zm.code === 'N/A' ? '' : zm.code); setZmStatus(zm.status.toLowerCase() as 'active' | 'inactive'); setSelectedZMZone(zm.zoneId || ''); setSelectedZMStates(zm.stateNames || []); setSelectedZMDistricts(zm.districts?.map((d: any) => d.id) || []); setShowZMDialog(true); }; const handleSaveZM = async () => { if (!zmManagerId || !selectedZMZone) { toast.error('Manager and Zone are required'); return; } try { const payload = { userId: zmManagerId, roleCode: 'DD-ZM', zmCode, districts: selectedZMDistricts, status: zmStatus, locationId: selectedZMZone // ZM primary location is the zone }; // Use the generic saveASM method which I generalized on the backend const res = await masterService.saveASM(payload) as any; if (res.success) { toast.success(`Zonal Manager ${editingZMId ? 'updated' : 'assigned'} successfully`); setShowZMDialog(false); fetchInitialData(); } } catch (error) { toast.error('Failed to save Zonal Manager'); } }; const handleSaveZone = async () => { try { const payload = { id: editingZoneId, name: zoneName, code: zoneCode, description: zoneDescription, managerId: zonalBusinessHeadId }; const res = await masterService.saveZone(payload) as any; if (res.success) { toast.success('Zone saved successfully'); setShowZoneDialog(false); fetchInitialData(); } } catch (error) { toast.error('Error saving zone'); } }; const handleSaveRegion = async () => { try { const payload = { name: regionName, code: regionCode, description: regionDescription, parentId: selectedRegionZone, managerId: regionalManagerId, districts: selectedRegionDistricts, status: 'Active' }; const res = await masterService.saveRegion(payload) as any; if (res.success) { toast.success('Region saved successfully'); setShowRegionDialog(false); fetchInitialData(); } } catch (error) { toast.error('Error saving region'); } }; const handleSaveTemplate = async () => { try { const res = await (editingTemplate?.id ? masterService.updateEmailTemplate(editingTemplate.id, editingTemplate) : masterService.createEmailTemplate(editingTemplate)) as any; if (res.success) { toast.success('Template saved'); setShowTemplateDialog(false); fetchInitialData(); } } catch (error) { toast.error('Error saving template'); } }; const handlePreviewTemplate = async () => { setPreviewLoading(true); try { const res = await masterService.previewEmailTemplate({ template: editingTemplate, testData: JSON.parse(testDataInput) }) as any; if (res.success) setPreviewContent(res.data); } catch (error) { toast.error('Preview failed'); } finally { setPreviewLoading(false); } }; const handleSaveLocation = async () => { try { const payload = { id: editingLocationId, stateId: locationState, districtId: locationDistrict, city: locationCity, pincode: locationPincode, status: locationStatus, activeFrom: locationActiveFrom, activeTo: locationActiveTo }; const res = await (editingLocationId ? masterService.updateArea(editingLocationId, payload) : masterService.createArea(payload)) as any; if (res.success) { toast.success('Location saved'); setShowLocationDialog(false); fetchInitialData(); } } catch (error) { toast.error('Error saving location'); } }; return (

Master Configuration

Centralized governance for locations, roles, and operational policies

Admin Control Panel
{loading ? (

Synchronizing Global Settings...

) : ( Organisation Roles SLA Config Emails Locations Approvals setSelectedZone(selectedZone === id ? 'all' : id)} /> { setEditingZoneId(null); setZoneName(''); setZoneCode(''); setZoneDescription(''); setZonalBusinessHeadId(''); setShowZoneDialog(true); }} onEditZone={(z) => { setEditingZoneId(z.id); setZoneName(z.name); setZoneCode(z.code); setZoneDescription(z.description); setZonalBusinessHeadId(z.zonalBusinessHead?.id || ''); setShowZoneDialog(true); }} /> { setEditingRegionId(null); setRegionName(''); setRegionCode(''); setSelectedRegionZone(selectedZone === 'all' ? '' : selectedZone); setRegionalManagerId(''); setSelectedRegionDistricts([]); setShowRegionDialog(true); }} onEditRegion={(r) => { setEditingRegionId(r.id); setRegionName(r.name); setRegionCode(r.code); setSelectedRegionZone(r.zoneId); setRegionalManagerId(r.regionalManager?.id || ''); setSelectedRegionDistricts(r.districts?.map((d: any) => d.id) || []); setShowRegionDialog(true); }} onDeleteRegion={() => toast.error('Regional office deletion is restricted via portal')} /> { setEditingZMId(null); setZmManagerId(''); setZmName(''); setZmCode(''); setZmEmployeeId(''); setZmStatus('active'); setSelectedZMZone(selectedZone === 'all' ? '' : selectedZone); setSelectedZMStates([]); setSelectedZMDistricts([]); setShowZMDialog(true); }} onEditZM={handleEditZM} onDeleteZM={() => toast.error('ZM deletion restricted')} /> { setEditingASMId(null); setAsmManagerId(''); setAsmName(''); setAsmCode(''); setAsmEmployeeId(''); setSelectedASMZone(selectedZone === 'all' ? '' : selectedZone); setSelectedASMRegion(''); setSelectedASMStates([]); setSelectedASMDistricts([]); setShowASMDialog(true); }} onEditASM={handleEditASM} onDeleteASM={() => toast.error('ASM deletion restricted')} /> 0 ? users : asms} /> toast.info('Unified Role Management interface being updated')} onEditRole={() => toast.info('Unified Role Management interface being updated')} /> toast.info('SLA Matrix Configuration interface being updated')} /> setShowTemplateDialog(true)} onEditTemplate={() => toast.info('Template Editor being updated')} onDeleteTemplate={() => toast.error('Delete Template restricted')} /> setShowLocationDialog(true)} onEditLocation={() => toast.info('Location Editor being updated')} onDeleteLocation={() => toast.error('Delete Location restricted')} /> )} {/* Main Dialogs */} 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} /> 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} /> 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} districtsAssignedToOthers={districtsAssignedToOthers} getDistrictsForSelectedState={getDistrictsForSelectedState} /> 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} districtsAssignedToOthers={districtsAssignedToOthers} getDistrictsForSelectedState={getDistrictsForSelectedState} />
); }; // No default export as App.tsx expects named export MasterPage