import { useRef, useState } from "react"; import { useMutation } from "@tanstack/react-query"; import { VendorPortalFeedback } from "@/app/v/_components/vendor-portal-feedback"; import { vendorPortalApi } from "@/domain/vendor-portal/api/vendor-portal-api"; import { validateVendorDocument } from "@/domain/vendor-portal/lib/document-validation"; import type { VendorPortalDocument } from "@/domain/vendor-portal/types/vendor-portal"; type VendorPortalDocumentsProps = { token: string; dispatchId: number; documents: VendorPortalDocument[]; locked: boolean; onChanged: () => Promise; }; type UploadRequest = { file: File; replacementId?: number; }; export function VendorPortalDocuments({ token, dispatchId, documents, locked, onChanged, }: VendorPortalDocumentsProps) { const inputRef = useRef(null); const [replacementId, setReplacementId] = useState(); const [progress, setProgress] = useState(); const [validationError, setValidationError] = useState(); const uploadMutation = useMutation({ mutationFn: ({ file, replacementId: requestedReplacementId }: UploadRequest) => vendorPortalApi.uploadDocument({ token, dispatchId, file, replacesDocumentId: requestedReplacementId, onProgress: setProgress, }), onSuccess: onChanged, onSettled: () => { setProgress(undefined); setReplacementId(undefined); if (inputRef.current) { inputRef.current.value = ""; } }, }); const chooseFile = (documentId?: number) => { setValidationError(undefined); uploadMutation.reset(); setReplacementId(documentId); inputRef.current?.click(); }; const uploadSelectedFile = async (file?: File) => { if (!file) { return; } const validationMessage = await validateVendorDocument(file); if (validationMessage) { setValidationError(validationMessage); return; } setValidationError(undefined); setProgress(0); uploadMutation.mutate({ file, replacementId }); }; const uploadError = validationError ?? (uploadMutation.error ? "Unable to upload the document. Please try again." : undefined); return ( <> void uploadSelectedFile(event.target.files?.[0])} /> {documents.length === 0 && ( No completion documents uploaded. )} {documents.map((document) => (
File {document.originalFileName} · v{document.version}
Security scan {document.scanStatus}
Review {document.reviewStatus}
{Boolean(document.rejectionReason) && ( {document.rejectionReason} )}
{!locked && ( )}
))} {progress !== undefined && (
Uploading… {progress}%
)} {Boolean(uploadError) && ( {uploadError} )} {!locked && (
Accepted: PDF, JPG, PNG, HEIC, MP4, MOV · Photos up to 10 MB · Videos up to 100 MB and 90 s
)} ); }