workflow test file added and enhanncing the status transition

This commit is contained in:
laxmanhalaki 2026-04-09 09:59:37 +05:30
parent 078afa3590
commit c78d97fd31
3 changed files with 239 additions and 278 deletions

View File

@ -49,6 +49,7 @@ import {
Loader2, Loader2,
Info, Info,
ShieldAlert, ShieldAlert,
CheckCircle2,
} from 'lucide-react'; } from 'lucide-react';
import { Progress } from '../ui/progress'; import { Progress } from '../ui/progress';
import { Textarea } from '../ui/textarea'; import { Textarea } from '../ui/textarea';
@ -1018,6 +1019,10 @@ export const ApplicationDetails = () => {
return (documents || []).some(d => d.documentType === docType); 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 getStageStatus = (stageName: string, fallbackLogic: () => ProcessStage['status']): ProcessStage['status'] => {
const backendStage = (application.progressTracking || []).find((ps: any) => ps.stageName === stageName); const backendStage = (application.progressTracking || []).find((ps: any) => ps.stageName === stageName);
if (backendStage) { if (backendStage) {
@ -1042,7 +1047,7 @@ export const ApplicationDetails = () => {
id: 2, id: 2,
name: 'Questionnaire', name: 'Questionnaire',
status: getStageStatus('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' application.status === 'Questionnaire Pending' ? 'active' : 'pending'
), ),
date: application.questionnaireDate, date: application.questionnaireDate,
@ -1052,7 +1057,7 @@ export const ApplicationDetails = () => {
{ {
id: 3, id: 3,
name: 'Shortlist', 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, date: application.shortlistDate,
description: 'Application shortlisted by DD', description: 'Application shortlisted by DD',
evaluators: Array.from(new Set((application.participants || []) evaluators: Array.from(new Set((application.participants || [])
@ -1064,16 +1069,14 @@ export const ApplicationDetails = () => {
{ {
id: 4, id: 4,
name: '1st Level Interview', 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, date: application.level1InterviewDate,
description: 'DD-ZM + RBM evaluation', description: 'DD-ZM + RBM evaluation',
evaluators: Array.from(new Set((application.participants || []) evaluators: Array.from(new Set((application.participants || [])
.filter((p: any) => .filter((p: any) => p.metadata?.interviewLevel === 1 || p.metadata?.interviewLevel === '1' || p.metadata?.allAssignments?.includes(1))
p.metadata?.interviewLevel === 1 ||
p.metadata?.interviewLevel === '1' ||
p.metadata?.allAssignments?.includes(1) ||
p.metadata?.allAssignments?.includes('1')
)
.map((p: any) => `${p.user?.name} (${p.user?.role})`) .map((p: any) => `${p.user?.name} (${p.user?.role})`)
)), )),
documentsUploaded: 1 documentsUploaded: 1
@ -1081,16 +1084,14 @@ export const ApplicationDetails = () => {
{ {
id: 5, id: 5,
name: '2nd Level Interview', 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, date: application.level2InterviewDate,
description: 'DD Lead + ZBH evaluation', description: 'DD Lead + ZBH evaluation',
evaluators: Array.from(new Set((application.participants || []) evaluators: Array.from(new Set((application.participants || [])
.filter((p: any) => .filter((p: any) => p.metadata?.interviewLevel === 2 || p.metadata?.interviewLevel === '2' || p.metadata?.allAssignments?.includes(2))
p.metadata?.interviewLevel === 2 ||
p.metadata?.interviewLevel === '2' ||
p.metadata?.allAssignments?.includes(2) ||
p.metadata?.allAssignments?.includes('2')
)
.map((p: any) => `${p.user?.name} (${p.user?.role})`) .map((p: any) => `${p.user?.name} (${p.user?.role})`)
)), )),
documentsUploaded: 1 documentsUploaded: 1
@ -1098,16 +1099,14 @@ export const ApplicationDetails = () => {
{ {
id: 6, id: 6,
name: '3rd Level Interview', 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, date: application.level3InterviewDate,
description: 'NBH + DD Head evaluation', description: 'NBH + DD Head evaluation',
evaluators: Array.from(new Set((application.participants || []) evaluators: Array.from(new Set((application.participants || [])
.filter((p: any) => .filter((p: any) => p.metadata?.interviewLevel === 3 || p.metadata?.interviewLevel === '3' || p.metadata?.allAssignments?.includes(3))
p.metadata?.interviewLevel === 3 ||
p.metadata?.interviewLevel === '3' ||
p.metadata?.allAssignments?.includes(3) ||
p.metadata?.allAssignments?.includes('3')
)
.map((p: any) => `${p.user?.name} (${p.user?.role})`) .map((p: any) => `${p.user?.name} (${p.user?.role})`)
)), )),
documentsUploaded: 2 documentsUploaded: 2
@ -1115,7 +1114,7 @@ export const ApplicationDetails = () => {
{ {
id: 7, id: 7,
name: 'FDD', 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, date: application.fddDate,
description: 'Financial Due Diligence', description: 'Financial Due Diligence',
documentsUploaded: 5 documentsUploaded: 5
@ -1123,14 +1122,11 @@ export const ApplicationDetails = () => {
{ {
id: 8, id: 8,
name: 'LOI Approval', 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, date: application.loiApprovalDate,
description: 'Letter of Intent approval', description: 'Letter of Intent approval',
evaluators: Array.from(new Set((application.participants || []) evaluators: Array.from(new Set((application.participants || [])
.filter((p: any) => .filter((p: any) => p.metadata?.stageCode === 'LOI_APPROVAL' || p.metadata?.allAssignments?.includes('LOI_APPROVAL'))
p.metadata?.stageCode === 'LOI_APPROVAL' ||
p.metadata?.allAssignments?.includes('LOI_APPROVAL')
)
.map((p: any) => `${p.user?.name} (${p.user?.role})`) .map((p: any) => `${p.user?.name} (${p.user?.role})`)
)), )),
documentsUploaded: 1 documentsUploaded: 1
@ -1138,7 +1134,7 @@ export const ApplicationDetails = () => {
{ {
id: 9, id: 9,
name: 'Security Details', 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, date: application.securityDetailsDate,
description: 'Security verification', description: 'Security verification',
documentsUploaded: 3 documentsUploaded: 3
@ -1146,7 +1142,7 @@ export const ApplicationDetails = () => {
{ {
id: 10, id: 10,
name: 'LOI Issue', 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, date: application.loiIssueDate,
description: 'Letter of Intent issued', description: 'Letter of Intent issued',
documentsUploaded: 1 documentsUploaded: 1
@ -1154,10 +1150,9 @@ export const ApplicationDetails = () => {
{ {
id: 11, id: 11,
name: 'Dealer Code Generation', 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, date: application.dealerCodeDate,
description: 'Dealer code generated and assigned', description: 'Dealer code generated and assigned',
documentsUploaded: 0,
isParallel: true, isParallel: true,
branches: [ branches: [
{ {
@ -1166,27 +1161,21 @@ export const ApplicationDetails = () => {
stages: [ stages: [
{ {
id: '11a-1', id: '11a-1',
name: 'Assigned to Architecture Team', name: 'Architecture Assignment',
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', status: application.architectureAssignedTo ? 'completed' : application.status === 'Architecture Team Assigned' ? 'active' : 'pending',
date: application.architectureAssignedDate, description: 'Assigned to architecture team'
description: 'Assigned to architecture team for site planning',
documentsUploaded: 0
}, },
{ {
id: '11a-2', id: '11a-2',
name: 'Architectural Document Upload', name: 'Site Plan Blueprint',
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', status: isDocumentUploaded('Architecture Blueprint') ? 'completed' : application.architectureAssignedTo ? 'active' : 'pending',
date: application.architectureDocumentDate, description: 'Blueprints and site plans'
description: 'Architectural documents and blueprints uploaded',
documentsUploaded: (documents || []).filter(d => ['Architecture Blueprint', 'Site Plan'].includes(d.documentType)).length
}, },
{ {
id: '11a-3', id: '11a-3',
name: 'Architecture Team Completion', name: 'Architecture Work',
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', status: application.architectureStatus === 'COMPLETED' ? 'completed' : (application.architectureStatus === 'IN_PROGRESS' || isDocumentUploaded('Architecture Blueprint')) ? 'active' : 'pending',
date: application.architectureCompletionDate, description: 'Final architecture approval'
description: 'Architecture team work completed',
documentsUploaded: 0
} }
] ]
}, },
@ -1194,83 +1183,18 @@ export const ApplicationDetails = () => {
name: 'Statutory Documents', name: 'Statutory Documents',
color: 'green', color: 'green',
stages: [ stages: [
{ { id: '11b-1', name: 'GST Certificate', status: isDocumentUploaded('Statutory GST') || isDocumentUploaded('GST Certificate') ? 'completed' : 'active', description: 'GST details' },
id: '11b-1', { id: '11b-2', name: 'PAN Card', status: isDocumentUploaded('Statutory PAN') || isDocumentUploaded('PAN Card') ? 'completed' : 'active', description: 'PAN details' },
name: 'GST', { id: '11b-3', name: 'Nodal Agreement', status: isDocumentUploaded('Statutory Nodal') || isDocumentUploaded('Nodal Agreement') ? 'completed' : 'active', description: 'Nodal details' },
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', { id: '11b-4', name: 'Cancelled Check', status: isDocumentUploaded('Statutory Check') || isDocumentUploaded('Cancelled Check') ? 'completed' : 'active', description: 'Bank verification' },
description: 'GST certificate', { id: '11b-5', name: 'Partnership Deed', status: isDocumentUploaded('Statutory Partnership') || isDocumentUploaded('Partnership Deed') ? 'completed' : 'active', description: 'Legal constitution' },
documentsUploaded: (documents || []).filter(d => d.documentType === 'GST Certificate').length { 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-2', { id: '11b-9', name: 'MSD Configuration', status: isDocumentUploaded('Statutory MSD') || isDocumentUploaded('MSD Configuration') ? 'completed' : 'active', description: 'Multiple Security Deposit' },
name: 'PAN', { id: '11b-10', name: 'LOI Acknowledgement', status: isDocumentUploaded('Statutory LOI Ack') || isDocumentUploaded('LOI Acknowledgement') ? 'completed' : 'active', description: 'LOI Signed copy' },
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', { id: '11b-11', name: 'Board Resolution', status: isDocumentUploaded('Board Resolution') || isDocumentUploaded('Authorization Proof') ? 'completed' : 'active', description: 'Legal authorization' },
description: 'PAN card', { id: '11b-12', name: 'Consolidated Approval', status: application.statutoryStatus === 'COMPLETED' ? 'completed' : 'active', description: 'Managerial sign-off' }
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
}
] ]
} }
] ]
@ -1279,45 +1203,31 @@ export const ApplicationDetails = () => {
id: 12, id: 12,
name: 'LOA', name: 'LOA',
status: getStageStatus('LOA', () => ['EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'LOA Pending' ? 'active' : 'pending'), 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' && isLocked: application.status === 'LOA Pending' && getDeposit('FINAL')?.status !== 'Verified',
getDeposit('FINAL')?.status !== 'Verified' &&
!documents.some(d => (d.documentType?.toLowerCase().includes('first') && d.documentType?.toLowerCase().includes('fill')) && d.status === 'Approved'),
lockMessage: 'First Fill (₹15L) must be verified by Finance before LOA Approval.', 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 || []) evaluators: Array.from(new Set((application.participants || [])
.filter((p: any) => .filter((p: any) => p.metadata?.stageCode === 'LOA_APPROVAL' || p.metadata?.allAssignments?.includes('LOA_APPROVAL'))
p.metadata?.stageCode === 'LOA_APPROVAL' ||
p.metadata?.allAssignments?.includes('LOA_APPROVAL')
)
.map((p: any) => `${p.user?.name} (${p.user?.role})`) .map((p: any) => `${p.user?.name} (${p.user?.role})`)
)), )),
documentsUploaded: 1 description: 'Letter of Authorization'
}, },
{ {
id: 13, id: 13,
name: 'EOR Complete', name: 'EOR Complete',
status: getStageStatus('EOR Complete', () => status: getStageStatus('EOR Complete', () => ['Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'EOR Complete' ? 'active' : 'pending'),
['Inauguration', 'Approved', 'Onboarded'].includes(application.status) ? 'completed' : description: 'Essential Operating Requirements'
['EOR In Progress', 'EOR Complete'].includes(application.status) ? 'active' : 'pending'),
date: application.eorCompleteDate,
description: 'Essential Operating Requirements completed',
documentsUploaded: 6
}, },
{ {
id: 14, id: 14,
name: 'Inauguration', name: 'Inauguration',
status: getStageStatus('Inauguration', () => ['Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Inauguration' ? 'active' : 'pending'), status: getStageStatus('Inauguration', () => ['Approved', 'Onboarded'].includes(application.status) ? 'completed' : application.status === 'Inauguration' ? 'active' : 'pending'),
date: application.inaugurationDate, description: 'Dealership inauguration'
description: 'Dealership inauguration ceremony',
documentsUploaded: 2
}, },
{ {
id: 15, id: 15,
name: 'Dealership Active', name: 'Dealership Active',
status: getStageStatus('Onboarded', () => application.status === 'Onboarded' ? 'completed' : 'pending'), status: getStageStatus('Onboarded', () => application.status === 'Onboarded' ? 'completed' : 'pending'),
date: application.onboardedDate, description: 'Dealer profile active'
description: 'Dealer profile and login created'
} }
]; ];
@ -2599,7 +2509,7 @@ export const ApplicationDetails = () => {
<div className="flex gap-4 pb-8"> <div className="flex gap-4 pb-8">
<div className="relative"> <div className="relative">
<div className={`w-10 h-10 rounded-full flex items-center justify-center border-2 z-10 relative ${stage.status === 'completed' <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.status === 'active'
? stage.isLocked ? 'bg-slate-400 border-slate-400 text-white' : 'bg-amber-500 border-amber-500 text-white animate-pulse-subtle' ? 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' : 'bg-white border-slate-300 text-slate-400 shadow-none'
@ -2622,7 +2532,7 @@ export const ApplicationDetails = () => {
) : ( ) : (
<> <>
{stage.status === 'completed' ? ( {stage.status === 'completed' ? (
<Check className="w-5 h-5" /> <CheckCircle2 className="w-6 h-6" />
) : stage.status === 'active' ? ( ) : stage.status === 'active' ? (
<Clock className="w-5 h-5 text-white" /> <Clock className="w-5 h-5 text-white" />
) : ( ) : (
@ -2712,19 +2622,19 @@ export const ApplicationDetails = () => {
).length; ).length;
return ( return (
<div className="flex items-center gap-2 mt-1"> <div className="flex items-center gap-2 mt-1">
<button <button
onClick={() => { onClick={() => {
setSelectedStage(stage.name); setSelectedStage(stage.name);
setShowDocumentsModal(true); setShowDocumentsModal(true);
if (stageDocsCount === 0) setShowUploadForm(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" /> <FileText className="w-3.5 h-3.5" />
{stageDocsCount > 0 ? `${stageDocsCount} Documents Uploaded` : 'Upload Document'} {stageDocsCount > 0 ? `${stageDocsCount} Documents` : 'Upload'}
</button> </button>
</div> </div>
); );
})()} })()}
@ -2745,34 +2655,69 @@ export const ApplicationDetails = () => {
return ( return (
<div key={branchIndex} className="mb-6 last:mb-0"> <div key={branchIndex} className="mb-6 last:mb-0">
<button <div className="flex items-center gap-3 mb-2">
onClick={() => setExpandedBranches(prev => ({ <button
...prev, onClick={() => setExpandedBranches(prev => ({
[branchKey]: !prev[branchKey] ...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' }))}
? 'border-blue-300 bg-blue-50 hover:bg-blue-100' className={`flex-1 flex items-center gap-3 p-4 rounded-lg border-2 transition-all hover:shadow-md ${branchColor === 'blue'
: 'border-green-300 bg-green-50 hover:bg-green-100' ? 'border-blue-300 bg-blue-50 hover:bg-blue-100'
}`} : 'border-green-300 bg-green-50 hover:bg-green-100'
> }`}
{isExpanded ? ( >
<ChevronDown className={`w-5 h-5 ${branchColor === 'blue' ? 'text-blue-600' : 'text-green-600'}`} /> {isExpanded ? (
) : ( <ChevronDown className={`w-5 h-5 ${branchColor === 'blue' ? 'text-blue-600' : 'text-green-600'}`} />
<ChevronRight className={`w-5 h-5 ${branchColor === 'blue' ? 'text-blue-600' : 'text-green-600'}`} /> ) : (
)} <ChevronRight className={`w-5 h-5 ${branchColor === 'blue' ? 'text-blue-600' : 'text-green-600'}`} />
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${branchColor === 'blue' ? 'bg-blue-200' : 'bg-green-200' )}
}`}> <div className={`w-8 h-8 rounded-full flex items-center justify-center ${branchColor === 'blue' ? 'bg-blue-200' : 'bg-green-200'
<GitBranch className={`w-4 h-4 ${branchColor === 'blue' ? 'text-blue-700' : 'text-green-700'}`} /> }`}>
</div> <GitBranch className={`w-4 h-4 ${branchColor === 'blue' ? 'text-blue-700' : 'text-green-700'}`} />
<div className="flex-1 text-left"> </div>
<p className={`${branchColor === 'blue' ? 'text-blue-900' : 'text-green-900'} font-semibold`}> <div className="flex-1 text-left">
{branch.name} <p className={`${branchColor === 'blue' ? 'text-blue-900' : 'text-green-900'} font-semibold tracking-tight`}>
</p> {branch.name}
<p className={`text-xs ${branchColor === 'blue' ? 'text-blue-700' : 'text-green-700'}`}> </p>
{branch.stages.length} steps <p className={`text-[10px] uppercase font-bold tracking-wider ${branchColor === 'blue' ? 'text-blue-500' : 'text-green-500'}`}>
</p> {branch.stages.length} SUB-STEPS
</div> </p>
</button> </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 && ( {isExpanded && (
<div className="mt-4 ml-8 border-l-2 border-slate-200 pl-6 space-y-6"> <div className="mt-4 ml-8 border-l-2 border-slate-200 pl-6 space-y-6">
@ -2817,10 +2762,7 @@ export const ApplicationDetails = () => {
setShowDocumentsModal(true); setShowDocumentsModal(true);
if (stageDocs.length === 0) setShowUploadForm(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' className="text-[10px] font-medium text-blue-600 hover:text-blue-800 flex items-center gap-1 transition-colors"
? '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'
}`}
> >
<FileText className="w-2.5 h-2.5" /> <FileText className="w-2.5 h-2.5" />
{stageDocs.length > 0 ? `${stageDocs.length} Docs` : 'Upload'} {stageDocs.length > 0 ? `${stageDocs.length} Docs` : 'Upload'}

View File

@ -3,6 +3,8 @@ import { useParams, useNavigate } from 'react-router-dom';
import { API } from '../../api/API'; import { API } from '../../api/API';
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
import { Badge } from '../ui/badge'; import { Badge } from '../ui/badge';
import { useSelector } from 'react-redux';
import { RootState } from '../../store';
import { import {
ArrowLeft, ArrowLeft,
FileText, FileText,
@ -45,6 +47,8 @@ export function FDDApplicationDetails() {
const [showFlagModal, setShowFlagModal] = useState(false); const [showFlagModal, setShowFlagModal] = useState(false);
const [fddAuditRecommendation, setFddAuditRecommendation] = useState<string>('Recommended'); const [fddAuditRecommendation, setFddAuditRecommendation] = useState<string>('Recommended');
const [fddAuditFindings, setFddAuditFindings] = useState<string>(''); const [fddAuditFindings, setFddAuditFindings] = useState<string>('');
const user = useSelector((state: RootState) => state.auth.user);
const isFddRole = user?.role === 'FDD' || user?.role === 'FDD Auditor';
useEffect(() => { useEffect(() => {
if (id) fetchApplication(); if (id) fetchApplication();
@ -162,54 +166,51 @@ export function FDDApplicationDetails() {
</div> </div>
) : !isCompleted ? ( ) : !isCompleted ? (
<> <>
<button {isFddRole && (
disabled={uploading} <>
onClick={() => { <button
const input = document.createElement('input'); disabled={uploading}
input.type = 'file'; onClick={() => {
input.onchange = async (e: any) => { const input = document.createElement('input');
const file = e.target.files[0]; input.type = 'file';
if (!file) return; input.onchange = async (e: any) => {
try { const file = e.target.files[0];
setUploading(true); if (!file) return;
const formData = new FormData(); try {
formData.append('file', file); setUploading(true);
formData.append('documentType', 'FDD Final Audit Report'); const formData = new FormData();
formData.append('stage', 'FDD'); formData.append('file', file);
formData.append('applicationId', application.id); formData.append('documentType', 'FDD Final Audit Report');
formData.append('stage', 'FDD');
const res: any = await API.uploadDocument(application.id, formData); formData.append('applicationId', application.id);
if (res.data?.success) {
toast.success('FDD Final Audit Report uploaded successfully'); const res: any = await API.uploadDocument(application.id, formData);
fetchApplication(); if (res.data?.success) {
} toast.success('FDD Final Audit Report uploaded successfully');
} catch (err) { fetchApplication();
toast.error('Upload failed'); }
} finally { } catch (err) {
setUploading(false); toast.error('Upload failed');
} } finally {
}; setUploading(false);
input.click(); }
}} };
className="flex items-center gap-2 px-4 py-2 bg-white border border-slate-200 text-slate-700 font-bold text-xs uppercase tracking-wider rounded-lg hover:bg-slate-50 transition-all" input.click();
> }}
<Upload className="w-4 h-4" /> className="flex items-center gap-2 px-4 py-2 bg-white border border-slate-200 text-slate-700 font-bold text-xs uppercase tracking-wider rounded-lg hover:bg-slate-50 transition-all"
{uploading ? 'Uploading...' : 'Upload Report'} >
</button> <Upload className="w-4 h-4" />
<button {uploading ? 'Uploading...' : 'Upload Report'}
disabled={uploading} </button>
onClick={() => setShowFlagModal(true)} <button
className="px-4 py-2 text-red-600 font-bold text-xs uppercase tracking-wider hover:bg-red-50 rounded-lg transition-all" disabled={uploading}
> onClick={() => setShowFlagModal(true)}
Flag Non-Responsive className="px-4 py-2 text-red-600 font-bold text-xs uppercase tracking-wider hover:bg-red-50 rounded-lg transition-all"
</button> >
<button Flag Non-Responsive
disabled={uploading} </button>
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"> <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,47 +317,53 @@ export function FDDApplicationDetails() {
<div className="w-12 h-12 bg-slate-50 text-slate-400 rounded-full flex items-center justify-center mb-4"> <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" /> <FileText className="w-6 h-6" />
</div> </div>
<p className="text-slate-600 font-medium mb-1">Select and upload the due diligence report</p> <p className="text-slate-600 font-medium mb-1">
<p className="text-slate-400 text-xs mb-6">PDF or JPG formats accepted (Max 10MB)</p> {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>
<div className="w-full max-w-sm space-y-4"> {isFddRole && (
<select <div className="w-full max-w-sm space-y-4">
value={selectedDocType} <select
onChange={(e) => setSelectedDocType(e.target.value)} value={selectedDocType}
className="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded text-sm font-medium text-slate-700 outline-none focus:ring-1 focus:ring-blue-500 transition-all" onChange={(e) => setSelectedDocType(e.target.value)}
> className="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded text-sm font-medium text-slate-700 outline-none focus:ring-1 focus:ring-blue-500 transition-all"
<option value="">Select Document Category...</option> >
<option value="FDD Final Audit Report">FDD Final Audit Report</option> <option value="">Select Document Category...</option>
<option value="Bank Statement">Bank Statement</option> <option value="FDD Final Audit Report">FDD Final Audit Report</option>
<option value="Income Tax Returns (ITR)">Income Tax Returns (ITR)</option> <option value="Bank Statement">Bank Statement</option>
<option value="CIBIL Report">CIBIL Report</option> <option value="Income Tax Returns (ITR)">Income Tax Returns (ITR)</option>
<option value="Business Valuation Report">Business Valuation Report</option> <option value="CIBIL Report">CIBIL Report</option>
<option value="Property Documents">Property Documents</option> <option value="Business Valuation Report">Business Valuation Report</option>
</select> <option value="Property Documents">Property Documents</option>
</select>
<div className="relative"> <div className="relative">
{uploading ? ( {uploading ? (
<div className="w-full py-2.5 bg-slate-100 rounded flex items-center justify-center gap-2"> <div className="w-full py-2.5 bg-slate-100 rounded flex items-center justify-center gap-2">
<Loader2 className="w-4 h-4 animate-spin text-slate-400" /> <Loader2 className="w-4 h-4 animate-spin text-slate-400" />
<span className="text-slate-500 text-xs font-bold uppercase tracking-wider">Uploading...</span> <span className="text-slate-500 text-xs font-bold uppercase tracking-wider">Uploading...</span>
</div>
) : (
<>
<input
type="file"
className="absolute inset-0 opacity-0 cursor-pointer"
onChange={handleFileUpload}
disabled={!selectedDocType}
/>
<div className={`w-full py-2.5 text-center font-bold uppercase tracking-wider text-xs rounded transition-all ${
!selectedDocType ? 'bg-slate-100 text-slate-300' : 'bg-slate-900 text-white hover:bg-slate-800'
}`}>
Browse & Upload
</div> </div>
</> ) : (
)} <>
<input
type="file"
className="absolute inset-0 opacity-0 cursor-pointer"
onChange={handleFileUpload}
disabled={!selectedDocType}
/>
<div className={`w-full py-2.5 text-center font-bold uppercase tracking-wider text-xs rounded transition-all ${
!selectedDocType ? 'bg-slate-100 text-slate-300' : 'bg-slate-900 text-white hover:bg-slate-800'
}`}>
Browse & Upload
</div>
</>
)}
</div>
</div> </div>
</div> )}
</div> </div>
)} )}

View File

@ -35,8 +35,19 @@ export type ApplicationStatus =
| 'FDD Verification' | 'FDD Verification'
| 'Payment Pending' | 'Payment Pending'
| 'LOI In Progress' | 'LOI In Progress'
| 'LOI Approved'
| 'Security Details In Progress'
| 'Security Details Approved'
| 'Security Details'
| 'LOI Issued In Progress'
| 'LOI Issued' | '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 Generation'
| 'Dealer Code Generated'
| 'Architecture Team Assigned' | 'Architecture Team Assigned'
| 'Architecture Document Upload' | 'Architecture Document Upload'
| 'Architecture Team Completion' | 'Architecture Team Completion'
@ -52,6 +63,7 @@ export type ApplicationStatus =
| 'Statutory MSD' | 'Statutory MSD'
| 'Statutory LOI Ack' | 'Statutory LOI Ack'
| 'LOA Pending' | 'LOA Pending'
| 'LOA Issued'
| 'EOR In Progress' | 'EOR In Progress'
| 'EOR Complete' | 'EOR Complete'
| 'Inauguration' | 'Inauguration'