import { ArrowLeft, Check, RotateCcw, UserPlus, MessageSquare, FileText, Calendar, AlertTriangle, Send, ShieldCheck, Loader2, Upload } from 'lucide-react'; import { Button } from '../ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'; import { Badge } from '../ui/badge'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../ui/dialog'; import { Label } from '../ui/label'; import { Textarea } from '../ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table'; import { Alert, AlertDescription, AlertTitle } from '../ui/alert'; import { useState, useEffect } from 'react'; import { User } from '../../lib/mock-data'; import { toast } from 'sonner'; import { terminationService } from '../../services/termination.service'; import { useNavigate } from 'react-router-dom'; import { API } from '../../api/API'; import { formatDateTime } from '../ui/utils'; import { TERMINATION_DOCUMENT_TYPES, TERMINATION_STAGE_OPTIONS } from '../../lib/offboardingDocumentOptions'; import { DocumentPreviewModal } from '../ui/DocumentPreviewModal'; import { WIDE_DIALOG_CLASS } from '../../lib/dialogStyles'; interface TerminationDetailsProps { terminationId: string; onBack: () => void; currentUser: User | null; } export function TerminationDetails({ terminationId, onBack, currentUser }: TerminationDetailsProps) { const navigate = useNavigate(); const [actionDialog, setActionDialog] = useState<{ open: boolean; type: 'approve' | 'withdrawal' | 'sendback' | 'assign' | 'pushfnf' | null }>({ open: false, type: null }); const [remarks, setRemarks] = useState(''); const [assignToUser, setAssignToUser] = useState(''); const [stageDocumentsDialog, setStageDocumentsDialog] = useState<{ open: boolean; stageName: string; documents: any[] }>({ open: false, stageName: '', documents: [] }); const [isLoading, setIsLoading] = useState(true); const [terminationData, setTerminationData] = useState(null); const [auditLogs, setAuditLogs] = useState([]); const [showSCNDialog, setShowSCNDialog] = useState(false); const [scnFile, setScnFile] = useState(null); const [scnRemarks, setScnRemarks] = useState(''); const [isProcessing, setIsProcessing] = useState(false); const [showFinalizeDialog, setShowFinalizeDialog] = useState(false); const [finalDecision, setFinalDecision] = useState<'Approve' | 'Reject' | 'Reconsider'>('Approve'); const [finalRemarks, setFinalRemarks] = useState(''); const [showUploadDialog, setShowUploadDialog] = useState(false); const [uploadFile, setUploadFile] = useState(null); const [uploadDocType, setUploadDocType] = useState(TERMINATION_DOCUMENT_TYPES[0]); const [uploadStage, setUploadStage] = useState(''); const [previewDocument, setPreviewDocument] = useState(null); const fetchTermination = async () => { try { setIsLoading(true); const data = await terminationService.getTerminationById(terminationId); setTerminationData(data); fetchAuditLogs(); } catch (error) { console.error('Error fetching termination:', error); } finally { setIsLoading(false); } }; const fetchAuditLogs = async () => { try { const response: any = await API.getAuditLogs('termination', terminationId); if (response.data && response.data.success) { setAuditLogs(response.data.data || []); } } catch (error) { console.error('Error fetching audit logs:', error); } }; useEffect(() => { fetchTermination(); }, [terminationId]); if (isLoading) { return (

