Dealer_Onboard_Frontend/src/features/onboarding/pages/ApplicationDetails.tsx

653 lines
25 KiB
TypeScript

import { useEffect } from 'react';
import { useParams, useNavigate, useLocation } from 'react-router-dom';
import { onboardingService } from '@/services/onboarding.service';
import { ApplicationDetailsHeader } from '@/features/onboarding/components/application-details/ApplicationDetailsHeader';
import { ApplicantInformationCard } from '@/features/onboarding/components/application-details/ApplicantInformationCard';
import { ApplicationDetailsTabs } from '@/features/onboarding/components/application-details/ApplicationDetailsTabs';
import { ApplicationDetailsSidebar } from '@/features/onboarding/components/application-details/ApplicationDetailsSidebar';
import { ApplicationDetailsActionModals } from '@/features/onboarding/components/application-details/ApplicationDetailsActionModals';
import { ApplicationDetailsExtendedModals } from '@/features/onboarding/components/application-details/ApplicationDetailsExtendedModals';
import { ApplicationDetailsFddAuditContent } from '@/features/onboarding/components/application-details/ApplicationDetailsFddAuditContent';
import { auditLogActionBadgeClass } from '@/features/onboarding/components/application-details/applicationDetails.shared';
import { useApplicationDetailsPermissions } from '@/features/onboarding/hooks/useApplicationDetailsPermissions';
import { useApplicationDetailsUIState } from '@/features/onboarding/hooks/useApplicationDetailsUIState';
import { useApplicationDetailsFeedbackActions } from '@/features/onboarding/hooks/useApplicationDetailsFeedbackActions';
import { useInterviewConfigs } from '@/features/onboarding/hooks/useInterviewConfigs';
import { useApplicationDetailsAdminActions } from '@/features/onboarding/hooks/useApplicationDetailsAdminActions';
import { useApplicationDetailsData } from '@/features/onboarding/hooks/useApplicationDetailsData';
import { useApplicationDetailsLocalActions } from '@/features/onboarding/hooks/useApplicationDetailsLocalActions';
import { useApplicationDetailsStageData } from '@/features/onboarding/hooks/useApplicationDetailsStageData';
import { useSelector } from 'react-redux';
import { RootState } from '@/store';
import { Loader2 } from 'lucide-react';
export const ApplicationDetails = () => {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { user: currentUser } = useSelector((state: RootState) => state.auth);
const applicationId = id || '';
const onBack = () => navigate(-1);
const {
application,
loading,
setLoading,
documents,
setDocuments,
eorData,
auditLogs,
auditLoading,
worknotes,
deposits,
paymentConfigs,
refreshDocuments,
fetchApplication,
fetchEorData,
getDeposit,
} = useApplicationDetailsData({ applicationId });
const eorProgress = eorData?.items ? (eorData.items.filter((item: any) => item.isCompliant).length / eorData.items.length) * 100 : 0;
const routerLocation = useLocation();
const {
showFirmTypeModal, setShowFirmTypeModal,
updatingFirmType, setUpdatingFirmType,
tempFirmType, setTempFirmType,
activeTab, setActiveTab,
showApproveModal, setShowApproveModal,
showOnboardModal, setShowOnboardModal,
isOnboarding, setIsOnboarding,
showRejectModal, setShowRejectModal,
rejectionReason, setRejectionReason,
scheduledInterviewParticipants, setScheduledInterviewParticipants,
showScheduleModal, setShowScheduleModal,
showCancelInterviewModal, setShowCancelInterviewModal,
interviewIdToCancel, setInterviewIdToCancel,
showKTMatrixModal, setShowKTMatrixModal,
showLevel2FeedbackModal, setShowLevel2FeedbackModal,
showLevel3FeedbackModal, setShowLevel3FeedbackModal,
showDocumentsModal, setShowDocumentsModal,
showAssignModal, setShowAssignModal,
selectedStage, setSelectedStage,
interviewMode, setInterviewMode,
approvalRemark, setApprovalRemark,
expandedBranches, setExpandedBranches,
users, setUsers,
selectedUser, setSelectedUser,
participantType, setParticipantType,
interviewDate, setInterviewDate,
interviewType, setInterviewType,
meetingLink, setMeetingLink,
location, setLocation,
showUploadForm, setShowUploadForm,
uploadFile, setUploadFile,
uploadDocType, setUploadDocType,
approvalFile, setApprovalFile,
isUploading, setIsUploading,
previewDoc, setPreviewDoc,
showPreviewModal, setShowPreviewModal,
selectedInterviewerId, setSelectedInterviewerId,
isEditingStatutory, setIsEditingStatutory,
statutoryForm, setStatutoryForm,
isSavingStatutory, setIsSavingStatutory,
interviews, setInterviews,
isScheduling, setIsScheduling,
isCancellingInterview, setIsCancellingInterview,
showAssignArchitectureModal, setShowAssignArchitectureModal,
architectureLeadId, setArchitectureLeadId,
isAssigningArchitecture, setIsAssigningArchitecture,
showArchitectureStatusModal, setShowArchitectureStatusModal,
architectureStatus, setArchitectureStatus,
architectureRemarks, setArchitectureRemarks,
isUpdatingArchitecture, setIsUpdatingArchitecture,
isAssigningParticipant, setIsAssigningParticipant,
documentConfigs, setDocumentConfigs,
fddAgencies, setFddAgencies,
selectedAgencyId, setSelectedAgencyId,
isAssigningAgency, setIsAssigningAgency,
isApproving, setIsApproving,
isRejecting, setIsRejecting,
ktMatrixScores, setKtMatrixScores,
ktMatrixSelectedValues, setKtMatrixSelectedValues,
ktMatrixRemarks, setKtMatrixRemarks,
ktMatrixRecommendation, setKtMatrixRecommendation,
isSubmittingKT, setIsSubmittingKT,
selectedInterviewForFeedback, setSelectedInterviewForFeedback,
showFddFinalizeModal, setShowFddFinalizeModal,
showFddFlagModal, setShowFddFlagModal,
fddAuditRecommendation, setFddAuditRecommendation,
fddAuditFindings, setFddAuditFindings,
isFinalizingFdd, setIsFinalizingFdd,
isFddFlagging, setIsFddFlagging,
level2Feedback, setLevel2Feedback,
level2Recommendation, setLevel2Recommendation,
isSubmittingLevel2, setIsSubmittingLevel2,
level3Feedback, setLevel3Feedback,
level3Recommendation, setLevel3Recommendation,
isSubmittingLevel3, setIsSubmittingLevel3,
showFeedbackDetailsModal, setShowFeedbackDetailsModal,
selectedEvaluationForView, setSelectedEvaluationForView,
} = useApplicationDetailsUIState({
currentUser,
initialTab: routerLocation.state?.activeTab || 'questionnaire',
});
const isNonResponsive = (worknotes || []).some(note =>
(note.noteText || '').includes('FLAGGED:')
) || application?.statutoryStatus === 'Flagged';
const {
handleUpdateFirmType,
handleEditStatutory,
handleSaveStatutory,
fetchFddAgencies,
handleAssignAgency,
} = useApplicationDetailsLocalActions({
application,
applicationId,
tempFirmType,
setUpdatingFirmType,
setShowFirmTypeModal,
setStatutoryForm,
setIsEditingStatutory,
setIsSavingStatutory,
statutoryForm,
setFddAgencies,
selectedAgencyId,
setIsAssigningAgency,
fetchApplication,
});
const canEditStatutory = currentUser?.roleCode === 'Super Admin' || currentUser?.roleCode === 'DD Admin' || currentUser?.role === 'Super Admin' || currentUser?.role === 'DD Admin';
const isAdmin = currentUser?.roleCode === 'Super Admin' || currentUser?.roleCode === 'DD Admin' ||
currentUser?.role === 'Super Admin' || currentUser?.role === 'DD Admin' ||
currentUser?.role === 'NBH' || currentUser?.role === 'DD Head' ||
currentUser?.roleCode === 'NBH' || currentUser?.roleCode === 'DD_HEAD';
useEffect(() => {
const fetchConfigs = async () => {
try {
const res = await onboardingService.getDocumentConfigs({ limit: 1000 });
const configs = res.data || (Array.isArray(res) ? res : []);
setDocumentConfigs(configs);
} catch (error) {
console.error('Failed to fetch document configs:', error);
}
};
fetchConfigs();
}, [setDocumentConfigs]);
useEffect(() => {
if (showScheduleModal && application) {
if (application.status === 'Shortlisted' || application.status === 'Questionnaire Completed') {
setInterviewType('level1');
} else if (application.status === 'Level 1 Approved') {
setInterviewType('level2');
} else if (application.status === 'Level 2 Approved' || application.status === 'Level 2 Recommended') {
setInterviewType('level3');
}
}
}, [showScheduleModal, application?.status, setInterviewType]);
const fetchInterviews = async () => {
if (applicationId) {
try {
const data = await onboardingService.getInterviews(applicationId);
setInterviews(data || []);
} catch (error) {
console.error('Failed to fetch interviews', error);
}
}
};
useEffect(() => {
fetchInterviews();
}, [applicationId]);
const {
ktMatrixConfig,
level2Config,
level3Config,
} = useInterviewConfigs();
const {
handleKTMatrixChange,
calculateKTScore,
handleSubmitKTMatrix,
handleLevel2Change,
handleSubmitLevel2Feedback,
handleLevel3Change,
handleSubmitLevel3Feedback,
ktCriteria,
l2Fields,
l3Fields,
} = useApplicationDetailsFeedbackActions({
ktMatrixScores,
setKtMatrixScores,
setKtMatrixSelectedValues,
ktMatrixRemarks,
setKtMatrixRemarks,
ktMatrixRecommendation,
setKtMatrixRecommendation,
selectedInterviewForFeedback,
interviews,
setIsSubmittingKT,
setShowKTMatrixModal,
level2Feedback,
setLevel2Feedback,
level2Recommendation,
setLevel2Recommendation,
setIsSubmittingLevel2,
setShowLevel2FeedbackModal,
level3Feedback,
setLevel3Feedback,
level3Recommendation,
setLevel3Recommendation,
setIsSubmittingLevel3,
setShowLevel3FeedbackModal,
currentUser,
fetchInterviews,
fetchApplication,
ktMatrixConfig,
level2Config,
level3Config,
});
useEffect(() => {
if (['documents', 'progress', 'fdd', 'eor'].includes(activeTab) && applicationId) {
refreshDocuments();
}
if (activeTab === 'fdd' && (currentUser?.role === 'DD Admin' || currentUser?.role === 'Super Admin')) {
fetchFddAgencies();
}
}, [activeTab, applicationId, refreshDocuments, fetchFddAgencies, currentUser?.role]);
const {
handleAddInterviewer,
handleRemoveInterviewer,
maybeFetchUsersForModal,
handleScheduleInterview,
handleCancelInterview,
handleConfirmCancelInterview,
handleUpload,
handleApprove,
handleReject,
handleGenerateDealerCodes,
handleAssignArchitecture,
handleUpdateArchitectureStatus,
handleAddParticipant,
handleRetriggerEvaluators,
} = useApplicationDetailsAdminActions({
application,
applicationId,
currentUser,
interviews,
approvalFile,
approvalRemark,
rejectionReason,
architectureLeadId,
architectureStatus,
architectureRemarks,
selectedUser,
participantType,
users,
interviewDate,
interviewType,
interviewMode,
meetingLink,
location,
scheduledInterviewParticipants,
uploadFile,
uploadDocType,
selectedStage,
setIsApproving,
setShowApproveModal,
setApprovalRemark,
setApprovalFile,
setIsRejecting,
setShowRejectModal,
setRejectionReason,
setIsAssigningArchitecture,
setShowAssignArchitectureModal,
setIsUpdatingArchitecture,
setShowArchitectureStatusModal,
setIsAssigningParticipant,
setSelectedUser,
setShowAssignModal,
setLoading,
setIsScheduling,
setShowScheduleModal,
setShowCancelInterviewModal,
interviewIdToCancel,
setInterviewIdToCancel,
setIsCancellingInterview,
setIsUploading,
setShowUploadForm,
setUploadFile,
setUploadDocType,
setDocuments,
selectedInterviewerId,
setSelectedInterviewerId,
setScheduledInterviewParticipants,
setUsers,
showScheduleModal,
showAssignArchitectureModal,
showAssignModal,
fetchApplication,
fetchInterviews,
fetchEorData,
});
useEffect(() => {
maybeFetchUsersForModal();
}, [showScheduleModal, showAssignArchitectureModal, showAssignModal, interviewType, application?.id, maybeFetchUsersForModal]);
if (loading && !application) {
return (
<div className="flex items-center justify-center min-h-[60vh]">
<Loader2 className="w-10 h-10 animate-spin text-amber-600" />
</div>
);
}
if (!application) {
return <div className="flex justify-center items-center h-96">Application not found</div>;
}
const { processStages, eorChecklist, flattenedStages, getDocumentsForStage } = useApplicationDetailsStageData({
application,
documents,
interviews,
eorData,
getDeposit,
});
const {
activeInterviewForUser,
currentUserEvaluation,
hasSubmittedFeedback,
currentUserStageAction,
isInterviewCompleted,
isInterviewActive,
permissions,
} = useApplicationDetailsPermissions({
application,
interviews,
currentUser,
getDeposit,
eorProgress,
});
const renderFddAuditContent = () => (
<ApplicationDetailsFddAuditContent
application={application}
currentUser={currentUser}
documents={documents}
fddAgencies={fddAgencies}
selectedAgencyId={selectedAgencyId}
setSelectedAgencyId={setSelectedAgencyId}
isAssigningAgency={isAssigningAgency}
handleAssignAgency={handleAssignAgency}
setPreviewDoc={setPreviewDoc}
setShowPreviewModal={setShowPreviewModal}
setIsUploading={setIsUploading}
fetchApplication={fetchApplication}
refreshDocuments={refreshDocuments}
/>
);
return (
<div className="space-y-6">
<ApplicationDetailsHeader
application={application}
isNonResponsive={isNonResponsive}
isAdmin={isAdmin}
onBack={onBack}
onOpenWorknotes={() => navigate(`/worknotes/application/${application.id}`, {
state: {
applicationName: application.name,
registrationNumber: application.registrationNumber,
participants: application.participants
}
})}
/>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6">
<ApplicantInformationCard
application={application}
canEditStatutory={canEditStatutory}
isEditingStatutory={isEditingStatutory}
isSavingStatutory={isSavingStatutory}
statutoryForm={statutoryForm}
onEditFirmType={() => {
setTempFirmType(application.constitutionType || '');
setShowFirmTypeModal(true);
}}
onEditStatutory={handleEditStatutory}
onCancelEditStatutory={() => setIsEditingStatutory(false)}
onSaveStatutory={handleSaveStatutory}
onStatutoryFormChange={setStatutoryForm}
/>
{application.isShortlisted !== false && (
<ApplicationDetailsTabs
application={application}
activeTab={activeTab}
setActiveTab={setActiveTab}
processStages={processStages}
documents={documents}
interviews={interviews}
expandedBranches={expandedBranches}
setExpandedBranches={setExpandedBranches}
setSelectedStage={setSelectedStage}
setShowDocumentsModal={setShowDocumentsModal}
setShowUploadForm={setShowUploadForm}
handleRetriggerEvaluators={handleRetriggerEvaluators}
handleCancelInterview={handleCancelInterview}
setSelectedEvaluationForView={setSelectedEvaluationForView}
setShowFeedbackDetailsModal={setShowFeedbackDetailsModal}
renderFddAuditContent={renderFddAuditContent}
eorProgress={eorProgress}
eorData={eorData}
eorChecklist={eorChecklist}
setUploadDocType={setUploadDocType}
isAdmin={isAdmin}
fetchApplication={fetchApplication}
fetchEorData={fetchEorData}
deposits={deposits}
getDeposit={getDeposit}
paymentConfigs={paymentConfigs}
setPreviewDoc={setPreviewDoc}
setShowPreviewModal={setShowPreviewModal}
auditLoading={auditLoading}
auditLogs={auditLogs}
auditLogActionBadgeClass={auditLogActionBadgeClass}
/>
)}
</div>
<ApplicationDetailsSidebar
application={application}
permissions={permissions}
getDeposit={getDeposit}
isNonResponsive={isNonResponsive}
isAdmin={isAdmin}
currentUserStageAction={currentUserStageAction}
currentUserEvaluation={currentUserEvaluation}
onOpenApproveModal={() => setShowApproveModal(true)}
onOpenRejectModal={() => setShowRejectModal(true)}
onOpenWorknote={() => navigate(`/worknotes/application/${application.id}`, {
state: {
applicationName: application.name,
registrationNumber: application.registrationNumber,
participants: application.participants
}
})}
onOpenScheduleModal={() => setShowScheduleModal(true)}
currentUser={currentUser}
handleGenerateDealerCodes={handleGenerateDealerCodes}
onOpenAssignArchitectureModal={() => setShowAssignArchitectureModal(true)}
activeInterviewForUser={activeInterviewForUser}
hasSubmittedFeedback={hasSubmittedFeedback}
setSelectedInterviewForFeedback={setSelectedInterviewForFeedback}
setShowKTMatrixModal={setShowKTMatrixModal}
setShowLevel2FeedbackModal={setShowLevel2FeedbackModal}
setShowLevel3FeedbackModal={setShowLevel3FeedbackModal}
onGoToDashboard={() => navigate('/dashboard')}
showAssignModal={showAssignModal}
setShowAssignModal={setShowAssignModal}
selectedUser={selectedUser}
setSelectedUser={setSelectedUser}
users={users}
participantType={participantType}
setParticipantType={setParticipantType}
handleAddParticipant={handleAddParticipant}
isAssigningParticipant={isAssigningParticipant}
/>
<ApplicationDetailsActionModals
application={application}
fetchApplication={fetchApplication}
showApproveModal={showApproveModal}
setShowApproveModal={setShowApproveModal}
approvalRemark={approvalRemark}
setApprovalRemark={setApprovalRemark}
setApprovalFile={setApprovalFile}
isApproving={isApproving}
handleApprove={handleApprove}
showOnboardModal={showOnboardModal}
setShowOnboardModal={setShowOnboardModal}
isOnboarding={isOnboarding}
setIsOnboarding={setIsOnboarding}
showRejectModal={showRejectModal}
setShowRejectModal={setShowRejectModal}
rejectionReason={rejectionReason}
setRejectionReason={setRejectionReason}
isRejecting={isRejecting}
handleReject={handleReject}
showScheduleModal={showScheduleModal}
setShowScheduleModal={setShowScheduleModal}
showCancelInterviewModal={showCancelInterviewModal}
setShowCancelInterviewModal={setShowCancelInterviewModal}
setInterviewIdToCancel={setInterviewIdToCancel}
isCancellingInterview={isCancellingInterview}
handleConfirmCancelInterview={handleConfirmCancelInterview}
interviewType={interviewType}
setInterviewType={setInterviewType}
interviewMode={interviewMode}
setInterviewMode={setInterviewMode}
interviewDate={interviewDate}
setInterviewDate={setInterviewDate}
meetingLink={meetingLink}
setMeetingLink={setMeetingLink}
location={location}
setLocation={setLocation}
isInterviewCompleted={isInterviewCompleted}
isInterviewActive={isInterviewActive}
users={users}
selectedInterviewerId={selectedInterviewerId}
setSelectedInterviewerId={setSelectedInterviewerId}
handleAddInterviewer={handleAddInterviewer}
scheduledInterviewParticipants={scheduledInterviewParticipants}
handleRemoveInterviewer={handleRemoveInterviewer}
isScheduling={isScheduling}
handleScheduleInterview={handleScheduleInterview}
showAssignArchitectureModal={showAssignArchitectureModal}
setShowAssignArchitectureModal={setShowAssignArchitectureModal}
architectureLeadId={architectureLeadId}
setArchitectureLeadId={setArchitectureLeadId}
isAssigningArchitecture={isAssigningArchitecture}
handleAssignArchitecture={handleAssignArchitecture}
showArchitectureStatusModal={showArchitectureStatusModal}
setShowArchitectureStatusModal={setShowArchitectureStatusModal}
architectureStatus={architectureStatus}
setArchitectureStatus={setArchitectureStatus}
architectureRemarks={architectureRemarks}
setArchitectureRemarks={setArchitectureRemarks}
isUpdatingArchitecture={isUpdatingArchitecture}
handleUpdateArchitectureStatus={handleUpdateArchitectureStatus}
/>
<ApplicationDetailsExtendedModals
application={application}
ktCriteria={ktCriteria}
l2Fields={l2Fields}
l3Fields={l3Fields}
showKTMatrixModal={showKTMatrixModal}
setShowKTMatrixModal={setShowKTMatrixModal}
ktMatrixSelectedValues={ktMatrixSelectedValues}
handleKTMatrixChange={handleKTMatrixChange}
ktMatrixRemarks={ktMatrixRemarks}
setKtMatrixRemarks={setKtMatrixRemarks}
ktMatrixRecommendation={ktMatrixRecommendation}
setKtMatrixRecommendation={setKtMatrixRecommendation}
calculateKTScore={calculateKTScore}
handleSubmitKTMatrix={handleSubmitKTMatrix}
isSubmittingKT={isSubmittingKT}
showLevel2FeedbackModal={showLevel2FeedbackModal}
setShowLevel2FeedbackModal={setShowLevel2FeedbackModal}
level2Feedback={level2Feedback}
handleLevel2Change={handleLevel2Change}
level2Recommendation={level2Recommendation}
setLevel2Recommendation={setLevel2Recommendation}
handleSubmitLevel2Feedback={handleSubmitLevel2Feedback}
isSubmittingLevel2={isSubmittingLevel2}
showFeedbackDetailsModal={showFeedbackDetailsModal}
setShowFeedbackDetailsModal={setShowFeedbackDetailsModal}
selectedEvaluationForView={selectedEvaluationForView}
selectedInterviewForFeedback={selectedInterviewForFeedback}
showLevel3FeedbackModal={showLevel3FeedbackModal}
setShowLevel3FeedbackModal={setShowLevel3FeedbackModal}
level3Feedback={level3Feedback}
handleLevel3Change={handleLevel3Change}
level3Recommendation={level3Recommendation}
setLevel3Recommendation={setLevel3Recommendation}
handleSubmitLevel3Feedback={handleSubmitLevel3Feedback}
isSubmittingLevel3={isSubmittingLevel3}
showDocumentsModal={showDocumentsModal}
setShowDocumentsModal={setShowDocumentsModal}
showUploadForm={showUploadForm}
setShowUploadForm={setShowUploadForm}
selectedStage={selectedStage}
getDocumentsForStage={getDocumentsForStage}
setPreviewDoc={setPreviewDoc}
setShowPreviewModal={setShowPreviewModal}
flattenedStages={flattenedStages}
setSelectedStage={setSelectedStage}
uploadDocType={uploadDocType}
setUploadDocType={setUploadDocType}
setUploadFile={setUploadFile}
isUploading={isUploading}
handleUpload={handleUpload}
uploadFile={uploadFile}
documentConfigs={documentConfigs}
showPreviewModal={showPreviewModal}
previewDoc={previewDoc}
showFddFinalizeModal={showFddFinalizeModal}
setShowFddFinalizeModal={setShowFddFinalizeModal}
currentUser={currentUser}
fddAuditRecommendation={fddAuditRecommendation}
setFddAuditRecommendation={setFddAuditRecommendation}
fddAuditFindings={fddAuditFindings}
setFddAuditFindings={setFddAuditFindings}
isFinalizingFdd={isFinalizingFdd}
setIsFinalizingFdd={setIsFinalizingFdd}
fetchApplication={fetchApplication}
showFddFlagModal={showFddFlagModal}
setShowFddFlagModal={setShowFddFlagModal}
isFddFlagging={isFddFlagging}
setIsFddFlagging={setIsFddFlagging}
showFirmTypeModal={showFirmTypeModal}
setShowFirmTypeModal={setShowFirmTypeModal}
tempFirmType={tempFirmType}
setTempFirmType={setTempFirmType}
updatingFirmType={updatingFirmType}
handleUpdateFirmType={handleUpdateFirmType}
/>
</div>
</div>
);
};
export default ApplicationDetails;