diff --git a/inventory/src/App.tsx b/inventory/src/App.tsx index e2d8a61..5c0e24f 100644 --- a/inventory/src/App.tsx +++ b/inventory/src/App.tsx @@ -14,8 +14,8 @@ function App() { return ( + - } /> } /> diff --git a/inventory/src/pages/Settings.tsx b/inventory/src/pages/Settings.tsx index d9cc33e..0b6c36b 100644 --- a/inventory/src/pages/Settings.tsx +++ b/inventory/src/pages/Settings.tsx @@ -4,7 +4,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com import { Progress } from "@/components/ui/progress"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Alert, AlertDescription } from "@/components/ui/alert"; +import { toast } from "sonner"; import { AlertDialog, AlertDialogAction, @@ -61,7 +61,13 @@ export function Settings() { // Clean up function to reset state const handleCancel = async () => { - // Just clean up everything immediately + // Determine which operation is running first + const operation = isImporting ? 'Import' : isUpdating ? 'Update' : 'Reset'; + + // Show cancellation toast immediately + toast.warning(`${operation} cancelled`); + + // Clean up everything immediately if (eventSource) { eventSource.close(); setEventSource(null); @@ -74,11 +80,15 @@ export function Settings() { setResetProgress(null); // Fire and forget the cancel request with the operation type - const operation = isImporting ? 'import' : isUpdating ? 'update' : 'reset'; - fetch(`${config.apiUrl}/csv/cancel?operation=${operation}`, { - method: 'POST', - credentials: 'include' - }).catch(() => {}); + try { + await fetch(`${config.apiUrl}/csv/cancel?operation=${operation.toLowerCase()}`, { + method: 'POST', + credentials: 'include' + }); + } catch (error) { + // Silently ignore any errors from the cancel request + console.log('Cancel request failed:', error); + } }; const handleUpdateCSV = async () => { @@ -161,17 +171,15 @@ export function Settings() { source.close(); setEventSource(null); setIsUpdating(false); - setIsImporting(false); + setUpdateProgress(null); if (!progressData.operation?.includes('cancelled')) { - setTimeout(() => { - setUpdateProgress(null); - }, 1000); + handleComplete('CSV update'); } - } else if (progressData.status === 'error' && !progressData.operation?.includes('cancelled')) { + } else if (progressData.status === 'error') { source.close(); setEventSource(null); setIsUpdating(false); - setIsImporting(false); + handleError('CSV update', progressData.error || 'Unknown error'); } } catch (error) { // Silently handle parsing errors @@ -193,10 +201,8 @@ export function Settings() { setEventSource(null); } setIsUpdating(false); - // Don't show any errors if we're cleaning up - if (updateProgress?.status === 'running') { - setUpdateProgress(null); - } + setUpdateProgress(null); + handleError('CSV update', error instanceof Error ? error.message : 'Unknown error'); } }; @@ -281,16 +287,16 @@ export function Settings() { setEventSource(null); setIsUpdating(false); setIsImporting(false); + setImportProgress(null); if (!progressData.operation?.includes('cancelled')) { - setTimeout(() => { - setImportProgress(null); - }, 1000); + handleComplete('Data import'); } - } else if (progressData.status === 'error' && !progressData.operation?.includes('cancelled')) { + } else if (progressData.status === 'error') { source.close(); setEventSource(null); setIsUpdating(false); setIsImporting(false); + handleError('Data import', progressData.error || 'Unknown error'); } } catch (error) { // Silently handle parsing errors @@ -316,10 +322,8 @@ export function Settings() { setEventSource(null); } setIsImporting(false); - // Don't show any errors if we're cleaning up - if (importProgress?.status === 'running') { - setImportProgress(null); - } + setImportProgress(null); + handleError('Data import', error instanceof Error ? error.message : 'Unknown error'); } }; @@ -403,15 +407,15 @@ export function Settings() { source.close(); setEventSource(null); setIsResetting(false); + setResetProgress(null); if (!progressData.operation?.includes('cancelled')) { - setTimeout(() => { - setResetProgress(null); - }, 1000); + handleComplete('Database reset'); } - } else if (progressData.status === 'error' && !progressData.operation?.includes('cancelled')) { + } else if (progressData.status === 'error') { source.close(); setEventSource(null); setIsResetting(false); + handleError('Database reset', progressData.error || 'Unknown error'); } } catch (error) { // Silently handle parsing errors @@ -433,10 +437,8 @@ export function Settings() { setEventSource(null); } setIsResetting(false); - // Don't show any errors if we're cleaning up - if (resetProgress?.status === 'running') { - setResetProgress(null); - } + setResetProgress(null); + handleError('Database reset', error instanceof Error ? error.message : 'Unknown error'); } }; @@ -471,31 +473,26 @@ export function Settings() { )} - - {(progress.elapsed || progress.remaining) && ( -
- {progress.elapsed && Elapsed: {progress.elapsed}} - {progress.remaining && Remaining: {progress.remaining}} -
- )} - - {progress.message && ( -
- {progress.message} -
- )} - - {progress.error && ( - - - {progress.error} - - - )} ); }; + const handleError = (operation: string, error: string) => { + // Skip error toast if we're cancelling or if it's a cancellation error + if (error.includes('cancelled') || + error.includes('Process exited with code 143') || + error.includes('Operation cancelled') || + error.includes('500 Internal Server Error')) { + return; + } + toast.error(`${operation} failed: ${error}`); + }; + + // Update the message handlers to use toast + const handleComplete = (operation: string) => { + toast.success(`${operation} completed successfully`); + }; + return (