workflow test file added and enhanncing the status transition
This commit is contained in:
parent
078afa3590
commit
c78d97fd31
@ -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 = () => {
|
||||
<div className="flex gap-4 pb-8">
|
||||
<div className="relative">
|
||||
<div className={`w-10 h-10 rounded-full flex items-center justify-center border-2 z-10 relative ${stage.status === 'completed'
|
||||
? 'bg-green-500 border-green-500 text-white shadow-sm'
|
||||
? 'bg-green-500 border-green-500 text-white shadow-md'
|
||||
: stage.status === 'active'
|
||||
? stage.isLocked ? 'bg-slate-400 border-slate-400 text-white' : 'bg-amber-500 border-amber-500 text-white animate-pulse-subtle'
|
||||
: 'bg-white border-slate-300 text-slate-400 shadow-none'
|
||||
@ -2622,7 +2532,7 @@ export const ApplicationDetails = () => {
|
||||
) : (
|
||||
<>
|
||||
{stage.status === 'completed' ? (
|
||||
<Check className="w-5 h-5" />
|
||||
<CheckCircle2 className="w-6 h-6" />
|
||||
) : stage.status === 'active' ? (
|
||||
<Clock className="w-5 h-5 text-white" />
|
||||
) : (
|
||||
@ -2719,10 +2629,10 @@ export const ApplicationDetails = () => {
|
||||
setShowDocumentsModal(true);
|
||||
if (stageDocsCount === 0) setShowUploadForm(true);
|
||||
}}
|
||||
className="text-xs font-medium text-amber-700 hover:text-amber-800 flex items-center gap-1 bg-amber-50 px-2 py-0.5 rounded border border-amber-200"
|
||||
className="text-xs font-semibold text-blue-600 hover:text-blue-800 flex items-center gap-1.5 px-3 py-1 rounded-full bg-blue-50 border border-blue-100 hover:bg-blue-100 transition-all shadow-sm"
|
||||
>
|
||||
<FileText className="w-3 h-3" />
|
||||
{stageDocsCount > 0 ? `${stageDocsCount} Documents Uploaded` : 'Upload Document'}
|
||||
<FileText className="w-3.5 h-3.5" />
|
||||
{stageDocsCount > 0 ? `${stageDocsCount} Documents` : 'Upload'}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@ -2745,12 +2655,13 @@ export const ApplicationDetails = () => {
|
||||
|
||||
return (
|
||||
<div key={branchIndex} className="mb-6 last:mb-0">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<button
|
||||
onClick={() => setExpandedBranches(prev => ({
|
||||
...prev,
|
||||
[branchKey]: !prev[branchKey]
|
||||
}))}
|
||||
className={`w-full flex items-center gap-3 p-4 rounded-lg border-2 transition-all hover:shadow-md ${branchColor === 'blue'
|
||||
className={`flex-1 flex items-center gap-3 p-4 rounded-lg border-2 transition-all hover:shadow-md ${branchColor === 'blue'
|
||||
? 'border-blue-300 bg-blue-50 hover:bg-blue-100'
|
||||
: 'border-green-300 bg-green-50 hover:bg-green-100'
|
||||
}`}
|
||||
@ -2765,15 +2676,49 @@ export const ApplicationDetails = () => {
|
||||
<GitBranch className={`w-4 h-4 ${branchColor === 'blue' ? 'text-blue-700' : 'text-green-700'}`} />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<p className={`${branchColor === 'blue' ? 'text-blue-900' : 'text-green-900'} font-semibold`}>
|
||||
<p className={`${branchColor === 'blue' ? 'text-blue-900' : 'text-green-900'} font-semibold tracking-tight`}>
|
||||
{branch.name}
|
||||
</p>
|
||||
<p className={`text-xs ${branchColor === 'blue' ? 'text-blue-700' : 'text-green-700'}`}>
|
||||
{branch.stages.length} steps
|
||||
<p className={`text-[10px] uppercase font-bold tracking-wider ${branchColor === 'blue' ? 'text-blue-500' : 'text-green-500'}`}>
|
||||
{branch.stages.length} SUB-STEPS
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* 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 (
|
||||
<Button
|
||||
size="sm"
|
||||
className={cn(
|
||||
"h-14 px-6 font-bold shadow-lg border-b-4 active:border-b-0 active:translate-y-1 transition-all",
|
||||
branchColor === 'blue' ? "bg-blue-600 hover:bg-blue-700 border-blue-800" : "bg-green-600 hover:bg-green-700 border-green-800"
|
||||
)}
|
||||
onClick={() => {
|
||||
onboardingService.submitStageDecision({
|
||||
applicationId: application.id,
|
||||
stageCode: branchConfig.stageCode,
|
||||
decision: 'Approved',
|
||||
remarks: `Consolidated approval for ${branch.name} track`
|
||||
}).then(() => {
|
||||
toast.success(`${branch.name} approved successfully`);
|
||||
fetchApplication();
|
||||
});
|
||||
}}
|
||||
>
|
||||
Approve Track
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})()}
|
||||
</div>
|
||||
|
||||
{isExpanded && (
|
||||
<div className="mt-4 ml-8 border-l-2 border-slate-200 pl-6 space-y-6">
|
||||
{branch.stages.map((branchStage) => (
|
||||
@ -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"
|
||||
>
|
||||
<FileText className="w-2.5 h-2.5" />
|
||||
{stageDocs.length > 0 ? `${stageDocs.length} Docs` : 'Upload'}
|
||||
|
||||
@ -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<string>('Recommended');
|
||||
const [fddAuditFindings, setFddAuditFindings] = useState<string>('');
|
||||
const user = useSelector((state: RootState) => state.auth.user);
|
||||
const isFddRole = user?.role === 'FDD' || user?.role === 'FDD Auditor';
|
||||
|
||||
useEffect(() => {
|
||||
if (id) fetchApplication();
|
||||
@ -161,6 +165,8 @@ export function FDDApplicationDetails() {
|
||||
Awaiting Previous Stages
|
||||
</div>
|
||||
) : !isCompleted ? (
|
||||
<>
|
||||
{isFddRole && (
|
||||
<>
|
||||
<button
|
||||
disabled={uploading}
|
||||
@ -203,13 +209,8 @@ export function FDDApplicationDetails() {
|
||||
>
|
||||
Flag Non-Responsive
|
||||
</button>
|
||||
<button
|
||||
disabled={uploading}
|
||||
onClick={() => setShowFinalizeModal(true)}
|
||||
className="px-6 py-2 bg-blue-600 text-white font-bold text-xs uppercase tracking-wider rounded-lg shadow-lg shadow-blue-200 hover:bg-blue-700 transition-all hover:scale-[1.02] disabled:opacity-50"
|
||||
>
|
||||
{uploading ? 'Processing...' : 'Finalize & Submit Report'}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-green-50 border border-green-200 text-green-700 font-bold text-[10px] uppercase tracking-[0.1em] rounded-lg shadow-inner">
|
||||
@ -316,9 +317,14 @@ export function FDDApplicationDetails() {
|
||||
<div className="w-12 h-12 bg-slate-50 text-slate-400 rounded-full flex items-center justify-center mb-4">
|
||||
<FileText className="w-6 h-6" />
|
||||
</div>
|
||||
<p className="text-slate-600 font-medium mb-1">Select and upload the due diligence report</p>
|
||||
<p className="text-slate-400 text-xs mb-6">PDF or JPG formats accepted (Max 10MB)</p>
|
||||
<p className="text-slate-600 font-medium mb-1">
|
||||
{isFddRole ? 'Select and upload the due diligence report' : 'View Authorized Documents'}
|
||||
</p>
|
||||
<p className="text-slate-400 text-xs mb-6">
|
||||
{isFddRole ? 'PDF or JPG formats accepted (Max 10MB)' : 'You are in View-Only mode for this Audit'}
|
||||
</p>
|
||||
|
||||
{isFddRole && (
|
||||
<div className="w-full max-w-sm space-y-4">
|
||||
<select
|
||||
value={selectedDocType}
|
||||
@ -357,6 +363,7 @@ export function FDDApplicationDetails() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@ -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'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user