/* eslint-disable @typescript-eslint/no-explicit-any */ import { useEffect, useRef, useState } from "react"; import { ExportType } from "./type"; import FactoryRenderer from "../../../../Renderer"; import { ExportDataScope } from "../../type"; import useClickOutside from "../../../../utils/useClickOutside"; interface ExportPopupProps { setTogglePopup: React.Dispatch>; onExport: (callBack: () => void, exportViewModel: ExportViewModel) => void; onExportDelete: (callBack: ((args: any) => void) | null, id: string) => void; onExportList: (callBack: ((args: any) => void) | null) => void; onExportDownload: ( callBack: ((args: any) => void) | null, id: string, ) => void; exportTypes?: string[]; dataScopes?: ExportDataScope[]; } export type ExportViewModel = { exportType: string; } & ExportDataScope; enum Status { IN_PROGRESS = "InProcess", COMPLETED = "Success", FAILED = "Error", SCHEDULED = "Scheduled", } type ExportHistoryViewModel = { id: string; fileName: string; exportType: ExportType; exportDataScope: string; date: string; status: string; src: string; referenceId: string; }; const DEFAULT_EXPORT_TYPES = Object.values(ExportType) as string[]; const DEFAULT_DATA_SCOPES: ExportDataScope[] = [ { label: "Header List", type: "header", entity: "header" }, ]; const ExportPopup = (props: ExportPopupProps) => { const exportTypes = props.exportTypes?.length ? props.exportTypes : DEFAULT_EXPORT_TYPES; const dataScopes = props.dataScopes?.length ? props.dataScopes : DEFAULT_DATA_SCOPES; const popupRef = useRef(null); const closeTimerRef = useRef | null>(null); const [exporHistoryList, setExporHistoryList] = useState< ExportHistoryViewModel[] >([]); useEffect(() => { props.onExportList((list: ExportHistoryViewModel[]) => { setExporHistoryList(list); }); }, []); // The popup only exists while it is open, so the listener is always wanted. useClickOutside( popupRef, true, () => { popupRef.current?.classList.add("tmpl-popup-animation-reverse"); // Restart the close timer rather than stacking another one, otherwise a // second outside click races the first and can close after unmount. if (closeTimerRef.current !== null) { clearTimeout(closeTimerRef.current); } closeTimerRef.current = setTimeout(() => { closeTimerRef.current = null; props.setTogglePopup(false); }, 200); }, (target) => Boolean(target.closest(`.tmpl-prvent-outside-click-close`)), ); useEffect(() => { return () => { if (closeTimerRef.current !== null) { clearTimeout(closeTimerRef.current); closeTimerRef.current = null; } }; }, []); const handleExportClick = ( exportType: string, dataScope: ExportDataScope, ) => { const exportViewModel: ExportViewModel = { exportType, ...dataScope, }; props.onExport(() => { props.onExportList((list: ExportHistoryViewModel[]) => { setExporHistoryList(list); }); }, exportViewModel); }; const downloadResultHandler = (response: any, fileName: string) => { const blob = new Blob([response]); const downloadUrl = window.URL.createObjectURL(blob); const link = document.createElement("a"); link.href = downloadUrl; link.download = fileName; document.body.appendChild(link); link.click(); window.URL.revokeObjectURL(downloadUrl); document.body.removeChild(link); }; const handleDownload = async (fileUrl: string, fileName: string) => { try { props.onExportDownload( (res) => downloadResultHandler(res, fileName), fileUrl, ); } catch (error) { console.error("Download failed:", error); } }; return (
{dataScopes.map((scope) => (

{scope.label}

{exportTypes.map((type) => ( ))}
))}

Previous Exports

{exporHistoryList?.map((exportHistoryViewModel) => { return (

{exportHistoryViewModel.fileName}

{exportHistoryViewModel.date}

{exportHistoryViewModel.status === Status.COMPLETED ? ( handleDownload( exportHistoryViewModel.referenceId, exportHistoryViewModel.fileName, ) } /> ) : exportHistoryViewModel.status === Status.FAILED ? ( ) : ( )} props.onExportDelete(() => { props.onExportList((list: ExportHistoryViewModel[]) => { setExporHistoryList(list); }); }, exportHistoryViewModel.id) } />
); })}
); }; export default ExportPopup;