ui and extra inputs fwhile creeating region zone, assigning zm are removed
This commit is contained in:
parent
8ea748fde6
commit
bc2b7faf08
@ -9,6 +9,7 @@ export const API = {
|
||||
|
||||
// Master module routes
|
||||
getRoles: () => client.get('/admin/roles'),
|
||||
createRole: (data: any) => client.post('/admin/roles', data),
|
||||
getPermissions: () => client.get('/admin/permissions'),
|
||||
updateRole: (id: string, data: any) => client.put(`/admin/roles/${id}`, data),
|
||||
|
||||
|
||||
@ -490,7 +490,8 @@ export function UserManagementPage() {
|
||||
|
||||
{/* Geographical Assignments */}
|
||||
<div className="col-span-2 border-t pt-4 mt-2">
|
||||
<h3 className="text-sm font-semibold text-slate-900 mb-4">Geographical Assignments</h3>
|
||||
<h3 className="text-sm font-semibold text-slate-900 mb-1">Geographical Assignments</h3>
|
||||
<p className="text-xs text-slate-500 mb-4">Optional: you can create users without territory mapping and assign later.</p>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="zoneId">Zone (Top Level)</Label>
|
||||
|
||||
@ -174,7 +174,7 @@ export function AllApplicationsPage({ onViewDetails, initialFilter = 'all' }: Al
|
||||
];
|
||||
|
||||
const getStatusColor = (status: ApplicationStatus) => {
|
||||
const colors: Record<ApplicationStatus, string> = {
|
||||
const colors: Partial<Record<ApplicationStatus, string>> = {
|
||||
'Submitted': 'bg-blue-100 text-blue-800',
|
||||
'Questionnaire Pending': 'bg-yellow-100 text-yellow-800',
|
||||
'Questionnaire Completed': 'bg-cyan-100 text-cyan-800',
|
||||
@ -219,12 +219,8 @@ export function AllApplicationsPage({ onViewDetails, initialFilter = 'all' }: Al
|
||||
'Security Details Approved': 'bg-green-100 text-green-800',
|
||||
'Security Details': 'bg-amber-100 text-amber-800',
|
||||
'LOA Issued': 'bg-pink-100 text-pink-800',
|
||||
'EOR Complete': 'bg-violet-100 text-violet-800',
|
||||
'Level 1 Approved': 'bg-green-100 text-green-800',
|
||||
'Level 2 Approved': 'bg-green-100 text-green-800',
|
||||
'Level 3 Approved': 'bg-green-100 text-green-800',
|
||||
};
|
||||
return (statusColors as any)[status] || 'bg-gray-100 text-gray-800';
|
||||
return colors[status] || 'bg-gray-100 text-gray-800';
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -1875,6 +1875,8 @@ export const ApplicationDetails = () => {
|
||||
].includes(application.status);
|
||||
|
||||
const isLoaLocked = application.status === 'LOA Pending' && getDeposit('FIRST_FILL')?.status !== 'Verified';
|
||||
const isSecurityDetailsLocked = ['Security Details', 'Payment Pending'].includes(application.status) &&
|
||||
getDeposit('SECURITY_DEPOSIT')?.status !== 'Verified';
|
||||
const isFinalState = application.status === 'Onboarded' || application.status === 'Rejected';
|
||||
|
||||
// 2. Interview Specific Logic
|
||||
@ -1903,15 +1905,18 @@ export const ApplicationDetails = () => {
|
||||
|
||||
// 5. Final Permission Bits
|
||||
const isDecisionMade = (activeInterviewForUser ? hasMadeInterviewDecision : false) || hasMadeStageDecision;
|
||||
const canApproveReject = !isLoaLocked && !isFinalState && !isDecisionMade && (
|
||||
const canApproveReject = !isFinalState && !isDecisionMade && (
|
||||
(!!activeInterviewForUser && !!hasSubmittedFeedback) ||
|
||||
(isAdminRole && isAdministrativeStage && sequenceMet && (!['EOR In Progress', 'Inauguration', 'Approved'].includes(application.status) || eorProgress === 100))
|
||||
);
|
||||
const canApprove = canApproveReject && !isLoaLocked && !isSecurityDetailsLocked;
|
||||
const canReject = canApproveReject && !isLoaLocked;
|
||||
|
||||
return {
|
||||
canApprove: canApproveReject,
|
||||
canReject: canApproveReject,
|
||||
canApprove,
|
||||
canReject,
|
||||
isLoaLocked,
|
||||
isSecurityDetailsLocked,
|
||||
showDecisionMessage: isDecisionMade && (!isAdministrativeStage || hasMadeStageDecision),
|
||||
canSchedule: ['DD Admin', 'Super Admin', 'DD AM', 'ASM'].includes(currentUser.role) &&
|
||||
!isFinalState &&
|
||||
@ -3643,6 +3648,17 @@ export const ApplicationDetails = () => {
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{permissions.isSecurityDetailsLocked && (
|
||||
<Alert variant="destructive" className="mb-4 bg-amber-50 border-amber-200 text-amber-800">
|
||||
<Lock className="w-4 h-4 text-amber-600" />
|
||||
<AlertTitle className="text-amber-900 font-semibold">Security Details approval locked</AlertTitle>
|
||||
<AlertDescription className="text-amber-800">
|
||||
Finance must verify the <span className="font-medium">Security Deposit</span> before this stage can be approved.
|
||||
You can still use <span className="font-medium">Reject</span> if needed.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{['Security Details', 'Payment Pending'].includes(application.status) && (
|
||||
<Alert className="mb-4 border-sky-200 bg-sky-50/90 text-sky-900">
|
||||
<Info className="h-4 w-4 text-sky-700" />
|
||||
|
||||
@ -21,6 +21,7 @@ import { UserManagementTable } from './MasterPage/UserManagementTable';
|
||||
import { SLAConfiguration } from './MasterPage/SLAConfiguration';
|
||||
import { RolePermissions } from './MasterPage/RolePermissions';
|
||||
import { RoleDialog } from './MasterPage/RoleDialog';
|
||||
import { AddRoleDialog } from './MasterPage/AddRoleDialog';
|
||||
import { EmailTemplates } from './MasterPage/EmailTemplates';
|
||||
import { LocationManagement } from './MasterPage/LocationManagement';
|
||||
import { ASMDialog } from './MasterPage/ASMDialog';
|
||||
@ -40,6 +41,7 @@ export const MasterPage: React.FC = () => {
|
||||
const { fetchInitialData, fetchAreas } = useMasterData();
|
||||
const {
|
||||
asms, zonalManagerMappings, ddLeads,
|
||||
allStates,
|
||||
allDistricts,
|
||||
users,
|
||||
roles,
|
||||
@ -60,9 +62,6 @@ export const MasterPage: React.FC = () => {
|
||||
// Form State (ASM)
|
||||
const [editingASMId, setEditingASMId] = useState<string | null>(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('');
|
||||
@ -74,9 +73,6 @@ export const MasterPage: React.FC = () => {
|
||||
const [showZMDialog, setShowZMDialog] = useState(false);
|
||||
const [editingZMId, setEditingZMId] = useState<string | null>(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 [selectedZMRegions, setSelectedZMRegions] = useState<string[]>([]);
|
||||
@ -85,15 +81,13 @@ export const MasterPage: React.FC = () => {
|
||||
const [showDDLeadDialog, setShowDDLeadDialog] = useState(false);
|
||||
const [editingDDLeadId, setEditingDDLeadId] = useState<string | null>(null);
|
||||
const [ddLeadManagerId, setDdLeadManagerId] = useState('');
|
||||
const [ddLeadName, setDdLeadName] = useState('');
|
||||
const [ddLeadCode, setDdLeadCode] = useState('');
|
||||
const [ddLeadEmployeeId, setDdLeadEmployeeId] = useState('');
|
||||
const [ddLeadStatus, setDdLeadStatus] = useState<'active' | 'inactive'>('active');
|
||||
const [selectedDDLeadZones, setSelectedDDLeadZones] = useState<string[]>([]);
|
||||
|
||||
// Role Management State
|
||||
const [showRoleDialog, setShowRoleDialog] = useState(false);
|
||||
const [editingRole, setEditingRole] = useState<any>(null);
|
||||
const [showAddRoleDialog, setShowAddRoleDialog] = useState(false);
|
||||
|
||||
// Form State (Zone)
|
||||
const [editingZoneId, setEditingZoneId] = useState<string | null>(null);
|
||||
@ -105,7 +99,6 @@ export const MasterPage: React.FC = () => {
|
||||
// Form State (Region)
|
||||
const [editingRegionId, setEditingRegionId] = useState<string | null>(null);
|
||||
const [regionName, setRegionName] = useState('');
|
||||
const [regionCode, setRegionCode] = useState('');
|
||||
const [regionDescription, setRegionDescription] = useState('');
|
||||
const [selectedRegionZone, setSelectedRegionZone] = useState('');
|
||||
const [regionalManagerId, setRegionalManagerId] = useState('');
|
||||
@ -176,7 +169,6 @@ export const MasterPage: React.FC = () => {
|
||||
const payload = {
|
||||
userId: asmManagerId,
|
||||
roleCode: asmRoleCode,
|
||||
asmCode,
|
||||
districts: selectedASMDistricts,
|
||||
status: asmStatus
|
||||
};
|
||||
@ -197,9 +189,6 @@ export const MasterPage: React.FC = () => {
|
||||
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);
|
||||
@ -212,9 +201,6 @@ export const MasterPage: React.FC = () => {
|
||||
const handleEditZM = (zm: any) => {
|
||||
setEditingZMId(zm.id);
|
||||
setZmManagerId(zm.id);
|
||||
setZmName(zm.name);
|
||||
setZmCode(zm.zmCode || zm.code || '');
|
||||
setZmEmployeeId(zm.employeeId || '');
|
||||
setZmStatus(zm.status?.toLowerCase() === 'active' ? 'active' : 'inactive');
|
||||
setSelectedZMZone(zm.zoneId || '');
|
||||
setSelectedZMRegions(zm.assignedRegionIds || []);
|
||||
@ -224,9 +210,6 @@ export const MasterPage: React.FC = () => {
|
||||
const handleEditDDLead = (lead: any) => {
|
||||
setEditingDDLeadId(lead.id);
|
||||
setDdLeadManagerId(lead.id);
|
||||
setDdLeadName(lead.name);
|
||||
setDdLeadCode(lead.leadCode || '');
|
||||
setDdLeadEmployeeId(lead.employeeId || '');
|
||||
setDdLeadStatus(lead.status?.toLowerCase() === 'active' ? 'active' : 'inactive');
|
||||
setSelectedDDLeadZones(lead.assignedZoneIds || []);
|
||||
setShowDDLeadDialog(true);
|
||||
@ -240,7 +223,6 @@ export const MasterPage: React.FC = () => {
|
||||
try {
|
||||
const payload = {
|
||||
userId: zmManagerId,
|
||||
zmCode,
|
||||
zoneId: selectedZMZone,
|
||||
regionIds: selectedZMRegions,
|
||||
status: zmStatus
|
||||
@ -268,7 +250,6 @@ export const MasterPage: React.FC = () => {
|
||||
try {
|
||||
const payload = {
|
||||
userId: ddLeadManagerId,
|
||||
leadCode: ddLeadCode,
|
||||
zoneIds: selectedDDLeadZones,
|
||||
status: ddLeadStatus
|
||||
};
|
||||
@ -316,7 +297,6 @@ export const MasterPage: React.FC = () => {
|
||||
const payload = {
|
||||
...(editingRegionId ? { id: editingRegionId } : {}),
|
||||
name: regionName,
|
||||
code: regionCode,
|
||||
description: regionDescription,
|
||||
parentId: selectedRegionZone,
|
||||
managerId: regionalManagerId,
|
||||
@ -384,11 +364,32 @@ export const MasterPage: React.FC = () => {
|
||||
setShowRoleDialog(true);
|
||||
};
|
||||
|
||||
const handleCreateRole = async (data: { roleCode: string; roleName: string; description?: string }) => {
|
||||
try {
|
||||
const payload = {
|
||||
...data,
|
||||
permissionIds: []
|
||||
};
|
||||
const res = await (masterService as any).createRole(payload);
|
||||
if (res?.success) {
|
||||
toast.success('Role created successfully');
|
||||
fetchInitialData();
|
||||
return;
|
||||
}
|
||||
throw new Error(res?.message || 'Failed to create role');
|
||||
} catch (error: any) {
|
||||
const msg = error?.response?.data?.message || error?.message || 'Failed to create role';
|
||||
toast.error(msg);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditLocation = (loc: any) => {
|
||||
const matchedDistrict = allDistricts.find((d: any) => d.id === loc.districtId);
|
||||
setEditingLocationId(loc.id);
|
||||
setLocationState(loc.stateName || '');
|
||||
setLocationState(matchedDistrict?.stateId || loc.stateId || '');
|
||||
setLocationCity(loc.city || '');
|
||||
setLocationDistrict(loc.name || '');
|
||||
setLocationDistrict(loc.districtId || '');
|
||||
setLocationActiveFrom(loc.openFrom ? new Date(loc.openFrom).toISOString().split('T')[0] : '');
|
||||
setLocationActiveTo(loc.openTo ? new Date(loc.openTo).toISOString().split('T')[0] : '');
|
||||
setLocationStatus(loc.isActive ? 'active' : 'inactive');
|
||||
@ -397,10 +398,23 @@ export const MasterPage: React.FC = () => {
|
||||
|
||||
const handleSaveLocation = async () => {
|
||||
try {
|
||||
if (!locationState) {
|
||||
toast.error('Please select a state');
|
||||
return;
|
||||
}
|
||||
if (!locationDistrict) {
|
||||
toast.error('Please select a district');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedState = allStates.find((s: any) => s.id === locationState);
|
||||
const selectedDistrict = allDistricts.find((d: any) => d.id === locationDistrict);
|
||||
const payload = {
|
||||
id: editingLocationId,
|
||||
stateName: locationState,
|
||||
name: locationDistrict,
|
||||
stateId: locationState,
|
||||
stateName: selectedState?.name || selectedState?.stateName || '',
|
||||
districtId: locationDistrict,
|
||||
name: locationCity || selectedDistrict?.name || 'New Location',
|
||||
city: locationCity,
|
||||
status: locationStatus,
|
||||
openFrom: locationActiveFrom,
|
||||
@ -474,11 +488,10 @@ export const MasterPage: React.FC = () => {
|
||||
<ZoneDetails selectedZone={selectedZone} onAddZone={() => { setEditingZoneId(null); setZoneName(''); setZoneCode(''); setZoneDescription(''); setZonalBusinessHeadId('none'); setShowZoneDialog(true); }}
|
||||
onEditZone={(z) => { setEditingZoneId(z.id); setZoneName(z.name); setZoneCode(z.code); setZoneDescription(z.description); setZonalBusinessHeadId(z.zonalBusinessHead?.id || 'none'); setShowZoneDialog(true); }} />
|
||||
|
||||
<RegionalManagement selectedZone={selectedZone} onAddRegion={() => { setEditingRegionId(null); setRegionName(''); setRegionCode(''); setSelectedRegionZone(selectedZone === 'all' ? '' : selectedZone); setRegionalManagerId(''); setSelectedRegionDistricts([]); setShowRegionDialog(true); }}
|
||||
<RegionalManagement selectedZone={selectedZone} onAddRegion={() => { setEditingRegionId(null); setRegionName(''); 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) || []);
|
||||
@ -488,7 +501,7 @@ export const MasterPage: React.FC = () => {
|
||||
|
||||
<ZMManagement selectedZone={selectedZone}
|
||||
onAddZM={() => {
|
||||
setEditingZMId(null); setZmManagerId(''); setZmName(''); setZmCode(''); setZmEmployeeId('');
|
||||
setEditingZMId(null); setZmManagerId('');
|
||||
setZmStatus('active'); setSelectedZMZone(selectedZone === 'all' ? '' : selectedZone);
|
||||
setSelectedZMRegions([]);
|
||||
setShowZMDialog(true);
|
||||
@ -496,12 +509,12 @@ export const MasterPage: React.FC = () => {
|
||||
onEditZM={handleEditZM}
|
||||
onDeleteZM={() => toast.error('ZM deletion restricted')} />
|
||||
|
||||
<ASMManagement selectedZone={selectedZone} onAddASM={() => { setEditingASMId(null); setAsmManagerId(''); setAsmName(''); setAsmCode(''); setAsmEmployeeId(''); setSelectedASMZone(selectedZone === 'all' ? '' : selectedZone); setSelectedASMRegion(''); setSelectedASMStates([]); setSelectedASMDistricts([]); setShowASMDialog(true); }}
|
||||
<ASMManagement selectedZone={selectedZone} onAddASM={() => { setEditingASMId(null); setAsmManagerId(''); setSelectedASMZone(selectedZone === 'all' ? '' : selectedZone); setSelectedASMRegion(''); setSelectedASMStates([]); setSelectedASMDistricts([]); setShowASMDialog(true); }}
|
||||
onEditASM={handleEditASM} onDeleteASM={() => toast.error('ASM deletion restricted')} />
|
||||
|
||||
<DDLeadManagement selectedZone={selectedZone}
|
||||
onAddLead={() => {
|
||||
setEditingDDLeadId(null); setDdLeadManagerId(''); setDdLeadName(''); setDdLeadCode(''); setDdLeadEmployeeId('');
|
||||
setEditingDDLeadId(null); setDdLeadManagerId('');
|
||||
setDdLeadStatus('active'); setSelectedDDLeadZones([]);
|
||||
setShowDDLeadDialog(true);
|
||||
}}
|
||||
@ -512,7 +525,7 @@ export const MasterPage: React.FC = () => {
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="roles" className="animate-in fade-in duration-300">
|
||||
<RolePermissions onAddRole={() => toast.info('Unified Role Management interface being updated')}
|
||||
<RolePermissions onAddRole={() => setShowAddRoleDialog(true)}
|
||||
onEditRole={handleEditRole} />
|
||||
</TabsContent>
|
||||
|
||||
@ -592,20 +605,14 @@ export const MasterPage: React.FC = () => {
|
||||
|
||||
{/* Main Dialogs */}
|
||||
<ZoneDialog isOpen={showZoneDialog} onOpenChange={setShowZoneDialog} editingZoneId={editingZoneId} zoneName={zoneName} setZoneName={setZoneName} zoneCode={zoneCode} setZoneCode={setZoneCode} zoneDescription={zoneDescription} setZoneDescription={setZoneDescription} zonalBusinessHeadId={zonalBusinessHeadId} setZonalBusinessHeadId={setZonalBusinessHeadId} onSave={handleSaveZone} userAssignedData={users.length > 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} />
|
||||
<RegionDialog isOpen={showRegionDialog} onOpenChange={setShowRegionDialog} editingRegionId={editingRegionId} regionName={regionName} setRegionName={setRegionName} regionCode={regionCode} setRegionCode={setRegionCode} regionDescription={regionDescription} setRegionDescription={setRegionDescription} selectedRegionZone={selectedRegionZone} setSelectedRegionZone={setSelectedRegionZone} regionalManagerId={regionalManagerId} setRegionalManagerId={setRegionalManagerId} selectedRegionStates={selectedRegionDistricts} setSelectedRegionStates={setSelectedRegionDistricts} onSave={handleSaveRegion} userAssignedData={users.length > 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} />
|
||||
<ASMDialog isOpen={showASMDialog} onOpenChange={setShowASMDialog} editingASMId={editingASMId} asmManagerId={asmManagerId} setAsmManagerId={setAsmManagerId} asmName={asmName} setAsmName={setAsmName} asmCode={asmCode} setAsmCode={setAsmCode} asmEmployeeId={asmEmployeeId} setAsmEmployeeId={setAsmEmployeeId} asmStatus={asmStatus} setAsmStatus={setAsmStatus} selectedASMZone={selectedASMZone} setSelectedASMZone={setSelectedASMZone} selectedASMRegion={selectedASMRegion} setSelectedASMRegion={setSelectedASMRegion} selectedASMStates={selectedASMStates} setSelectedASMStates={setSelectedASMStates} selectedASMDistricts={selectedASMDistricts} setSelectedASMDistricts={setSelectedASMDistricts} onSave={handleSaveASM} asmRoleCode={asmRoleCode} setAsmRoleCode={setAsmRoleCode} userAssignedData={users.length > 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={(state) => getDistrictsForSelectedState(state, selectedASMRegion || undefined)} />
|
||||
<RegionDialog isOpen={showRegionDialog} onOpenChange={setShowRegionDialog} editingRegionId={editingRegionId} regionName={regionName} setRegionName={setRegionName} regionDescription={regionDescription} setRegionDescription={setRegionDescription} selectedRegionZone={selectedRegionZone} setSelectedRegionZone={setSelectedRegionZone} regionalManagerId={regionalManagerId} setRegionalManagerId={setRegionalManagerId} selectedRegionStates={selectedRegionDistricts} setSelectedRegionStates={setSelectedRegionDistricts} onSave={handleSaveRegion} userAssignedData={users.length > 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles})) : asms} />
|
||||
<ASMDialog isOpen={showASMDialog} onOpenChange={setShowASMDialog} editingASMId={editingASMId} asmManagerId={asmManagerId} setAsmManagerId={setAsmManagerId} asmStatus={asmStatus} setAsmStatus={setAsmStatus} selectedASMZone={selectedASMZone} setSelectedASMZone={setSelectedASMZone} selectedASMRegion={selectedASMRegion} setSelectedASMRegion={setSelectedASMRegion} selectedASMStates={selectedASMStates} setSelectedASMStates={setSelectedASMStates} selectedASMDistricts={selectedASMDistricts} setSelectedASMDistricts={setSelectedASMDistricts} onSave={handleSaveASM} asmRoleCode={asmRoleCode} setAsmRoleCode={setAsmRoleCode} userAssignedData={users.length > 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={(state) => getDistrictsForSelectedState(state, selectedASMRegion || undefined)} />
|
||||
<ZMDialog
|
||||
isOpen={showZMDialog}
|
||||
onOpenChange={setShowZMDialog}
|
||||
editingZMId={editingZMId}
|
||||
zmManagerId={zmManagerId}
|
||||
setZmManagerId={setZmManagerId}
|
||||
zmName={zmName}
|
||||
setZmName={setZmName}
|
||||
zmCode={zmCode}
|
||||
setZmCode={setZmCode}
|
||||
zmEmployeeId={zmEmployeeId}
|
||||
setZmEmployeeId={setZmEmployeeId}
|
||||
zmStatus={zmStatus}
|
||||
setZmStatus={setZmStatus}
|
||||
selectedZone={selectedZMZone}
|
||||
@ -621,12 +628,6 @@ export const MasterPage: React.FC = () => {
|
||||
editingLeadId={editingDDLeadId}
|
||||
leadManagerId={ddLeadManagerId}
|
||||
setLeadManagerId={setDdLeadManagerId}
|
||||
leadName={ddLeadName}
|
||||
setLeadName={setDdLeadName}
|
||||
leadCode={ddLeadCode}
|
||||
setLeadCode={setDdLeadCode}
|
||||
leadEmployeeId={ddLeadEmployeeId}
|
||||
setLeadEmployeeId={setDdLeadEmployeeId}
|
||||
leadStatus={ddLeadStatus}
|
||||
setLeadStatus={setDdLeadStatus}
|
||||
selectedZones={selectedDDLeadZones}
|
||||
@ -635,8 +636,9 @@ export const MasterPage: React.FC = () => {
|
||||
userAssignedData={users.length > 0 ? users.map(u => ({...u, name: u.fullName || u.name, role: u.role?.roleName, roleCode: u.role?.roleCode, allRoles: u.allRoles, assignedZoneIds: (ddLeads.find(l => l.id === u.id)?.assignedZoneIds || [])})) : asms}
|
||||
/>
|
||||
<TemplateDialog isOpen={showTemplateDialog} onOpenChange={setShowTemplateDialog} editingTemplate={editingTemplate} setEditingTemplate={setEditingTemplate} testDataInput={testDataInput} setTestDataInput={setTestDataInput} previewLoading={previewLoading} handlePreviewTemplate={handlePreviewTemplate} previewContent={previewContent} handleSaveTemplate={handleSaveTemplate} />
|
||||
<LocationDialog isOpen={showLocationDialog} onOpenChange={setShowLocationDialog} editingLocationId={editingLocationId} locationState={locationState} setLocationState={setLocationState} locationDistrict={locationDistrict} setLocationDistrict={setLocationDistrict} locationCity={locationCity} setLocationCity={setLocationCity} locationActiveFrom={locationActiveFrom} setLocationActiveFrom={setLocationActiveFrom} locationActiveTo={locationActiveTo} setLocationActiveTo={setLocationActiveTo} locationStatus={locationStatus} setLocationStatus={setLocationStatus} onSave={handleSaveLocation} />
|
||||
<LocationDialog isOpen={showLocationDialog} onOpenChange={setShowLocationDialog} editingLocationId={editingLocationId} locationState={locationState} setLocationState={setLocationState} locationDistrict={locationDistrict} setLocationDistrict={setLocationDistrict} locationCity={locationCity} setLocationCity={setLocationCity} locationActiveFrom={locationActiveFrom} setLocationActiveFrom={setLocationActiveFrom} locationActiveTo={locationActiveTo} setLocationActiveTo={setLocationActiveTo} locationStatus={locationStatus} setLocationStatus={setLocationStatus} allStates={allStates} allDistricts={allDistricts} onSave={handleSaveLocation} />
|
||||
<RoleDialog isOpen={showRoleDialog} onOpenChange={setShowRoleDialog} role={editingRole} onSave={handleSaveRole} />
|
||||
<AddRoleDialog isOpen={showAddRoleDialog} onOpenChange={setShowAddRoleDialog} onSave={handleCreateRole} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -3,7 +3,6 @@ import { useSelector } from 'react-redux';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||
import { Button } from '../../ui/button';
|
||||
import { Label } from '../../ui/label';
|
||||
import { Input } from '../../ui/input';
|
||||
import { Checkbox } from '../../ui/checkbox';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip';
|
||||
@ -15,12 +14,6 @@ interface ASMDialogProps {
|
||||
editingASMId: string | null;
|
||||
asmManagerId: string;
|
||||
setAsmManagerId: (id: string) => void;
|
||||
asmName: string;
|
||||
setAsmName: (name: string) => void;
|
||||
asmCode: string;
|
||||
setAsmCode: (code: string) => void;
|
||||
asmEmployeeId: string;
|
||||
setAsmEmployeeId: (id: string) => void;
|
||||
asmStatus: 'active' | 'inactive';
|
||||
setAsmStatus: (status: 'active' | 'inactive') => void;
|
||||
selectedASMZone: string;
|
||||
@ -41,7 +34,6 @@ interface ASMDialogProps {
|
||||
|
||||
export const ASMDialog: React.FC<ASMDialogProps> = ({
|
||||
isOpen, onOpenChange, editingASMId, asmManagerId, setAsmManagerId,
|
||||
asmName, setAsmName, asmCode, setAsmCode, asmEmployeeId, setAsmEmployeeId,
|
||||
asmStatus, setAsmStatus, selectedASMZone, setSelectedASMZone,
|
||||
selectedASMRegion, setSelectedASMRegion, selectedASMStates, setSelectedASMStates,
|
||||
selectedASMDistricts, setSelectedASMDistricts, onSave,
|
||||
@ -257,13 +249,7 @@ export const ASMDialog: React.FC<ASMDialogProps> = ({
|
||||
setAsmManagerId(value);
|
||||
const selectedUser = userAssignedData.find(u => u.id === value);
|
||||
if (selectedUser) {
|
||||
setAsmName(selectedUser.name);
|
||||
setAsmEmployeeId(selectedUser.employeeId || '');
|
||||
|
||||
// Extraction logic: Look for managerCode in the territoryProfile matching the current role
|
||||
const roleProfile = (selectedUser.territoryProfile || []).find((t: any) => t.roleCode === asmRoleCode);
|
||||
const existingCode = roleProfile?.managerCode || selectedUser.asmCode || selectedUser.employeeId || '';
|
||||
setAsmCode(existingCode);
|
||||
|
||||
// Extract zone/region from assignments if present
|
||||
if (roleProfile?.zoneId) setSelectedASMZone(roleProfile.zoneId);
|
||||
@ -295,22 +281,6 @@ export const ASMDialog: React.FC<ASMDialogProps> = ({
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>Employee ID</Label>
|
||||
<Input readOnly placeholder="Auto-populated" className="mt-2 bg-slate-100" value={asmEmployeeId} />
|
||||
</div>
|
||||
<div>
|
||||
<Label>ASM Code</Label>
|
||||
<Input placeholder="Enter ASM Code" className="mt-2 text-slate-900" value={asmCode} onChange={(e) => setAsmCode(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Full Name</Label>
|
||||
<Input placeholder="Enter full name" className="mt-2 text-slate-900" value={asmName} onChange={(e) => setAsmName(e.target.value)} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Status</Label>
|
||||
<Select value={asmStatus} onValueChange={(val: 'active' | 'inactive') => setAsmStatus(val)}>
|
||||
|
||||
99
src/components/applications/MasterPage/AddRoleDialog.tsx
Normal file
99
src/components/applications/MasterPage/AddRoleDialog.tsx
Normal file
@ -0,0 +1,99 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||
import { Button } from '../../ui/button';
|
||||
import { Input } from '../../ui/input';
|
||||
import { Label } from '../../ui/label';
|
||||
import { Textarea } from '../../ui/textarea';
|
||||
|
||||
interface AddRoleDialogProps {
|
||||
isOpen: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
onSave: (data: { roleCode: string; roleName: string; description?: string }) => Promise<void>;
|
||||
}
|
||||
|
||||
export const AddRoleDialog: React.FC<AddRoleDialogProps> = ({
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
onSave
|
||||
}) => {
|
||||
const [roleName, setRoleName] = useState('');
|
||||
const [roleCode, setRoleCode] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
setRoleName('');
|
||||
setRoleCode('');
|
||||
setDescription('');
|
||||
setSaving(false);
|
||||
}, [isOpen]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!roleName.trim() || !roleCode.trim()) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
await onSave({
|
||||
roleName: roleName.trim(),
|
||||
roleCode: roleCode.trim(),
|
||||
description: description.trim() || undefined
|
||||
});
|
||||
onOpenChange(false);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Role</DialogTitle>
|
||||
<DialogDescription>Create a new role for Master Configuration.</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="role-name">Role Name</Label>
|
||||
<Input
|
||||
id="role-name"
|
||||
value={roleName}
|
||||
onChange={(e) => setRoleName(e.target.value)}
|
||||
placeholder="e.g. Finance Admin"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="role-code">Role Code</Label>
|
||||
<Input
|
||||
id="role-code"
|
||||
value={roleCode}
|
||||
onChange={(e) => setRoleCode(e.target.value)}
|
||||
placeholder="e.g. FINANCE_ADMIN"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="role-description">Description</Label>
|
||||
<Textarea
|
||||
id="role-description"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
placeholder="Optional"
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="outline" onClick={() => onOpenChange(false)} disabled={saving}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleSubmit} disabled={saving || !roleName.trim() || !roleCode.trim()}>
|
||||
{saving ? 'Saving...' : 'Create Role'}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@ -3,7 +3,6 @@ import { useSelector } from 'react-redux';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||
import { Button } from '../../ui/button';
|
||||
import { Label } from '../../ui/label';
|
||||
import { Input } from '../../ui/input';
|
||||
import { Checkbox } from '../../ui/checkbox';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
|
||||
import { RootState } from '../../../store';
|
||||
@ -14,12 +13,6 @@ interface DDLeadDialogProps {
|
||||
editingLeadId: string | null;
|
||||
leadManagerId: string;
|
||||
setLeadManagerId: (id: string) => void;
|
||||
leadName: string;
|
||||
setLeadName: (name: string) => void;
|
||||
leadCode: string;
|
||||
setLeadCode: (code: string) => void;
|
||||
leadEmployeeId: string;
|
||||
setLeadEmployeeId: (id: string) => void;
|
||||
leadStatus: 'active' | 'inactive';
|
||||
setLeadStatus: (status: 'active' | 'inactive') => void;
|
||||
selectedZones: string[];
|
||||
@ -30,7 +23,6 @@ interface DDLeadDialogProps {
|
||||
|
||||
export const DDLeadDialog: React.FC<DDLeadDialogProps> = ({
|
||||
isOpen, onOpenChange, editingLeadId, leadManagerId, setLeadManagerId,
|
||||
leadName, setLeadName, leadCode, setLeadCode, leadEmployeeId, setLeadEmployeeId,
|
||||
leadStatus, setLeadStatus, selectedZones, setSelectedZones, onSave,
|
||||
userAssignedData
|
||||
}) => {
|
||||
@ -70,10 +62,6 @@ export const DDLeadDialog: React.FC<DDLeadDialogProps> = ({
|
||||
setLeadManagerId(value);
|
||||
const selectedUser = userAssignedData.find(u => u.id === value);
|
||||
if (selectedUser) {
|
||||
setLeadName(selectedUser.name);
|
||||
setLeadEmployeeId(selectedUser.employeeId || '');
|
||||
setLeadCode(selectedUser.leadCode || selectedUser.employeeId || '');
|
||||
|
||||
// If they have existing assigned zones
|
||||
if (selectedUser.assignedZoneIds) {
|
||||
setSelectedZones(selectedUser.assignedZoneIds);
|
||||
@ -124,22 +112,6 @@ export const DDLeadDialog: React.FC<DDLeadDialogProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>Employee ID</Label>
|
||||
<Input readOnly placeholder="Auto-populated" className="mt-2 bg-slate-50 border-slate-200" value={leadEmployeeId} />
|
||||
</div>
|
||||
<div>
|
||||
<Label>Lead Code</Label>
|
||||
<Input placeholder="Enter Lead Code" className="mt-2 text-slate-900 border-slate-200" value={leadCode} onChange={(e) => setLeadCode(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Full Name</Label>
|
||||
<Input placeholder="Enter full name" className="mt-2 text-slate-900 border-slate-200" value={leadName} onChange={(e) => setLeadName(e.target.value)} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Status</Label>
|
||||
<Select value={leadStatus} onValueChange={(val: 'active' | 'inactive') => setLeadStatus(val)}>
|
||||
|
||||
@ -9,9 +9,9 @@ interface LocationDialogProps {
|
||||
isOpen: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
editingLocationId: string | null;
|
||||
locationState: string;
|
||||
locationState: string; // stateId
|
||||
setLocationState: (id: string) => void;
|
||||
locationDistrict: string;
|
||||
locationDistrict: string; // districtId
|
||||
setLocationDistrict: (id: string) => void;
|
||||
locationCity: string;
|
||||
setLocationCity: (city: string) => void;
|
||||
@ -21,6 +21,8 @@ interface LocationDialogProps {
|
||||
setLocationActiveTo: (date: string) => void;
|
||||
locationStatus: string;
|
||||
setLocationStatus: (status: string) => void;
|
||||
allStates: any[];
|
||||
allDistricts: any[];
|
||||
onSave: () => void;
|
||||
}
|
||||
|
||||
@ -28,8 +30,14 @@ export const LocationDialog: React.FC<LocationDialogProps> = ({
|
||||
isOpen, onOpenChange, editingLocationId, locationState, setLocationState,
|
||||
locationDistrict, setLocationDistrict, locationCity, setLocationCity,
|
||||
locationActiveFrom, setLocationActiveFrom,
|
||||
locationActiveTo, setLocationActiveTo, locationStatus, setLocationStatus, onSave
|
||||
locationActiveTo, setLocationActiveTo, locationStatus, setLocationStatus,
|
||||
allStates, allDistricts, onSave
|
||||
}) => {
|
||||
const filteredDistricts = React.useMemo(() => {
|
||||
if (!locationState) return [];
|
||||
return (allDistricts || []).filter((d: any) => d.stateId === locationState);
|
||||
}, [allDistricts, locationState]);
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
||||
<DialogContent>
|
||||
@ -40,12 +48,24 @@ export const LocationDialog: React.FC<LocationDialogProps> = ({
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label className="flex items-center gap-2 text-sm leading-none font-medium text-slate-700">State</Label>
|
||||
<Input
|
||||
placeholder="Enter state name"
|
||||
className="mt-2 text-slate-900 border-slate-200 focus-visible:ring-amber-500/30 focus-visible:border-amber-500"
|
||||
<Select
|
||||
value={locationState}
|
||||
onChange={(e) => setLocationState(e.target.value)}
|
||||
/>
|
||||
onValueChange={(value) => {
|
||||
setLocationState(value);
|
||||
setLocationDistrict('');
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="mt-2 text-slate-900 border-slate-200 focus:ring-amber-500/30 focus:border-amber-500">
|
||||
<SelectValue placeholder="Select state" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{(allStates || []).map((state: any) => (
|
||||
<SelectItem key={state.id} value={state.id}>
|
||||
{state.name || state.stateName}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="flex items-center gap-2 text-sm leading-none font-medium text-slate-700">City</Label>
|
||||
@ -58,12 +78,18 @@ export const LocationDialog: React.FC<LocationDialogProps> = ({
|
||||
</div>
|
||||
<div>
|
||||
<Label className="flex items-center gap-2 text-sm leading-none font-medium text-slate-700">District</Label>
|
||||
<Input
|
||||
placeholder="Enter district name"
|
||||
className="mt-2 text-slate-900 border-slate-200 focus-visible:ring-amber-500/30 focus-visible:border-amber-500"
|
||||
value={locationDistrict}
|
||||
onChange={(e) => setLocationDistrict(e.target.value)}
|
||||
/>
|
||||
<Select value={locationDistrict} onValueChange={setLocationDistrict} disabled={!locationState}>
|
||||
<SelectTrigger className="mt-2 text-slate-900 border-slate-200 focus:ring-amber-500/30 focus:border-amber-500">
|
||||
<SelectValue placeholder={locationState ? 'Select district' : 'Select state first'} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{filteredDistricts.map((district: any) => (
|
||||
<SelectItem key={district.id} value={district.id}>
|
||||
{district.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="border rounded-lg p-4 bg-gradient-to-br from-blue-50 to-cyan-50 border-blue-200">
|
||||
|
||||
@ -16,8 +16,6 @@ interface RegionDialogProps {
|
||||
editingRegionId: string | null;
|
||||
regionName: string;
|
||||
setRegionName: (name: string) => void;
|
||||
regionCode: string;
|
||||
setRegionCode: (code: string) => void;
|
||||
regionDescription: string;
|
||||
setRegionDescription: (desc: string) => void;
|
||||
selectedRegionZone: string;
|
||||
@ -32,7 +30,7 @@ interface RegionDialogProps {
|
||||
|
||||
export const RegionDialog: React.FC<RegionDialogProps> = ({
|
||||
isOpen, onOpenChange, editingRegionId, regionName, setRegionName,
|
||||
regionCode, setRegionCode, regionDescription, setRegionDescription,
|
||||
regionDescription, setRegionDescription,
|
||||
selectedRegionZone, setSelectedRegionZone, regionalManagerId, setRegionalManagerId,
|
||||
selectedRegionStates, setSelectedRegionStates, onSave, userAssignedData
|
||||
}) => {
|
||||
@ -142,17 +140,11 @@ export const RegionDialog: React.FC<RegionDialogProps> = ({
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Region Code & Name */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>Region Code</Label>
|
||||
<Input placeholder="e.g., NZ-R1" className="mt-2 text-slate-900" value={regionCode} onChange={(e) => setRegionCode(e.target.value)} />
|
||||
</div>
|
||||
{/* Region Name */}
|
||||
<div>
|
||||
<Label>Region Name</Label>
|
||||
<Input placeholder="e.g., Delhi NCR Region" className="mt-2 text-slate-900" value={regionName} onChange={(e) => setRegionName(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Zone */}
|
||||
<div>
|
||||
|
||||
@ -3,7 +3,6 @@ import { useSelector } from 'react-redux';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||
import { Button } from '../../ui/button';
|
||||
import { Label } from '../../ui/label';
|
||||
import { Input } from '../../ui/input';
|
||||
import { Checkbox } from '../../ui/checkbox';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
|
||||
import { RootState } from '../../../store';
|
||||
@ -14,12 +13,6 @@ interface ZMDialogProps {
|
||||
editingZMId: string | null;
|
||||
zmManagerId: string;
|
||||
setZmManagerId: (id: string) => void;
|
||||
zmName: string;
|
||||
setZmName: (name: string) => void;
|
||||
zmCode: string;
|
||||
setZmCode: (code: string) => void;
|
||||
zmEmployeeId: string;
|
||||
setZmEmployeeId: (id: string) => void;
|
||||
zmStatus: 'active' | 'inactive';
|
||||
setZmStatus: (status: 'active' | 'inactive') => void;
|
||||
selectedZone: string;
|
||||
@ -32,7 +25,6 @@ interface ZMDialogProps {
|
||||
|
||||
export const ZMDialog: React.FC<ZMDialogProps> = ({
|
||||
isOpen, onOpenChange, editingZMId, zmManagerId, setZmManagerId,
|
||||
zmName, setZmName, zmCode, setZmCode, zmEmployeeId, setZmEmployeeId,
|
||||
zmStatus, setZmStatus, selectedZone, setSelectedZone,
|
||||
selectedRegions, setSelectedRegions, onSave,
|
||||
userAssignedData
|
||||
@ -66,10 +58,6 @@ export const ZMDialog: React.FC<ZMDialogProps> = ({
|
||||
setZmManagerId(value);
|
||||
const selectedUser = userAssignedData.find(u => u.id === value);
|
||||
if (selectedUser) {
|
||||
setZmName(selectedUser.name);
|
||||
setZmEmployeeId(selectedUser.employeeId || '');
|
||||
setZmCode(selectedUser.zmCode || selectedUser.employeeId || '');
|
||||
|
||||
if (selectedUser.zoneId) setSelectedZone(selectedUser.zoneId);
|
||||
if (selectedUser.assignedRegionIds) setSelectedRegions(selectedUser.assignedRegionIds);
|
||||
}
|
||||
@ -92,17 +80,6 @@ export const ZMDialog: React.FC<ZMDialogProps> = ({
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>Employee ID</Label>
|
||||
<Input readOnly className="mt-2 bg-slate-50 border-slate-200" value={zmEmployeeId} />
|
||||
</div>
|
||||
<div>
|
||||
<Label>ZM Code</Label>
|
||||
<Input placeholder="Enter ZM Code" className="mt-2" value={zmCode} onChange={(e) => setZmCode(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>Managed Zone <span className="text-red-500">*</span></Label>
|
||||
<Select value={selectedZone} onValueChange={(value) => {
|
||||
|
||||
@ -31,14 +31,15 @@ export const ZoneDialog: React.FC<ZoneDialogProps> = ({
|
||||
// Always include the currently assigned head to ensure pre-filling works
|
||||
if (zonalBusinessHeadId !== 'none' && u.id === zonalBusinessHeadId) return true;
|
||||
|
||||
const roles = u.allRoles || [];
|
||||
const topLevelRole = (u.roleCode || '').toUpperCase();
|
||||
const roles = (u.allRoles || []).map((r: string) => String(r || '').toUpperCase());
|
||||
const topLevelRole = String(u.roleCode || u.role || '').toUpperCase();
|
||||
|
||||
return topLevelRole === 'ZBH' || roles.some((r: string) => {
|
||||
const roleStr = (r || '').toUpperCase();
|
||||
return topLevelRole === 'ZBH' || topLevelRole.includes('ZONAL BUSINESS HEAD') || roles.some((r: string) => {
|
||||
const roleStr = String(r || '').toUpperCase();
|
||||
return roleStr === 'ZBH' || roleStr === 'ZONE BUSINESS HEAD' || roleStr === 'ZONAL BUSINESS HEAD';
|
||||
});
|
||||
});
|
||||
const dropdownUsers = filteredZBHUsers.length > 0 ? filteredZBHUsers : (userAssignedData || []);
|
||||
|
||||
// PRE-FILLING: When editing an existing zone, find its current ZBH from master data
|
||||
React.useEffect(() => {
|
||||
@ -84,7 +85,7 @@ export const ZoneDialog: React.FC<ZoneDialogProps> = ({
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-60">
|
||||
<SelectItem value="none">None / Unassigned</SelectItem>
|
||||
{filteredZBHUsers.map((user) => (
|
||||
{dropdownUsers.map((user) => (
|
||||
<SelectItem key={user.id} value={user.id}>
|
||||
{user.name} ({user.email})
|
||||
</SelectItem>
|
||||
|
||||
@ -50,14 +50,29 @@ export const useMasterData = () => {
|
||||
const bodyZms = getBody(zmsRes);
|
||||
const bodyDdLeads = getBody(ddLeadsRes);
|
||||
|
||||
const users = (bodyUsers?.users || bodyUsers?.data || []).map((u: any) => ({
|
||||
const users = (bodyUsers?.users || bodyUsers?.data || []).map((u: any) => {
|
||||
const territory = Array.isArray(u.territoryProfile) ? u.territoryProfile : [];
|
||||
const territoryZones = territory
|
||||
.filter((t: any) => String(t.locationType || '').toLowerCase() === 'zone')
|
||||
.map((t: any) => t.locationName || t.zone)
|
||||
.filter(Boolean);
|
||||
const territoryRegions = territory
|
||||
.filter((t: any) => String(t.locationType || '').toLowerCase() === 'region')
|
||||
.map((t: any) => t.locationName || t.region)
|
||||
.filter(Boolean);
|
||||
|
||||
const zones = Array.from(new Set([...(u.allZones || []), ...territoryZones]));
|
||||
const regions = Array.from(new Set([...(u.allRegions || []), ...territoryRegions]));
|
||||
|
||||
return {
|
||||
...u,
|
||||
name: u.fullName || u.name,
|
||||
role: u.role?.roleName || 'System User',
|
||||
zone: u.allZones?.join(', ') || 'Global',
|
||||
region: u.allRegions?.join(', ') || 'Unassigned',
|
||||
role: u.role?.roleName || (Array.isArray(u.allRoles) && u.allRoles.length > 0 ? u.allRoles[0] : 'System User'),
|
||||
zone: zones.length > 0 ? zones.join(', ') : 'Global',
|
||||
region: regions.length > 0 ? regions.join(', ') : 'Unassigned',
|
||||
status: u.isActive !== false ? 'Active' : 'Inactive'
|
||||
}));
|
||||
};
|
||||
});
|
||||
|
||||
const roles = (bodyRoles?.roles || bodyRoles?.data || []).map((r: any) => ({
|
||||
id: r.id, name: r.roleName, permissions: r.permissions?.map((p: any) => p.permissionCode) || [], userCount: r.userCount || 0
|
||||
|
||||
@ -14,6 +14,10 @@ export const masterService = {
|
||||
const response = await API.updateRole(id, data);
|
||||
return response.data;
|
||||
},
|
||||
createRole: async (data: any) => {
|
||||
const response = await (API as any).createRole(data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Zones & Regions
|
||||
getZones: async () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user