/** * useCSVHandling Hook - Manages CSV upload and download operations */ import { useState, useCallback } from 'react'; import axios from 'axios'; import { useAppDispatch } from '../stores/hooks'; import type { AsyncThunk } from '@reduxjs/toolkit'; import { logger } from '../lib/logger'; interface UseCSVHandlingReturn { csvFile: File | null; setCsvFile: (file: File | null) => void; isModalActive: boolean; setIsModalActive: (active: boolean) => void; isUploading: boolean; isDownloading: boolean; downloadCSV: () => Promise; uploadCSV: () => Promise; error: string | null; } interface UseCSVHandlingOptions { endpoint: string; uploadAction: AsyncThunk< { imported: number }, File, { rejectValue: unknown } >; setRefetchAction: (value: boolean) => { type: string; payload: boolean }; fileName?: string; } /** * Hook for handling CSV upload and download operations * * @param options - Configuration options * @returns CSV handling state and functions * * @example * ```typescript * const { * csvFile, * setCsvFile, * isModalActive, * setIsModalActive, * downloadCSV, * uploadCSV * } = useCSVHandling({ * endpoint: 'users', * uploadAction: uploadCsv, * setRefetchAction: setRefetch * }) * ``` */ export function useCSVHandling( options: UseCSVHandlingOptions, ): UseCSVHandlingReturn { const { endpoint, uploadAction, setRefetchAction, fileName } = options; const dispatch = useAppDispatch(); const [csvFile, setCsvFile] = useState(null); const [isModalActive, setIsModalActive] = useState(false); const [isUploading, setIsUploading] = useState(false); const [isDownloading, setIsDownloading] = useState(false); const [error, setError] = useState(null); const downloadCSV = useCallback(async () => { setIsDownloading(true); setError(null); try { const response = await axios({ url: `${endpoint}?filetype=csv`, method: 'GET', responseType: 'blob', }); const contentType = (response.headers['content-type'] as string) || 'text/csv'; const blob = new Blob([response.data], { type: contentType }); const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = fileName || `${endpoint}.csv`; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(link.href); } catch (err) { const message = err instanceof Error ? err.message : 'Failed to download CSV'; setError(message); logger.error( 'CSV download error:', err instanceof Error ? err : { error: err }, ); } finally { setIsDownloading(false); } }, [endpoint, fileName]); const uploadCSV = useCallback(async () => { if (!csvFile) { setError('No file selected'); return; } setIsUploading(true); setError(null); try { await dispatch(uploadAction(csvFile)).unwrap(); dispatch(setRefetchAction(true)); setCsvFile(null); setIsModalActive(false); } catch (err) { const message = err instanceof Error ? err.message : 'Failed to upload CSV'; setError(message); logger.error( 'CSV upload error:', err instanceof Error ? err : { error: err }, ); } finally { setIsUploading(false); } }, [csvFile, dispatch, uploadAction, setRefetchAction]); return { csvFile, setCsvFile, isModalActive, setIsModalActive, isUploading, isDownloading, downloadCSV, uploadCSV, error, }; } export default useCSVHandling;