Loading termination details...

); } const handleIssueSCN = async () => { try { setIsProcessing(true); await terminationService.issueSCN(terminationId, { remarks: scnRemarks }); toast.success('SCN issued successfully'); setShowSCNDialog(false); fetchTermination(); } catch (error) { toast.error('Failed to issue SCN'); } finally { setIsProcessing(false); } }; const handleUploadSCNResponse = async () => { if (!scnFile) return; try { setIsProcessing(true); await terminationService.uploadSCNResponse(terminationId, scnFile, scnRemarks); toast.success('SCN response uploaded'); setShowSCNDialog(false); fetchTermination(); } catch (error) { toast.error('Failed to upload response'); } finally { setIsProcessing(false); } }; const handleFinalize = async () => { try { setIsProcessing(true); await terminationService.finalizeTermination(terminationId, finalDecision, finalRemarks); toast.success(`Termination ${finalDecision.toLowerCase()}ed`); setShowFinalizeDialog(false); fetchTermination(); } catch (error) { toast.error('Failed to finalize termination'); } finally { setIsProcessing(false); } }; const handleUploadDocument = async () => { if (!uploadFile) { toast.error('Please select a file to upload'); return; } try { setIsProcessing(true); const formData = new FormData(); formData.append('file', uploadFile); formData.append('documentType', uploadDocType); if (uploadStage) formData.append('stage', uploadStage); await terminationService.uploadDocument(terminationId, formData); toast.success('Document uploaded successfully'); setShowUploadDialog(false); setUploadFile(null); setUploadDocType(TERMINATION_DOCUMENT_TYPES[0]); setUploadStage(''); fetchTermination(); } catch (error) { toast.error('Failed to upload document'); } finally { setIsProcessing(false); } }; // Check if user can push to F&F (DD Lead and above) const canPushToFnF = currentUser && ['DD Lead', 'DD Head', 'NBH', 'DD Admin', 'Super Admin'].includes(currentUser.role); // Centralized Permissions Utility for Termination logic (Robust Validation) const getTerminationPermissions = () => { if (!terminationData || !currentUser) { return { canApprove: false, canWithdraw: false, canIssueSCN: false, canUploadSCNResponse: false, canFinalize: false, canPushToFnF: false }; } const currentStage = terminationData.currentStage; const status = terminationData.status; const userRole = currentUser.role; const isFinalState = ['Completed', 'Rejected', 'Withdrawn', 'Terminated'].includes(status) || currentStage === 'Terminated'; const isSettlementPhase = status === 'F&F Initiated' || currentStage === 'F&F Initiated' || status === 'Settled' || status === 'FNF_INITIATED'; const isCurrentlyAssigned = userRole === 'Super Admin' || userRole === 'DD Admin' || ( (currentStage === 'RBM Review' && userRole === 'RBM') || (currentStage === 'ZBH Review' && userRole === 'ZBH') || (currentStage === 'DD Lead Review' && userRole === 'DD Lead') || (currentStage === 'Legal Verification' && userRole === 'Legal Admin') || (currentStage === 'NBH Evaluation' && userRole === 'NBH') || (currentStage === 'NBH Final Approval' && userRole === 'NBH') || (currentStage === 'CCO Approval' && userRole === 'CCO') || (currentStage === 'CEO Final Approval' && userRole === 'CEO') || (currentStage === 'Legal - Termination Letter' && userRole === 'Legal Admin') ); return { canApprove: isCurrentlyAssigned && !isFinalState && !isSettlementPhase && !['Show Cause Notice', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval'].includes(currentStage), canIssueSCN: currentStage === 'NBH Evaluation' && (userRole === 'NBH' || userRole === 'Super Admin') && !isFinalState, canUploadSCNResponse: currentStage === 'Show Cause Notice' && (['Legal Admin', 'DD Admin', 'Super Admin'].includes(userRole)) && !isFinalState, canFinalize: ['NBH Final Approval', 'CCO Approval', 'CEO Final Approval'].includes(currentStage) && (userRole === currentStage.replace(' Approval', '') || userRole === 'Super Admin') && !isFinalState, canPushToFnF: canPushToFnF && !isSettlementPhase && !isFinalState, canWithdraw: userRole === 'ASM' && currentStage === 'Request Initiated' && !isFinalState, isFinalState, isSettlementPhase }; }; const permissions = getTerminationPermissions(); // Use actual data from backend const request = terminationData || {}; const stageAliases: Record = { 'Submitted': ['Submitted', 'Request Initiated'], 'RBM Review': ['RBM Review'], 'ZBH Review': ['ZBH Review'], 'DD Lead Review': ['DD Lead Review'], 'Legal Verification': ['Legal Verification'], 'NBH Evaluation': ['NBH Evaluation'], 'Show Cause Notice (SCN)': ['Show Cause Notice', 'Show Cause Notice (SCN)', 'SCN'], 'Personal Hearing': ['Personal Hearing'], 'NBH Final Approval': ['NBH Final Approval'], 'CCO Approval': ['CCO Approval'], 'CEO Final Approval': ['CEO Final Approval'], 'Legal - Termination Letter': ['Legal - Termination Letter'], 'Dealer Terminated': ['Terminated', 'Dealer Terminated'] }; const allUploadedDocs = [ ...(request.documents || []), ...(request.uploadedDocuments || []) ]; const stageDocuments: Record = Object.keys(stageAliases).reduce((acc: Record, stageName) => { const aliases = stageAliases[stageName] || [stageName]; const docs = allUploadedDocs .filter((doc: any) => !doc.stage || aliases.includes(doc.stage)) .map((doc: any) => ({ id: doc.id || `${stageName}-${doc.fileName || doc.name}`, name: doc.fileName || doc.name || 'Document', type: doc.documentType || doc.type || 'Document', uploadDate: doc.uploadDate || doc.createdAt ? formatDateTime(doc.uploadDate || doc.createdAt) : 'N/A', uploader: doc.uploader?.fullName || doc.uploader || '-', path: doc.filePath || doc.path || doc.url })); acc[stageName] = docs; return acc; }, {}); const getLatestStageTimelineEntry = (stageName: string) => { const aliases = stageAliases[stageName] || [stageName]; const entries = (request.timeline || []).filter((entry: any) => aliases.includes(entry.stage) || aliases.includes(entry.targetStage) ); return entries.length > 0 ? entries[entries.length - 1] : null; }; const progressStages = [ { id: 1, name: 'Submitted', status: 'completed', description: 'Termination request initiated', date: '', actionType: '', actionBy: '', remarks: '', feedback: '' }, { id: 2, name: 'RBM Review', status: request.currentStage === 'RBM Review' ? 'active' : ['ZBH Review', 'DD Lead Review', 'Legal Verification', 'NBH Evaluation', 'Show Cause Notice', 'Personal Hearing', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'Regional Business Manager review' }, { id: 3, name: 'ZBH Review', status: request.currentStage === 'ZBH Review' ? 'active' : ['DD Lead Review', 'Legal Verification', 'NBH Evaluation', 'Show Cause Notice', 'Personal Hearing', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'Zonal Business Head evaluation' }, { id: 4, name: 'DD Lead Review', status: request.currentStage === 'DD Lead Review' ? 'active' : ['Legal Verification', 'NBH Evaluation', 'Show Cause Notice', 'Personal Hearing', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'DD Lead validation' }, { id: 5, name: 'Legal Verification', status: request.currentStage === 'Legal Verification' ? 'active' : ['NBH Evaluation', 'Show Cause Notice', 'Personal Hearing', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'Legal team validates termination grounds' }, { id: 6, name: 'NBH Evaluation', status: request.currentStage === 'NBH Evaluation' ? 'active' : ['Show Cause Notice', 'Personal Hearing', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'National Business Head decision' }, { id: 7, name: 'Show Cause Notice (SCN)', status: request.currentStage === 'Show Cause Notice' ? 'active' : ['Personal Hearing', 'NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'SCN sent to dealer, awaiting response' }, { id: 8, name: 'Personal Hearing', status: request.currentStage === 'Personal Hearing' ? 'active' : ['NBH Final Approval', 'CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'Evaluation of SCN response & Hearing' }, { id: 9, name: 'NBH Final Approval', status: request.currentStage === 'NBH Final Approval' ? 'active' : ['CCO Approval', 'CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'NBH final termination decision' }, { id: 10, name: 'CCO Approval', status: request.currentStage === 'CCO Approval' ? 'active' : ['CEO Final Approval', 'Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'Chief Commercial Officer approval' }, { id: 11, name: 'CEO Final Approval', status: request.currentStage === 'CEO Final Approval' ? 'active' : ['Legal - Termination Letter', 'Terminated'].includes(request.currentStage) ? 'completed' : 'pending', description: 'CEO final authorization' }, { id: 12, name: 'Legal - Termination Letter', status: request.currentStage === 'Legal - Termination Letter' ? 'active' : request.currentStage === 'Terminated' ? 'completed' : 'pending', description: 'Legal team issues final termination letter' }, { id: 13, name: 'Dealer Terminated', status: request.currentStage === 'Terminated' ? 'completed' : 'pending', description: 'Dealership termination effective', date: '', actionType: '', actionBy: '', remarks: '', feedback: '' } ]; const handleViewStageDocuments = (stageName: string) => { const documents = stageDocuments[stageName] || []; setStageDocumentsDialog({ open: true, stageName, documents }); }; const handleAction = (type: 'approve' | 'withdrawal' | 'sendback' | 'assign' | 'pushfnf') => { setActionDialog({ open: true, type }); }; const handleSubmitAction = async () => { if (!remarks && actionDialog.type !== 'assign' && actionDialog.type !== 'pushfnf') { toast.error('Please provide remarks'); return; } if (actionDialog.type === 'assign' && !assignToUser) { toast.error('Please select a user'); return; } setIsProcessing(true); try { if (actionDialog.type === 'approve') { await terminationService.updateTerminationStatus(terminationId, 'approve', remarks); } else { // Handle other actions } const actionMessages = { approve: 'Request approved and forwarded', withdrawal: 'Request withdrawn successfully', sendback: 'Request sent back for clarification', assign: `Request assigned to ${assignToUser}`, pushfnf: 'Request pushed to F&F successfully' }; toast.success(actionMessages[actionDialog.type!]); setActionDialog({ open: false, type: null }); setRemarks(''); setAssignToUser(''); fetchTermination(); } catch (error) { toast.error('Failed to perform action'); } finally { setIsProcessing(false); } }; const getSeverityColor = (severity: string) => { switch (severity) { case 'Critical': return 'bg-red-100 text-red-700 border-red-300'; case 'High': return 'bg-orange-100 text-orange-700 border-orange-300'; case 'Medium': return 'bg-yellow-100 text-yellow-700 border-yellow-300'; default: return 'bg-blue-100 text-blue-700 border-blue-300'; } }; const workNotesCount = (request.worknotes || []).length; return (
{/* Warning Alert */} Sensitive Information This is a termination case. All actions are logged and audited. Proceed with caution. {/* Header */}

