Yassine Mhirsi
enhance analysis page
78b3b2b
import React, { useMemo, useState } from 'react';
import { parseCsv } from '../../utils/index.ts';
import type { CsvRow } from '../../types/index.ts';
interface UploadCsvModalProps {
isOpen: boolean;
onClose: () => void;
onAnalyze: (file: File) => Promise<void>;
isAnalyzing: boolean;
}
const UploadCsvModal = ({
isOpen,
onClose,
onAnalyze,
isAnalyzing
}: UploadCsvModalProps) => {
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [rows, setRows] = useState<CsvRow[]>([]);
const [error, setError] = useState<string | null>(null);
const fileName = useMemo(
() => selectedFile?.name ?? 'Select a CSV file with arguments',
[selectedFile]
);
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0] ?? null;
setSelectedFile(file);
setError(null);
setRows([]);
if (!file) {
return;
}
// Parse CSV
try {
const content = await file.text();
const parsed = parseCsv(content);
setRows(parsed.rows);
if (parsed.rows.length === 0) {
setError('No data found in the CSV file.');
}
} catch (err) {
setError(
err instanceof Error ? err.message : 'Unable to read the CSV file.'
);
setRows([]);
}
};
const handleAnalyze = async () => {
if (!selectedFile) {
setError('Please choose a CSV file to analyze.');
return;
}
if (rows.length === 0) {
setError('No data found in the CSV file.');
return;
}
await onAnalyze(selectedFile);
};
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 dark:bg-black/70">
<div
className="relative w-full max-w-2xl max-h-[90vh] overflow-hidden rounded-xl border border-slate-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 shadow-xl"
onClick={(e) => e.stopPropagation()}
>
<div className="flex items-center justify-between border-b border-slate-200 dark:border-zinc-700 px-6 py-4">
<h2 className="text-lg font-semibold text-slate-800 dark:text-white">
Analyze New Arguments
</h2>
<button
onClick={onClose}
className="text-slate-500 dark:text-zinc-400 hover:text-slate-700 dark:hover:text-zinc-200 transition-colors"
aria-label="Close"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
</svg>
</button>
</div>
<div className="p-6 space-y-6 overflow-y-auto max-h-[calc(90vh-140px)]">
<div className="flex flex-col gap-3">
<label className="text-sm font-medium text-slate-700 dark:text-zinc-300">
Upload a CSV file
</label>
<div className="flex flex-wrap items-center justify-between gap-3">
<label className="flex w-full max-w-xl cursor-pointer items-center justify-between rounded-full border border-slate-300 dark:border-zinc-600 bg-slate-50 dark:bg-zinc-800 px-5 py-3 transition hover:border-slate-400 dark:hover:border-zinc-500">
<span className="truncate text-sm font-semibold text-slate-500 dark:text-zinc-400">
{fileName}
</span>
<input
type="file"
accept=".csv,text/csv"
className="hidden"
onChange={handleFileChange}
/>
</label>
<div className="flex w-full justify-center">
<button
type="button"
onClick={handleAnalyze}
disabled={!selectedFile || rows.length === 0 || isAnalyzing}
className="rounded-md bg-blue-600 dark:bg-blue-500 px-4 py-2 text-sm font-semibold text-white transition hover:bg-blue-700 dark:hover:bg-blue-600 disabled:cursor-not-allowed disabled:opacity-60"
>
{isAnalyzing ? 'Analyzing...' : 'Analyze'}
</button>
</div>
</div>
{error && <p className="text-sm text-red-600 dark:text-red-400">{error}</p>}
</div>
{isAnalyzing && (
<div className="flex items-center justify-center py-8">
<div className="flex flex-col items-center">
<div className="h-10 w-10 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div>
<p className="mt-3 text-sm text-slate-600 dark:text-zinc-400">Analyzing arguments...</p>
</div>
</div>
)}
</div>
</div>
</div>
);
};
export default UploadCsvModal;