legal-doc-masker/frontend/src/components/FileList.tsx

144 lines
4.0 KiB
TypeScript

import React, { useState } from 'react';
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
IconButton,
Checkbox,
Button,
Chip,
} from '@mui/material';
import { Download as DownloadIcon } from '@mui/icons-material';
import { File, FileStatus } from '../types/file';
import { api } from '../services/api';
interface FileListProps {
files: File[];
onFileStatusChange: () => void;
}
const FileList: React.FC<FileListProps> = ({ files, onFileStatusChange }) => {
const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
const handleSelectFile = (fileId: string) => {
setSelectedFiles((prev) =>
prev.includes(fileId)
? prev.filter((id) => id !== fileId)
: [...prev, fileId]
);
};
const handleSelectAll = () => {
setSelectedFiles((prev) =>
prev.length === files.length ? [] : files.map((file) => file.id)
);
};
const handleDownload = async (fileId: string) => {
try {
const blob = await api.downloadFile(fileId);
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = files.find((f) => f.id === fileId)?.filename || 'downloaded-file';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} catch (error) {
console.error('Error downloading file:', error);
}
};
const handleDownloadSelected = async () => {
for (const fileId of selectedFiles) {
await handleDownload(fileId);
}
};
const getStatusColor = (status: FileStatus) => {
switch (status) {
case FileStatus.SUCCESS:
return 'success';
case FileStatus.FAILED:
return 'error';
case FileStatus.PROCESSING:
return 'warning';
default:
return 'default';
}
};
return (
<div>
<div style={{ marginBottom: '1rem' }}>
<Button
variant="contained"
color="primary"
onClick={handleDownloadSelected}
disabled={selectedFiles.length === 0}
>
Download Selected
</Button>
</div>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
checked={selectedFiles.length === files.length}
indeterminate={selectedFiles.length > 0 && selectedFiles.length < files.length}
onChange={handleSelectAll}
/>
</TableCell>
<TableCell>Filename</TableCell>
<TableCell>Status</TableCell>
<TableCell>Created At</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{files.map((file) => (
<TableRow key={file.id}>
<TableCell padding="checkbox">
<Checkbox
checked={selectedFiles.includes(file.id)}
onChange={() => handleSelectFile(file.id)}
/>
</TableCell>
<TableCell>{file.filename}</TableCell>
<TableCell>
<Chip
label={file.status}
color={getStatusColor(file.status) as any}
size="small"
/>
</TableCell>
<TableCell>
{new Date(file.created_at).toLocaleString()}
</TableCell>
<TableCell>
{file.status === FileStatus.SUCCESS && (
<IconButton
onClick={() => handleDownload(file.id)}
size="small"
>
<DownloadIcon />
</IconButton>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</div>
);
};
export default FileList;