Dealer_Onboard_Frontend/src/features/master/components/ASMDialog.tsx

290 lines
13 KiB
TypeScript

import React from 'react';
import { useSelector } from 'react-redux';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { RootState } from '@/store';
interface ASMDialogProps {
isOpen: boolean;
onOpenChange: (open: boolean) => void;
editingASMId: string | null;
asmManagerId: string;
setAsmManagerId: (id: string) => void;
asmStatus: 'active' | 'inactive';
setAsmStatus: (status: 'active' | 'inactive') => void;
selectedASMZone: string;
setSelectedASMZone: (id: string) => void;
selectedASMRegion: string;
setSelectedASMRegion: (id: string) => void;
selectedASMStates: string[];
setSelectedASMStates: (states: string[]) => void;
selectedASMDistricts: string[];
setSelectedASMDistricts: (districts: string[]) => void;
onSave: () => void;
asmRoleCode: 'ASM' | 'DD-AM';
setAsmRoleCode: (role: 'ASM' | 'DD-AM') => void;
userAssignedData: any[];
districtsAssignedToOthers: Record<string, string[]>;
getDistrictsForSelectedState: (state: string) => { id: string; name: string }[];
}
export const ASMDialog: React.FC<ASMDialogProps> = ({
isOpen, onOpenChange, editingASMId, asmManagerId, setAsmManagerId,
asmStatus, setAsmStatus, selectedASMZone, setSelectedASMZone,
selectedASMRegion, setSelectedASMRegion, selectedASMStates, setSelectedASMStates,
selectedASMDistricts, setSelectedASMDistricts, onSave,
asmRoleCode,
userAssignedData, districtsAssignedToOthers, getDistrictsForSelectedState
}) => {
const { zones, regionalOffices } = useSelector((state: RootState) => state.master);
const filteredASMUsers = userAssignedData.filter(u => {
const roles = (u.allRoles || []).map((r: string) => String(r || '').toUpperCase());
const roleCode = String(u.roleCode || '').toUpperCase();
return roles.includes('DD-AM') || roleCode === 'DD-AM';
});
// PRE-FILLING LOGIC: When manager or role changes, pre-select their districts
React.useEffect(() => {
if (asmManagerId && isOpen) {
const manager = userAssignedData.find(u => u.id === asmManagerId);
if (manager && manager.territoryProfile) {
const assignedDistricts = manager.territoryProfile
.filter((t: any) => t.roleCode === asmRoleCode && t.locationType === 'district')
.map((t: any) => t.locationId);
if (assignedDistricts.length > 0) {
setSelectedASMDistricts(assignedDistricts);
}
}
}
}, [asmManagerId, asmRoleCode, isOpen, userAssignedData, setSelectedASMDistricts]);
return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>{editingASMId ? 'Edit' : 'Add'} DD Area Manager</DialogTitle>
<DialogDescription>Configure DD-AM details and district assignment</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div>
<Label>Zone</Label>
<Select value={selectedASMZone} onValueChange={(value) => {
setSelectedASMZone(value);
setSelectedASMRegion('');
setSelectedASMStates([]);
setSelectedASMDistricts([]);
}}>
<SelectTrigger className="mt-2 text-slate-900">
<SelectValue placeholder="Select zone" />
</SelectTrigger>
<SelectContent>
{zones.map((zone) => (
<SelectItem key={zone.id} value={zone.id}>{zone.name}</SelectItem>
))}
</SelectContent>
</Select>
</div>
{selectedASMZone && (
<div className="space-y-4">
<div>
<Label>Regional Office</Label>
<Select value={selectedASMRegion} onValueChange={(value) => {
setSelectedASMRegion(value);
setSelectedASMStates([]);
setSelectedASMDistricts([]);
}}>
<SelectTrigger className="mt-2 text-slate-900">
<SelectValue placeholder="Select regional office" />
</SelectTrigger>
<SelectContent>
{regionalOffices
.filter((office) => office.zoneId === selectedASMZone)
.map((office) => (
<SelectItem key={office.id} value={office.id}>{office.name}</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div>
<Label>Select DD-AM User</Label>
<Select value={asmManagerId} onValueChange={setAsmManagerId}>
<SelectTrigger className="mt-2 text-slate-900">
<SelectValue placeholder="Select DD-AM" />
</SelectTrigger>
<SelectContent className="max-h-64">
{filteredASMUsers.map(user => (
<SelectItem key={user.id} value={user.id}>
{user.name} ({user.employeeId || 'No ID'})
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
)}
{selectedASMRegion && (
<div>
<Label>States Covered</Label>
<div className="mt-2 border rounded-lg p-3 max-h-48 overflow-y-auto bg-slate-50">
{(() => {
const selectedRegion = regionalOffices.find(r => r.id === selectedASMRegion);
const availableStates = (selectedRegion?.states || []).map((s: any) => typeof s === 'string' ? s : s.name);
return availableStates.length > 0 ? (
<div className="space-y-2">
{availableStates.map((state: string) => (
<div key={state} className="flex items-center space-x-2">
<Checkbox
id={`asm-state-${state}`}
checked={selectedASMStates.some(s => s.toLowerCase() === state.toLowerCase())}
onCheckedChange={(checked) => {
if (checked) {
setSelectedASMStates([...selectedASMStates, state]);
} else {
setSelectedASMStates(selectedASMStates.filter(s => s.toLowerCase() !== state.toLowerCase()));
const stateDistricts = getDistrictsForSelectedState(state);
setSelectedASMDistricts(selectedASMDistricts.filter(dId => !stateDistricts.some(sd => sd.id === dId)));
}
}}
/>
<label htmlFor={`asm-state-${state}`} className="text-sm cursor-pointer text-slate-900">
{state}
</label>
</div>
))}
</div>
) : (
<p className="text-sm text-slate-500">No states available for this regional office</p>
);
})()}
</div>
</div>
)}
{selectedASMStates.length > 0 && (
<div>
<Label>Districts/Cities Covered</Label>
<div className="mt-2 border rounded-lg p-3 max-h-64 overflow-y-auto bg-slate-50">
<TooltipProvider>
{selectedASMStates.map((state) => {
const districts = getDistrictsForSelectedState(state);
if (districts.length === 0) return null;
return (
<div key={state} className="mb-4 last:mb-0">
<h4 className="text-sm text-re-red-hover mb-2 pb-1 border-b border-slate-200">{state}</h4>
<div className="space-y-2 ml-2">
{districts.map((district: any) => (
<div key={district.id}>
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center space-x-2 py-0.5">
<Checkbox
id={`asm-district-${district.id}`}
checked={selectedASMDistricts.includes(district.id)}
disabled={!!districtsAssignedToOthers[district.id]}
onCheckedChange={(checked) => {
if (checked) {
setSelectedASMDistricts([...selectedASMDistricts, district.id]);
} else {
setSelectedASMDistricts(selectedASMDistricts.filter(id => id !== district.id));
}
}}
/>
<label
htmlFor={`asm-district-${district.id}`}
className={`text-sm flex items-center gap-1.5 ${districtsAssignedToOthers[district.id] ? "text-slate-400 cursor-not-allowed" : "cursor-pointer text-slate-900"}`}
>
{district.name}
</label>
</div>
</TooltipTrigger>
{districtsAssignedToOthers[district.id] && (
<TooltipContent>
<p>Already managed by: {districtsAssignedToOthers[district.id].join(', ')}</p>
</TooltipContent>
)}
</Tooltip>
</div>
))}
</div>
</div>
);
})}
</TooltipProvider>
</div>
</div>
)}
<div className="border-t pt-4">
<Label>DD Area Manager <span className="text-red-500">*</span></Label>
<Select
value={asmManagerId}
onValueChange={(value) => {
setAsmManagerId(value);
const selectedUser = userAssignedData.find(u => u.id === value);
if (selectedUser) {
const roleProfile = (selectedUser.territoryProfile || []).find((t: any) => t.roleCode === asmRoleCode);
// Extract zone/region from assignments if present
if (roleProfile?.zoneId) setSelectedASMZone(roleProfile.zoneId);
if (roleProfile?.regionId) setSelectedASMRegion(roleProfile.regionId);
setSelectedASMDistricts(selectedUser.areasManaged?.filter((a: any) => a.roleCode === asmRoleCode).map((a: any) => a.id) || []);
setSelectedASMStates(selectedUser.stateNames || []);
}
}}
disabled={!!editingASMId}
>
<SelectTrigger className="mt-2 w-full text-slate-900">
<SelectValue placeholder="Select DD-AM User" />
</SelectTrigger>
<SelectContent className="max-h-60">
{filteredASMUsers.length > 0 ? (
filteredASMUsers.map((user) => (
<SelectItem key={user.id} value={user.id}>
<div className="flex flex-col text-left">
<span className="font-medium text-slate-900">{user.name}</span>
<span className="text-xs text-slate-500">{user.email}</span>
</div>
</SelectItem>
))
) : (
<div className="p-2 text-sm text-slate-500 text-center">No users available</div>
)}
</SelectContent>
</Select>
</div>
<div>
<Label>Status</Label>
<Select value={asmStatus} onValueChange={(val: 'active' | 'inactive') => setAsmStatus(val)}>
<SelectTrigger className="mt-2 text-slate-900">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="active">Active</SelectItem>
<SelectItem value="inactive">Inactive</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex gap-3 pt-4">
<Button variant="outline" className="flex-1" onClick={() => onOpenChange(false)}>Cancel</Button>
<Button className="flex-1 bg-re-red hover:bg-re-red-hover" onClick={onSave}>Save DD-AM</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
};