/** * Global Import/Export Configuration System * Provides reusable import/export configs for table pages * * Usage: * ```typescript * import { useImportExport } from '@/config/import-export.config'; * * const { handleExport, handleImport, ImportModal } = useImportExport({ * exportEndpoint: '/v1/planner/keywords/export/', * importEndpoint: '/v1/planner/keywords/import_keywords/', * filename: 'keywords', * formats: ['csv', 'json'], * onImportSuccess: () => loadData(), * }); * ``` */ import React, { useState, useCallback } from 'react'; import { exportTableData, importTableData, ExportConfig, ImportConfig } from '../utils/table-import-export'; import { Modal } from '../components/ui/modal'; import Button from '../components/ui/button/Button'; import FileInput from '../components/form/input/FileInput'; import Label from '../components/form/Label'; export interface ImportExportConfigOptions { exportEndpoint: string; importEndpoint: string; filename: string; formats?: ('csv' | 'json')[]; acceptedFormats?: string[]; maxFileSize?: number; importQueryParams?: Record; // Query params for import (e.g., site_id, sector_id) onImportSuccess?: (result: any) => void; onExportSuccess?: () => void; onError?: (error: Error) => void; } export interface ImportExportHandlers { handleExport: (format?: 'csv' | 'json', filters?: Record) => Promise; handleImportClick: () => void; ImportModal: React.FC; } /** * React hook for import/export functionality */ export function useImportExport( options: ImportExportConfigOptions ): ImportExportHandlers { const { exportEndpoint, importEndpoint, filename, formats = ['csv'], acceptedFormats = ['.csv'], maxFileSize = 5 * 1024 * 1024, // 5MB default onImportSuccess, onExportSuccess, onError, } = options; const [isImportModalOpen, setIsImportModalOpen] = useState(false); const [isProcessing, setIsProcessing] = useState(false); const handleExport = useCallback(async ( format: 'csv' | 'json' = 'csv', filters: Record = {} ) => { setIsProcessing(true); try { const exportConfig: ExportConfig = { endpoint: exportEndpoint, filename, format, filters, }; await exportTableData( exportConfig, (progress) => console.log(progress), (error) => { onError?.(error); throw error; } ); onExportSuccess?.(); } catch (error) { const err = error instanceof Error ? error : new Error('Export failed'); onError?.(err); throw err; } finally { setIsProcessing(false); } }, [exportEndpoint, filename, onError, onExportSuccess]); const handleImport = useCallback(async (file: File) => { setIsProcessing(true); try { const importConfig: ImportConfig = { endpoint: importEndpoint, acceptedFormats, maxFileSize, queryParams: options.importQueryParams, onSuccess: (result) => { onImportSuccess?.(result); }, }; const result = await importTableData( file, importConfig, (progress) => console.log(progress), (error) => { onError?.(error); throw error; } ); setIsImportModalOpen(false); return result; } catch (error) { const err = error instanceof Error ? error : new Error('Import failed'); onError?.(err); throw err; } finally { setIsProcessing(false); } }, [importEndpoint, acceptedFormats, maxFileSize, onImportSuccess, onError]); const handleImportFileChange = useCallback(async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; await handleImport(file); // Reset file input e.target.value = ''; }, [handleImport]); const ImportModalComponent: React.FC = () => ( setIsImportModalOpen(false)} className="max-w-md" >

Import {filename.charAt(0).toUpperCase() + filename.slice(1)}

Upload a CSV file (max {maxFileSize / 1024 / 1024}MB)

{filename === 'keywords' && (

Expected columns: keyword, volume, difficulty, country, status

)}
); return { handleExport, handleImportClick: () => setIsImportModalOpen(true), ImportModal: ImportModalComponent, }; } /** * Pre-configured import/export hooks for common modules */ export const useKeywordsImportExport = ( onImportSuccess?: () => void, onError?: (error: Error) => void, importQueryParams?: Record ) => { return useImportExport({ exportEndpoint: '/v1/planner/keywords/export/', importEndpoint: '/v1/planner/keywords/import_keywords/', filename: 'keywords', formats: ['csv', 'json'], acceptedFormats: ['.csv'], maxFileSize: 5 * 1024 * 1024, importQueryParams, onImportSuccess, onError, }); }; export const useClustersImportExport = (onImportSuccess?: () => void, onError?: (error: Error) => void) => { return useImportExport({ exportEndpoint: '/v1/planner/clusters/export/', importEndpoint: '/v1/planner/clusters/import_clusters/', filename: 'clusters', formats: ['csv', 'json'], acceptedFormats: ['.csv'], maxFileSize: 5 * 1024 * 1024, onImportSuccess, onError, }); };