{request.requestId || terminationId}

{request.dealer?.businessName || request.dealer?.legalName || 'Termination'}

{request.severity} {request.status === 'Settled' ? 'Completed' : (request.status || 'Pending')}
{/* Action Bar - Professional Layout */}
{/* Primary Actions Row */}
Termination Actions: {currentUser?.role !== 'Dealer' && ( <> {!permissions.canFinalize && ( <> {permissions.canApprove && ( )} {permissions.canIssueSCN && ( )} {permissions.canUploadSCNResponse && ( )} {permissions.canApprove && ( )} )} {permissions.canFinalize && ( )} )}
{/* Secondary Actions */}
{permissions.canPushToFnF && ( )} {!permissions.isFinalState && ( )}
{/* Work Notes Button - Independent Section */}
Communication & Notes
{/* Tabs */} Details Progress Documents Audit Trail {/* Details Tab */} Dealer Information

{request.dealer?.dealerCode?.dealerCode || 'N/A'}

{request.dealer?.businessName || 'N/A'}

{request.dealer?.gstNumber || 'N/A'}

{request.dealer?.registeredAddress || request.dealer?.application?.address || 'N/A'}

{request.dealer?.application?.city || 'N/A'}

{request.dealer?.application?.district?.name || 'N/A'}

{request.dealer?.businessName || request.dealershipName}

