import React, { useState, useEffect } from "react"; import { Paper, Button, Checkbox, Stack, Text, Group, Loader, Alert } from "@mantine/core"; import { useSearchParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { FileWithUrl } from "../types/file"; import { fileStorage } from "../services/fileStorage"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; export interface MergePdfPanelProps { files: FileWithUrl[]; setDownloadUrl: (url: string) => void; params: { order: string; removeDuplicates: boolean; }; updateParams: (newParams: Partial) => void; } const MergePdfPanel: React.FC = ({ files, setDownloadUrl, params, updateParams, }) => { const { t } = useTranslation(); const [selectedFiles, setSelectedFiles] = useState([]); const [downloadUrl, setLocalDownloadUrl] = useState(null); const [isLoading, setIsLoading] = useState(false); const [errorMessage, setErrorMessage] = useState(null); const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled("merge-pdfs"); useEffect(() => { setSelectedFiles(files.map(() => true)); }, [files]); const handleMerge = async () => { const filesToMerge = files.filter((_, index) => selectedFiles[index]); if (filesToMerge.length < 2) { setErrorMessage(t("multiPdfPrompt")); // "Select PDFs (2+)" return; } const formData = new FormData(); // Handle IndexedDB files for (const file of filesToMerge) { if (!file.id) { continue; // Skip files without an id } const storedFile = await fileStorage.getFile(file?.id); if (storedFile) { const blob = new Blob([storedFile.data], { type: storedFile.type }); const actualFile = new File([blob], storedFile.name, { type: storedFile.type, lastModified: storedFile.lastModified }); formData.append("fileInput", actualFile); } } setIsLoading(true); setErrorMessage(null); try { const response = await fetch("/api/v1/general/merge-pdfs", { method: "POST", body: formData, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Failed to merge PDFs: ${errorText}`); } const blob = await response.blob(); const url = URL.createObjectURL(blob); setDownloadUrl(url); setLocalDownloadUrl(url); } catch (error: any) { setErrorMessage(error.message || "Unknown error occurred."); } finally { setIsLoading(false); } }; const handleCheckboxChange = (index: number) => { setSelectedFiles((prev) => prev.map((selected, i) => (i === index ? !selected : selected)) ); }; const selectedCount = selectedFiles.filter(Boolean).length; const { order, removeDuplicates } = params; if (endpointLoading) { return ( {t("loading", "Loading...")} ); } if (endpointEnabled === false) { return ( {t("endpointDisabled", "This feature is currently disabled.")} ); } return ( {t("merge.header")} {files.map((file, index) => ( handleCheckboxChange(index)} /> {file.name} ))} {selectedCount < 2 && ( {t("multiPdfPrompt")} )} {errorMessage && ( {errorMessage} )} {downloadUrl && ( )} updateParams({ removeDuplicates: !removeDuplicates })} /> ); }; export default MergePdfPanel;