import { CLAIM_CAR_ANGLE_KEYS, hasClaimCarAngleCapture, hasDamagedPartCapture, } from "src/helpers/claim-car-angle-media"; import { catalogLikeKeyFromPart, normalizeDamageSelectedParts, } from "src/helpers/outer-damage-parts"; import type { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog"; /** Upload during CAPTURE_PART_DAMAGES (after parts + angles). */ export const CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS = [ "damaged_chassis_number", "damaged_engine_photo", "damaged_metal_plate", ] as const; export type CapturePhaseSequence = | "parts" | "angles" | "capture_phase_documents" | "complete"; export interface ClaimCaptureProgress { partsCaptured: number; partsTotal: number; partsComplete: boolean; anglesCaptured: number; anglesTotal: number; anglesComplete: boolean; capturePhaseDocsComplete: boolean; capturePhaseDocsRemaining: number; sequencePhase: CapturePhaseSequence; } export function isCapturePhaseDamagedPartyDocKey(key: string): boolean { return (CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS as readonly string[]).includes( key, ); } function isRequiredDocumentUploadedOnClaim( claimCase: any, key: string, ): boolean { const doc = (claimCase?.requiredDocuments as any)?.get?.(key) ?? claimCase?.requiredDocuments?.[key]; return !!doc?.uploaded; } export function getClaimCaptureProgress( claimCase: any, options?: { assumeCapturePhaseDocKey?: string }, ): ClaimCaptureProgress { const carType = claimCase?.vehicle?.carType as ClaimVehicleTypeV2 | undefined; const selectedNorm = normalizeDamageSelectedParts( claimCase?.damage?.selectedParts, carType, claimCase?.damage?.selectedOuterParts, ); const carAnglesData = claimCase?.media?.carAngles; const damagedPartsData = claimCase?.media?.damagedParts; const anglesCaptured = CLAIM_CAR_ANGLE_KEYS.filter((k) => hasClaimCarAngleCapture(carAnglesData, damagedPartsData, k), ).length; const partsCaptured = selectedNorm.filter((sp) => { const ck = sp.catalogKey ?? catalogLikeKeyFromPart(sp); return hasDamagedPartCapture(damagedPartsData, ck, selectedNorm); }).length; const partsTotal = selectedNorm.length; const partsComplete = partsTotal === 0 || partsCaptured >= partsTotal; const anglesTotal = CLAIM_CAR_ANGLE_KEYS.length; const anglesComplete = anglesCaptured >= anglesTotal; const capturePhaseDocsRemaining = CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.filter( (k) => { if (k === options?.assumeCapturePhaseDocKey) return false; return !isRequiredDocumentUploadedOnClaim(claimCase, k); }, ).length; const capturePhaseDocsComplete = capturePhaseDocsRemaining === 0; let sequencePhase: CapturePhaseSequence = "parts"; if (partsComplete && !anglesComplete) { sequencePhase = "angles"; } else if (partsComplete && anglesComplete && !capturePhaseDocsComplete) { sequencePhase = "capture_phase_documents"; } else if (partsComplete && anglesComplete && capturePhaseDocsComplete) { sequencePhase = "complete"; } return { partsCaptured, partsTotal, partsComplete, anglesCaptured, anglesTotal, anglesComplete, capturePhaseDocsComplete, capturePhaseDocsRemaining, sequencePhase, }; } export function isClaimCaptureStepComplete(claimCase: any): boolean { const p = getClaimCaptureProgress(claimCase); return ( p.partsComplete && p.anglesComplete && p.capturePhaseDocsComplete ); } export function capturePhaseSequenceMessage(phase: CapturePhaseSequence): string { switch (phase) { case "parts": return "Upload photos for all selected damaged parts first."; case "angles": return "Capture all four car angles (front, back, left, right) next."; case "capture_phase_documents": return "Upload chassis number, engine photo, and damaged metal plate photos last."; default: return "Damage capture is complete."; } }