{request.dealer?.dealerCode?.salesCode || request.salesCode || 'N/A'}

{request.dealer?.dealerCode?.serviceCode || request.serviceCode || 'N/A'}

{request.dealer?.dealerCode?.gmaCode || request.accessoriesCode || 'N/A'}

{request.dealer?.dealerCode?.gmaCode || 'N/A'}

{request.dealer?.dealerCode?.gearCode || 'N/A'}

Operational Details

{request.dealer?.onboardedAt ? formatDateTime(request.dealer.onboardedAt, 'date') : (request.inauguration || 'N/A')}

{request.dealer?.loaDate ? formatDateTime(request.dealer.loaDate, 'date') : 'N/A'}

{request.dealer?.loiDate ? formatDateTime(request.dealer.loiDate, 'date') : 'N/A'}

{request.lastSixMonthsSales}

{request.numberOfDealerships}

{request.numberOfStudios}

{request.dealer?.constitutionType || 'N/A'}

{request.dealer?.application?.businessType || 'N/A'}

{request.typeOfClosure || 'Complete'}

{request.formatCategory || 'N/A'}

{request.dealerScoreCardBand || 'N/A'}

Termination Details

{request.category}

{request.subCategory || 'N/A'}

{request.reason}

{request.severity}

{request.initiator?.fullName || 'System'}

