From c78d97fd313929232d9bc95ee52c3d18b4e2ea18 Mon Sep 17 00:00:00 2001 From: laxmanhalaki Date: Thu, 9 Apr 2026 09:59:37 +0530 Subject: [PATCH] workflow test file added and enhanncing the status transition --- .../applications/ApplicationDetails.tsx | 328 +++++++----------- .../applications/FDDApplicationDetails.tsx | 177 +++++----- src/lib/mock-data.ts | 12 + 3 files changed, 239 insertions(+), 278 deletions(-) diff --git a/src/components/applications/ApplicationDetails.tsx b/src/components/applications/ApplicationDetails.tsx index 3fdeddd..5887865 100644 --- a/src/components/applications/ApplicationDetails.tsx +++ b/src/components/applications/ApplicationDetails.tsx @@ -49,6 +49,7 @@ import { Loader2, Info, ShieldAlert, + CheckCircle2, } from 'lucide-react'; import { Progress } from '../ui/progress'; import { Textarea } from '../ui/textarea'; @@ -1018,6 +1019,10 @@ export const ApplicationDetails = () => { return (documents || []).some(d => d.documentType === docType); }; + const isInterviewScheduled = (level: number | string) => { + return (interviews || []).some(i => (i.level === level || i.level === level.toString()) && (i.status?.toLowerCase() === 'scheduled')); + }; + const getStageStatus = (stageName: string, fallbackLogic: () => ProcessStage['status']): ProcessStage['status'] => { const backendStage = (application.progressTracking || []).find((ps: any) => ps.stageName === stageName); if (backendStage) { @@ -1042,7 +1047,7 @@ export const ApplicationDetails = () => { id: 2, name: 'Questionnaire', status: getStageStatus('Questionnaire', () => - ['Questionnaire Completed', 'Shortlisted', 'Level 1 Interview Pending', 'Level 1 Approved', 'Level 2 Interview Pending', 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : + ['Questionnaire Completed', 'Shortlisted', 'Level 1 Interview Pending', 'Level 1 Approved', 'Level 2 Interview Pending', 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Questionnaire Pending' ? 'active' : 'pending' ), date: application.questionnaireDate, @@ -1052,7 +1057,7 @@ export const ApplicationDetails = () => { { id: 3, name: 'Shortlist', - status: getStageStatus('Shortlist', () => ['Shortlisted', 'Level 1 Interview Pending', 'Level 1 Approved', 'Level 2 Interview Pending', 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Rejected', 'Onboarded'].includes(application.status) ? 'completed' : 'pending'), + status: getStageStatus('Shortlist', () => ['Shortlisted', 'Level 1 Interview Pending', 'Level 1 Approved', 'Level 2 Interview Pending', 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Rejected', 'Onboarded'].includes(application.status) ? 'completed' : 'pending'), date: application.shortlistDate, description: 'Application shortlisted by DD', evaluators: Array.from(new Set((application.participants || []) @@ -1064,16 +1069,14 @@ export const ApplicationDetails = () => { { id: 4, name: '1st Level Interview', - status: getStageStatus('1st Level Interview', () => ['Level 1 Approved', 'Level 2 Interview Pending', 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Level 1 Interview Pending' ? 'active' : application.status === 'Rejected' && application.progress >= 40 ? 'completed' : 'pending'), + status: getStageStatus('1st Level Interview', () => + ['Level 1 Approved', 'Level 2 Interview Pending', 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : + (application.status === 'Level 1 Interview Pending' && isInterviewScheduled(1)) ? 'active' : 'pending' + ), date: application.level1InterviewDate, description: 'DD-ZM + RBM evaluation', evaluators: Array.from(new Set((application.participants || []) - .filter((p: any) => - p.metadata?.interviewLevel === 1 || - p.metadata?.interviewLevel === '1' || - p.metadata?.allAssignments?.includes(1) || - p.metadata?.allAssignments?.includes('1') - ) + .filter((p: any) => p.metadata?.interviewLevel === 1 || p.metadata?.interviewLevel === '1' || p.metadata?.allAssignments?.includes(1)) .map((p: any) => `${p.user?.name} (${p.user?.role})`) )), documentsUploaded: 1 @@ -1081,16 +1084,14 @@ export const ApplicationDetails = () => { { id: 5, name: '2nd Level Interview', - status: getStageStatus('2nd Level Interview', () => ['Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Level 2 Interview Pending' ? 'active' : application.status === 'Rejected' && application.progress >= 55 ? 'completed' : 'pending'), + status: getStageStatus('2nd Level Interview', () => + ['Level 2 Approved', 'Level 2 Recommended', 'Level 3 Interview Pending', 'Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : + (application.status === 'Level 2 Interview Pending' && isInterviewScheduled(2)) ? 'active' : 'pending' + ), date: application.level2InterviewDate, description: 'DD Lead + ZBH evaluation', evaluators: Array.from(new Set((application.participants || []) - .filter((p: any) => - p.metadata?.interviewLevel === 2 || - p.metadata?.interviewLevel === '2' || - p.metadata?.allAssignments?.includes(2) || - p.metadata?.allAssignments?.includes('2') - ) + .filter((p: any) => p.metadata?.interviewLevel === 2 || p.metadata?.interviewLevel === '2' || p.metadata?.allAssignments?.includes(2)) .map((p: any) => `${p.user?.name} (${p.user?.role})`) )), documentsUploaded: 1 @@ -1098,16 +1099,14 @@ export const ApplicationDetails = () => { { id: 6, name: '3rd Level Interview', - status: getStageStatus('3rd Level Interview', () => ['Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Level 3 Interview Pending' ? 'active' : application.status === 'Rejected' && application.progress >= 70 ? 'completed' : 'pending'), + status: getStageStatus('3rd Level Interview', () => + ['Level 3 Approved', 'FDD Verification', 'LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : + (application.status === 'Level 3 Interview Pending' && isInterviewScheduled(3)) ? 'active' : 'pending' + ), date: application.level3InterviewDate, description: 'NBH + DD Head evaluation', evaluators: Array.from(new Set((application.participants || []) - .filter((p: any) => - p.metadata?.interviewLevel === 3 || - p.metadata?.interviewLevel === '3' || - p.metadata?.allAssignments?.includes(3) || - p.metadata?.allAssignments?.includes('3') - ) + .filter((p: any) => p.metadata?.interviewLevel === 3 || p.metadata?.interviewLevel === '3' || p.metadata?.allAssignments?.includes(3)) .map((p: any) => `${p.user?.name} (${p.user?.role})`) )), documentsUploaded: 2 @@ -1115,7 +1114,7 @@ export const ApplicationDetails = () => { { id: 7, name: 'FDD', - status: getStageStatus('FDD', () => ['LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'FDD Verification' ? 'active' : 'pending'), + status: getStageStatus('FDD', () => ['LOI In Progress', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'FDD Verification' ? 'active' : 'pending'), date: application.fddDate, description: 'Financial Due Diligence', documentsUploaded: 5 @@ -1123,14 +1122,11 @@ export const ApplicationDetails = () => { { id: 8, name: 'LOI Approval', - status: getStageStatus('LOI Approval', () => ['Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'LOI In Progress' ? 'active' : 'pending'), + status: getStageStatus('LOI Approval', () => ['Payment Pending', 'LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'LOI In Progress' ? 'active' : 'pending'), date: application.loiApprovalDate, description: 'Letter of Intent approval', evaluators: Array.from(new Set((application.participants || []) - .filter((p: any) => - p.metadata?.stageCode === 'LOI_APPROVAL' || - p.metadata?.allAssignments?.includes('LOI_APPROVAL') - ) + .filter((p: any) => p.metadata?.stageCode === 'LOI_APPROVAL' || p.metadata?.allAssignments?.includes('LOI_APPROVAL')) .map((p: any) => `${p.user?.name} (${p.user?.role})`) )), documentsUploaded: 1 @@ -1138,7 +1134,7 @@ export const ApplicationDetails = () => { { id: 9, name: 'Security Details', - status: getStageStatus('Security Details', () => ['LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Payment Pending' ? 'active' : 'pending'), + status: getStageStatus('Security Details', () => ['LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Payment Pending' ? 'active' : 'pending'), date: application.securityDetailsDate, description: 'Security verification', documentsUploaded: 3 @@ -1146,7 +1142,7 @@ export const ApplicationDetails = () => { { id: 10, name: 'LOI Issue', - status: getStageStatus('LOI Issue', () => ['LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : 'pending'), + status: getStageStatus('LOI Issue', () => ['LOI Issued', 'Statutory LOI Ack', 'Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : 'pending'), date: application.loiIssueDate, description: 'Letter of Intent issued', documentsUploaded: 1 @@ -1154,10 +1150,9 @@ export const ApplicationDetails = () => { { id: 11, name: 'Dealer Code Generation', - status: getStageStatus('Dealer Code Generation', () => (application.dealerCode || ['Dealer Code Generation', 'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion', 'Statutory GST', 'Statutory PAN', 'Statutory NODAL', 'Statutory NODAL', 'Statutory Check', 'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status)) ? 'completed' : 'pending'), + status: getStageStatus('Dealer Code Generation', () => (application.dealerCode || ['Dealer Code Generation', 'Architecture Work', 'Statutory Work', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status)) ? 'completed' : 'pending'), date: application.dealerCodeDate, description: 'Dealer code generated and assigned', - documentsUploaded: 0, isParallel: true, branches: [ { @@ -1166,27 +1161,21 @@ export const ApplicationDetails = () => { stages: [ { id: '11a-1', - name: 'Assigned to Architecture Team', - status: application.architectureAssignedTo || ['Architecture Document Upload', 'Architecture Team Completion', 'Statutory GST', 'Statutory PAN', 'Statutory Nodal', 'Statutory Check', 'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) || application.architectureStatus === 'COMPLETED' || isDocumentUploaded('Architecture Assignment Document') ? 'completed' : application.status === 'Architecture Team Assigned' ? 'active' : 'pending', - date: application.architectureAssignedDate, - description: 'Assigned to architecture team for site planning', - documentsUploaded: 0 + name: 'Architecture Assignment', + status: application.architectureAssignedTo ? 'completed' : application.status === 'Architecture Team Assigned' ? 'active' : 'pending', + description: 'Assigned to architecture team' }, { id: '11a-2', - name: 'Architectural Document Upload', - status: isDocumentUploaded('Architecture Blueprint') || isDocumentUploaded('Site Plan') || ['Architecture Team Completion', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) || application.architectureStatus === 'COMPLETED' ? 'completed' : (application.architectureAssignedTo || application.status === 'Architecture Document Upload' || application.architectureStatus === 'IN_PROGRESS') ? 'active' : 'pending', - date: application.architectureDocumentDate, - description: 'Architectural documents and blueprints uploaded', - documentsUploaded: (documents || []).filter(d => ['Architecture Blueprint', 'Site Plan'].includes(d.documentType)).length + name: 'Site Plan Blueprint', + status: isDocumentUploaded('Architecture Blueprint') ? 'completed' : application.architectureAssignedTo ? 'active' : 'pending', + description: 'Blueprints and site plans' }, { id: '11a-3', - name: 'Architecture Team Completion', - status: ['LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) || application.architectureStatus === 'COMPLETED' || isDocumentUploaded('Architecture Completion Certificate') ? 'completed' : application.status === 'Architecture Team Completion' ? 'active' : 'pending', - date: application.architectureCompletionDate, - description: 'Architecture team work completed', - documentsUploaded: 0 + name: 'Architecture Work', + status: application.architectureStatus === 'COMPLETED' ? 'completed' : (application.architectureStatus === 'IN_PROGRESS' || isDocumentUploaded('Architecture Blueprint')) ? 'active' : 'pending', + description: 'Final architecture approval' } ] }, @@ -1194,83 +1183,18 @@ export const ApplicationDetails = () => { name: 'Statutory Documents', color: 'green', stages: [ - { - id: '11b-1', - name: 'GST', - status: isDocumentUploaded('GST Certificate') || ['Statutory PAN', 'Statutory Nodal', 'Statutory Check', 'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory GST' ? 'active' : 'pending', - description: 'GST certificate', - documentsUploaded: (documents || []).filter(d => d.documentType === 'GST Certificate').length - }, - { - id: '11b-2', - name: 'PAN', - status: isDocumentUploaded('PAN Card') || ['Statutory Nodal', 'Statutory Check', 'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory PAN' ? 'active' : 'pending', - description: 'PAN card', - documentsUploaded: (documents || []).filter(d => d.documentType === 'PAN Card').length - }, - { - id: '11b-3', - name: 'Nodal Agreement', - status: isDocumentUploaded('Nodal Agreement') || ['Statutory Check', 'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Nodal' ? 'active' : 'pending', - description: 'Nodal agreement document', - documentsUploaded: (documents || []).filter(d => d.documentType === 'Nodal Agreement').length - }, - { - id: '11b-4', - name: 'Cancelled Check', - status: isDocumentUploaded('Cancelled Check') || ['Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Check' ? 'active' : 'pending', - description: 'Cancelled check copy', - documentsUploaded: (documents || []).filter(d => d.documentType === 'Cancelled Check').length - }, - { - id: '11b-5', - name: 'Partnership Deed/LLP/MOA/AOA/COI', - status: isDocumentUploaded('Partnership Deed') || isDocumentUploaded('LLP Agreement') || isDocumentUploaded('Certificate of Incorporation') || isDocumentUploaded('MOA') || isDocumentUploaded('AOA') || ['Statutory Firm Reg', 'Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Partnership' ? 'active' : 'pending', - description: 'Business entity documents', - documentsUploaded: (documents || []).filter(d => ['Partnership Deed', 'LLP Agreement', 'Certificate of Incorporation', 'MOA', 'AOA'].includes(d.documentType)).length - }, - { - id: '11b-6', - name: 'Firm Registration Certificate', - status: isDocumentUploaded('Firm Registration') || ['Statutory Rental', 'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Firm Reg' ? 'active' : 'pending', - description: 'Firm registration certificate', - documentsUploaded: (documents || []).filter(d => d.documentType === 'Firm Registration').length - }, - { - id: '11b-7', - name: 'Rental agreement/ Lease agreement / Own/ Land agreement', - status: isDocumentUploaded('Rental Agreement') || isDocumentUploaded('Property Documents') || ['Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Rental' ? 'active' : 'pending', - description: 'Property agreement document', - documentsUploaded: (documents || []).filter(d => ['Rental Agreement', 'Property Documents'].includes(d.documentType)).length - }, - { - id: '11b-8', - name: 'Virtual Code', - status: isDocumentUploaded('Virtual Code Confirmation') || ['Statutory Domain', 'Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Virtual Code' ? 'active' : 'pending', - description: 'Virtual code availability', - documentsUploaded: (documents || []).filter(d => d.documentType === 'Virtual Code Confirmation').length - }, - { - id: '11b-9', - name: 'Domain ID', - status: isDocumentUploaded('Domain ID Setup') || ['Statutory MSD', 'Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory Domain' ? 'active' : 'pending', - description: 'Domain ID setup', - documentsUploaded: (documents || []).filter(d => d.documentType === 'Domain ID Setup').length - }, - { - id: '11b-10', - name: 'MSD Configuration', - status: isDocumentUploaded('MSD Configuration') || ['Statutory LOI Ack', 'LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory MSD' ? 'active' : 'pending', - description: 'Microsoft Dynamics configuration', - documentsUploaded: (documents || []).filter(d => d.documentType === 'MSD Configuration').length - }, - { - id: '11b-11', - name: 'LOI Acknowledgement Copy', - status: isDocumentUploaded('LOI Acknowledgement') || ['LOA Pending', 'LOA Issued', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Statutory LOI Ack' ? 'active' : 'pending', - description: 'LOI acknowledgement copy', - documentsUploaded: (documents || []).filter(d => d.documentType === 'LOI Acknowledgement').length - } + { id: '11b-1', name: 'GST Certificate', status: isDocumentUploaded('Statutory GST') || isDocumentUploaded('GST Certificate') ? 'completed' : 'active', description: 'GST details' }, + { id: '11b-2', name: 'PAN Card', status: isDocumentUploaded('Statutory PAN') || isDocumentUploaded('PAN Card') ? 'completed' : 'active', description: 'PAN details' }, + { id: '11b-3', name: 'Nodal Agreement', status: isDocumentUploaded('Statutory Nodal') || isDocumentUploaded('Nodal Agreement') ? 'completed' : 'active', description: 'Nodal details' }, + { id: '11b-4', name: 'Cancelled Check', status: isDocumentUploaded('Statutory Check') || isDocumentUploaded('Cancelled Check') ? 'completed' : 'active', description: 'Bank verification' }, + { id: '11b-5', name: 'Partnership Deed', status: isDocumentUploaded('Statutory Partnership') || isDocumentUploaded('Partnership Deed') ? 'completed' : 'active', description: 'Legal constitution' }, + { id: '11b-6', name: 'Firm Registration', status: isDocumentUploaded('Statutory Firm Reg') || isDocumentUploaded('Firm Registration') ? 'completed' : 'active', description: 'RoC/Firm reg' }, + { id: '11b-7', name: 'Virtual Code', status: isDocumentUploaded('Statutory Virtual Code') || isDocumentUploaded('Virtual Code Confirmation') ? 'completed' : 'active', description: 'Oracle setup' }, + { id: '11b-8', name: 'Domain ID', status: isDocumentUploaded('Statutory Domain') || isDocumentUploaded('Domain ID Setup') ? 'completed' : 'active', description: 'Email setup' }, + { id: '11b-9', name: 'MSD Configuration', status: isDocumentUploaded('Statutory MSD') || isDocumentUploaded('MSD Configuration') ? 'completed' : 'active', description: 'Multiple Security Deposit' }, + { id: '11b-10', name: 'LOI Acknowledgement', status: isDocumentUploaded('Statutory LOI Ack') || isDocumentUploaded('LOI Acknowledgement') ? 'completed' : 'active', description: 'LOI Signed copy' }, + { id: '11b-11', name: 'Board Resolution', status: isDocumentUploaded('Board Resolution') || isDocumentUploaded('Authorization Proof') ? 'completed' : 'active', description: 'Legal authorization' }, + { id: '11b-12', name: 'Consolidated Approval', status: application.statutoryStatus === 'COMPLETED' ? 'completed' : 'active', description: 'Managerial sign-off' } ] } ] @@ -1279,45 +1203,31 @@ export const ApplicationDetails = () => { id: 12, name: 'LOA', status: getStageStatus('LOA', () => ['EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'LOA Pending' ? 'active' : 'pending'), - isLocked: application.status === 'LOA Pending' && - getDeposit('FINAL')?.status !== 'Verified' && - !documents.some(d => (d.documentType?.toLowerCase().includes('first') && d.documentType?.toLowerCase().includes('fill')) && d.status === 'Approved'), + isLocked: application.status === 'LOA Pending' && getDeposit('FINAL')?.status !== 'Verified', lockMessage: 'First Fill (₹15L) must be verified by Finance before LOA Approval.', - date: application.loaDate, - description: 'Letter of Authorization', evaluators: Array.from(new Set((application.participants || []) - .filter((p: any) => - p.metadata?.stageCode === 'LOA_APPROVAL' || - p.metadata?.allAssignments?.includes('LOA_APPROVAL') - ) + .filter((p: any) => p.metadata?.stageCode === 'LOA_APPROVAL' || p.metadata?.allAssignments?.includes('LOA_APPROVAL')) .map((p: any) => `${p.user?.name} (${p.user?.role})`) )), - documentsUploaded: 1 + description: 'Letter of Authorization' }, { id: 13, name: 'EOR Complete', - status: getStageStatus('EOR Complete', () => - ['Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : - ['EOR In Progress', 'EOR Complete'].includes(application.status) ? 'active' : 'pending'), - date: application.eorCompleteDate, - description: 'Essential Operating Requirements completed', - documentsUploaded: 6 + status: getStageStatus('EOR Complete', () => ['Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'EOR Complete' ? 'active' : 'pending'), + description: 'Essential Operating Requirements' }, { id: 14, name: 'Inauguration', status: getStageStatus('Inauguration', () => ['Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Inauguration' ? 'active' : 'pending'), - date: application.inaugurationDate, - description: 'Dealership inauguration ceremony', - documentsUploaded: 2 + description: 'Dealership inauguration' }, { id: 15, name: 'Dealership Active', status: getStageStatus('Onboarded', () => application.status === 'Onboarded' ? 'completed' : 'pending'), - date: application.onboardedDate, - description: 'Dealer profile and login created' + description: 'Dealer profile active' } ]; @@ -2599,7 +2509,7 @@ export const ApplicationDetails = () => {
{ ) : ( <> {stage.status === 'completed' ? ( - + ) : stage.status === 'active' ? ( ) : ( @@ -2712,19 +2622,19 @@ export const ApplicationDetails = () => { ).length; return ( -
- -
+
+ +
); })()} @@ -2745,34 +2655,69 @@ export const ApplicationDetails = () => { return (
- +
+ + + {/* Branch Approval Button */} + {(() => { + const branchConfig = branchColor === 'blue' + ? { status: application.architectureStatus, role: 'ARCHITECTURE', stageCode: 'ARCHITECTURE_WORK' } + : { status: application.statutoryStatus, role: 'Legal Admin', stageCode: 'STATUTORY_WORK' }; + + if (branchConfig.status !== 'COMPLETED' && (currentUser?.roleCode === branchConfig.role || currentUser?.roleCode === 'Super Admin' || currentUser?.roleCode === 'DD Admin')) { + return ( + + ); + } + return null; + })()} +
{isExpanded && (
@@ -2817,10 +2762,7 @@ export const ApplicationDetails = () => { setShowDocumentsModal(true); if (stageDocs.length === 0) setShowUploadForm(true); }} - className={`text-[10px] font-medium flex items-center gap-1 px-1.5 py-0.5 rounded border ${branchColor === 'blue' - ? 'text-blue-700 bg-blue-50 border-blue-100 hover:bg-blue-100' - : 'text-green-700 bg-green-50 border-green-100 hover:bg-green-100' - }`} + className="text-[10px] font-medium text-blue-600 hover:text-blue-800 flex items-center gap-1 transition-colors" > {stageDocs.length > 0 ? `${stageDocs.length} Docs` : 'Upload'} diff --git a/src/components/applications/FDDApplicationDetails.tsx b/src/components/applications/FDDApplicationDetails.tsx index 1fa42bd..8cc6968 100644 --- a/src/components/applications/FDDApplicationDetails.tsx +++ b/src/components/applications/FDDApplicationDetails.tsx @@ -3,6 +3,8 @@ import { useParams, useNavigate } from 'react-router-dom'; import { API } from '../../api/API'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; import { Badge } from '../ui/badge'; +import { useSelector } from 'react-redux'; +import { RootState } from '../../store'; import { ArrowLeft, FileText, @@ -45,6 +47,8 @@ export function FDDApplicationDetails() { const [showFlagModal, setShowFlagModal] = useState(false); const [fddAuditRecommendation, setFddAuditRecommendation] = useState('Recommended'); const [fddAuditFindings, setFddAuditFindings] = useState(''); + const user = useSelector((state: RootState) => state.auth.user); + const isFddRole = user?.role === 'FDD' || user?.role === 'FDD Auditor'; useEffect(() => { if (id) fetchApplication(); @@ -162,54 +166,51 @@ export function FDDApplicationDetails() {
) : !isCompleted ? ( <> - - - + {isFddRole && ( + <> + + + + )} ) : (
@@ -316,47 +317,53 @@ export function FDDApplicationDetails() {
-

Select and upload the due diligence report

-

PDF or JPG formats accepted (Max 10MB)

+

+ {isFddRole ? 'Select and upload the due diligence report' : 'View Authorized Documents'} +

+

+ {isFddRole ? 'PDF or JPG formats accepted (Max 10MB)' : 'You are in View-Only mode for this Audit'} +

-
- + {isFddRole && ( +
+ -
- {uploading ? ( -
- - Uploading... -
- ) : ( - <> - -
- Browse & Upload +
+ {uploading ? ( +
+ + Uploading...
- - )} + ) : ( + <> + +
+ Browse & Upload +
+ + )} +
-
+ )}
)} diff --git a/src/lib/mock-data.ts b/src/lib/mock-data.ts index 4110f76..dd18c38 100644 --- a/src/lib/mock-data.ts +++ b/src/lib/mock-data.ts @@ -35,8 +35,19 @@ export type ApplicationStatus = | 'FDD Verification' | 'Payment Pending' | 'LOI In Progress' + | 'LOI Approved' + | 'Security Details In Progress' + | 'Security Details Approved' + | 'Security Details' + | 'LOI Issued In Progress' | 'LOI Issued' + | 'Statutory Work In Progress' + | 'Statutory Work Completed' + | 'Architecture Work In Progress' + | 'Architecture Work Completed' + | 'Dealer Code Generation In Progress' | 'Dealer Code Generation' + | 'Dealer Code Generated' | 'Architecture Team Assigned' | 'Architecture Document Upload' | 'Architecture Team Completion' @@ -52,6 +63,7 @@ export type ApplicationStatus = | 'Statutory MSD' | 'Statutory LOI Ack' | 'LOA Pending' + | 'LOA Issued' | 'EOR In Progress' | 'EOR Complete' | 'Inauguration'