import { MAX_PHOTOS_PER_WORK_ORDER, MAX_VIDEOS_PER_WORK_ORDER, MAX_VIDEO_DURATION_SECONDS, resolveWorkOrderUploadKind, workOrderFileSizeRejection, type WorkOrderMediaKindCounts, } from "@/domain/work-orders/utils/work-order-media-limits"; import { probeVideoDurationSeconds } from "@/lib/probe-video-duration"; export type WorkOrderUploadScreen = { /** Photos and videos already on the work order, across every surface. */ existing: WorkOrderMediaKindCounts; isTypeAllowed: (file: File) => boolean; unsupportedTypeMessage: string; }; export type WorkOrderUploadScreenResult = { accepted: File[]; rejections: string[] }; /** * SH-116 browser pre-check shared by every dispatcher upload surface: type, size, * per-work-order photo/video count (including earlier files in the same selection) * and video duration. The server enforces the same contract; a video whose duration * the browser cannot read is never blocked here. */ export async function screenWorkOrderUploads( files: readonly File[], { existing, isTypeAllowed, unsupportedTypeMessage }: WorkOrderUploadScreen, ): Promise { const counts = { ...existing }; const accepted: File[] = []; const rejections: string[] = []; for (const file of files) { if (!isTypeAllowed(file)) { rejections.push(unsupportedTypeMessage); continue; } const sizeRejection = workOrderFileSizeRejection(file); if (sizeRejection) { rejections.push(sizeRejection); continue; } const kind = resolveWorkOrderUploadKind(file); if (kind === "photo" && counts.photos >= MAX_PHOTOS_PER_WORK_ORDER) { rejections.push(`A work order can have at most ${MAX_PHOTOS_PER_WORK_ORDER} photos.`); continue; } if (kind === "video" && counts.videos >= MAX_VIDEOS_PER_WORK_ORDER) { rejections.push(`A work order can have at most ${MAX_VIDEOS_PER_WORK_ORDER} videos.`); continue; } if (kind === "video") { const duration = await probeVideoDurationSeconds(file); if (duration != null && duration > MAX_VIDEO_DURATION_SECONDS) { rejections.push(`Videos must be ${MAX_VIDEO_DURATION_SECONDS} seconds or shorter.`); continue; } } if (kind === "photo") counts.photos += 1; if (kind === "video") counts.videos += 1; accepted.push(file); } return { accepted, rejections }; }