add file viewer functionality across various components

- Implemented a shared file viewer modal using `useFileViewer` hook to allow inline viewing of documents (images, PDFs, videos, etc.) across the application.
- Updated `ContractClearanceReviewSection`, `ContractRequestDetailPage`, `ContractViewPage`, and booking-related components to utilize the new file viewer for document previews.
- Added "Approve all" button in `ContractClearanceReviewSection` to bulk approve documents.
- Enhanced document action buttons to include view and download options based on file type.
- Introduced `isViewable` utility to determine if a file can be previewed inline.
- Created `FileViewer` component to handle rendering of various file types and added appropriate fallback for unsupported formats.
This commit is contained in:
Marshal
2026-06-27 19:18:43 +00:00
parent e977893888
commit 0ab553bf48
19 changed files with 893 additions and 116 deletions

View File

@@ -227,6 +227,29 @@ export function useContractClearanceMutations(
onError: () => toast.error("Could not update document"),
});
// Approve every still-pending customer document in one click. There is no
// server-side bulk endpoint, so fan out the single-document review calls and
// refresh once after they all settle.
const approveAll = useMutation({
mutationFn: async (fileKeys: string[]) => {
const review = selfClear
? contractsService.opsReviewClearanceDocument
: contractsService.reviewClearanceDocument;
await Promise.all(
fileKeys.map((fileKey) =>
review(contractId, { fileKey, status: "APPROVED" }),
),
);
},
onSuccess: (_d, fileKeys) => {
toast.success(
`${fileKeys.length} document${fileKeys.length === 1 ? "" : "s"} approved`,
);
refresh();
},
onError: () => toast.error("Could not approve all documents"),
});
const uploadOutputDocuments = useMutation({
mutationFn: (files: Record<string, File | null>) =>
contractsService.uploadClearanceOutput(contractId, files),
@@ -256,7 +279,7 @@ export function useContractClearanceMutations(
),
});
return { reviewDocument, uploadOutputDocuments, finalizeClearance };
return { reviewDocument, approveAll, uploadOutputDocuments, finalizeClearance };
}
/** Complete a post-booking GL milestone. */