feat(upload): improve file upload progress and error handling
- Add persistent progress bars and error states - Remove individual file toasts in favor of batch status - Keep dialog open until manual close - Move Progress component inline to reduce dependencies
This commit is contained in:
@@ -21,37 +21,65 @@ export default function UploadDocumentsDialog() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [isUploading, setIsUploading] = useState(false)
|
||||
const [progresses, setProgresses] = useState<Record<string, number>>({})
|
||||
// Track upload errors for each file
|
||||
const [fileErrors, setFileErrors] = useState<Record<string, string>>({})
|
||||
|
||||
const handleDocumentsUpload = useCallback(
|
||||
async (filesToUpload: File[]) => {
|
||||
setIsUploading(true)
|
||||
|
||||
// Reset error states before new upload
|
||||
setFileErrors({})
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
filesToUpload.map(async (file) => {
|
||||
// Use a single toast for the entire batch upload process
|
||||
toast.promise(
|
||||
(async () => {
|
||||
try {
|
||||
const result = await uploadDocument(file, (percentCompleted: number) => {
|
||||
console.debug(t('documentPanel.uploadDocuments.uploading', { name: file.name, percent: percentCompleted }))
|
||||
setProgresses((pre) => ({
|
||||
...pre,
|
||||
[file.name]: percentCompleted
|
||||
}))
|
||||
})
|
||||
if (result.status === 'success') {
|
||||
toast.success(t('documentPanel.uploadDocuments.success', { name: file.name }))
|
||||
} else {
|
||||
toast.error(t('documentPanel.uploadDocuments.failed', { name: file.name, message: result.message }))
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error(t('documentPanel.uploadDocuments.error', { name: file.name, error: errorMessage(err) }))
|
||||
await Promise.all(
|
||||
filesToUpload.map(async (file) => {
|
||||
try {
|
||||
const result = await uploadDocument(file, (percentCompleted: number) => {
|
||||
console.debug(t('documentPanel.uploadDocuments.uploading', { name: file.name, percent: percentCompleted }))
|
||||
setProgresses((pre) => ({
|
||||
...pre,
|
||||
[file.name]: percentCompleted
|
||||
}))
|
||||
})
|
||||
|
||||
// Store error message if upload failed
|
||||
if (result.status !== 'success') {
|
||||
setFileErrors(prev => ({
|
||||
...prev,
|
||||
[file.name]: result.message
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
// Store error message from exception
|
||||
setFileErrors(prev => ({
|
||||
...prev,
|
||||
[file.name]: errorMessage(err)
|
||||
}))
|
||||
}
|
||||
})
|
||||
)
|
||||
// Keep dialog open to show final status
|
||||
// User needs to close dialog manually
|
||||
} catch (error) {
|
||||
console.error('Upload failed:', error)
|
||||
}
|
||||
})
|
||||
})(),
|
||||
{
|
||||
loading: t('documentPanel.uploadDocuments.uploading.batch'),
|
||||
success: t('documentPanel.uploadDocuments.success.batch'),
|
||||
error: t('documentPanel.uploadDocuments.error.batch')
|
||||
}
|
||||
)
|
||||
} catch (err) {
|
||||
toast.error(t('documentPanel.uploadDocuments.generalError', { error: errorMessage(err) }))
|
||||
// Handle general upload errors
|
||||
toast.error(`Upload error: ${errorMessage(err)}`)
|
||||
} finally {
|
||||
setIsUploading(false)
|
||||
// setOpen(false)
|
||||
}
|
||||
},
|
||||
[setIsUploading, setProgresses, t]
|
||||
@@ -61,9 +89,15 @@ export default function UploadDocumentsDialog() {
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (isUploading && !open) {
|
||||
// Prevent closing dialog during upload
|
||||
if (isUploading) {
|
||||
return
|
||||
}
|
||||
if (!open) {
|
||||
// Reset states when dialog is closed
|
||||
setProgresses({})
|
||||
setFileErrors({})
|
||||
}
|
||||
setOpen(open)
|
||||
}}
|
||||
>
|
||||
@@ -85,6 +119,7 @@ export default function UploadDocumentsDialog() {
|
||||
description={t('documentPanel.uploadDocuments.fileTypes')}
|
||||
onUpload={handleDocumentsUpload}
|
||||
progresses={progresses}
|
||||
fileErrors={fileErrors}
|
||||
disabled={isUploading}
|
||||
/>
|
||||
</DialogContent>
|
||||
|
Reference in New Issue
Block a user