{formatDateTime(request.createdAt)}

{/* Progress Tab */} Termination Progress Timeline Track the termination request approval process
{progressStages.map((stage, index) => { const documentCount = stageDocuments[stage.name]?.length || 0; const timelineEntry = getLatestStageTimelineEntry(stage.name); return (
{stage.status === 'completed' ? ( ) : stage.status === 'active' ? ( ) : ( {stage.id} )}
{index < progressStages.length - 1 && (
)}

{stage.name}

{documentCount > 0 && ( )}
{(timelineEntry?.timestamp || stage.date) && (
{formatDateTime(timelineEntry?.timestamp || stage.date)}
)}

{stage.description}

{timelineEntry && (
{timelineEntry.action || 'Updated'} by {timelineEntry.user || 'System'}

{timelineEntry.remarks || 'No remarks provided.'}

)}
); })}
{/* Documents Tab */}
Documents View and manage termination case documents
Document Name Type Upload Date Uploader Actions {(() => { const allDocs = [ ...(request.documents || []), ...(request.uploadedDocuments || []) ]; if (allDocs.length === 0) return ( No documents found ); return allDocs.map((doc: any, index: number) => (
{doc.name || doc.fileName}
{doc.documentType || doc.type || 'Document'} {formatDateTime(doc.uploadDate || doc.createdAt)} {doc.uploader?.fullName || doc.uploader || '-'}
)); })()}
{/* Audit Trail Tab */} Audit Trail Complete history of actions on this termination case
{auditLogs.length > 0 ? ( auditLogs.map((log: any, index: number) => (

{log.description || log.action}

{formatDateTime(log.timestamp || log.createdAt)}
{log.actor?.name || log.userName || 'System'}
{(log.remarks || log.newData?.remarks || log.details?.remarks) && (
{log.remarks || log.newData?.remarks || log.details?.remarks}
)}
)) ) : (

No activity logs found for this case.

)}
{/* Action Dialogs */} setActionDialog({ open, type: null })}> {actionDialog.type === 'approve' && 'Approve Termination Request'} {actionDialog.type === 'withdrawal' && 'Withdraw Termination Request'} {actionDialog.type === 'sendback' && 'Send Back for Clarification'} {actionDialog.type === 'assign' && 'Assign to User'} {actionDialog.type === 'pushfnf' && 'Push to Full & Final Settlement'} {actionDialog.type === 'assign' ? 'Select a user to assign this request to' : actionDialog.type === 'pushfnf' ? 'This will move the termination case to F&F for dues clearance' : 'Please provide remarks for this action' }
{actionDialog.type === 'assign' ? (
) : actionDialog.type === 'pushfnf' ? (