Convert errors/confirmations to toasts

This commit is contained in:
2025-01-10 15:59:05 -05:00
parent 4ae012d9dd
commit e28c26c8da
2 changed files with 52 additions and 55 deletions

View File

@@ -14,8 +14,8 @@ function App() {
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<Router> <Router>
<Toaster richColors position="top-center" />
<MainLayout> <MainLayout>
<Toaster />
<Routes> <Routes>
<Route path="/" element={<Dashboard />} /> <Route path="/" element={<Dashboard />} />
<Route path="/products" element={<Products />} /> <Route path="/products" element={<Products />} />

View File

@@ -4,7 +4,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
import { Progress } from "@/components/ui/progress"; import { Progress } from "@/components/ui/progress";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Alert, AlertDescription } from "@/components/ui/alert"; import { toast } from "sonner";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -61,7 +61,13 @@ export function Settings() {
// Clean up function to reset state // Clean up function to reset state
const handleCancel = async () => { 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) { if (eventSource) {
eventSource.close(); eventSource.close();
setEventSource(null); setEventSource(null);
@@ -74,11 +80,15 @@ export function Settings() {
setResetProgress(null); setResetProgress(null);
// Fire and forget the cancel request with the operation type // Fire and forget the cancel request with the operation type
const operation = isImporting ? 'import' : isUpdating ? 'update' : 'reset'; try {
fetch(`${config.apiUrl}/csv/cancel?operation=${operation}`, { await fetch(`${config.apiUrl}/csv/cancel?operation=${operation.toLowerCase()}`, {
method: 'POST', method: 'POST',
credentials: 'include' credentials: 'include'
}).catch(() => {}); });
} catch (error) {
// Silently ignore any errors from the cancel request
console.log('Cancel request failed:', error);
}
}; };
const handleUpdateCSV = async () => { const handleUpdateCSV = async () => {
@@ -161,17 +171,15 @@ export function Settings() {
source.close(); source.close();
setEventSource(null); setEventSource(null);
setIsUpdating(false); setIsUpdating(false);
setIsImporting(false);
if (!progressData.operation?.includes('cancelled')) {
setTimeout(() => {
setUpdateProgress(null); setUpdateProgress(null);
}, 1000); if (!progressData.operation?.includes('cancelled')) {
handleComplete('CSV update');
} }
} else if (progressData.status === 'error' && !progressData.operation?.includes('cancelled')) { } else if (progressData.status === 'error') {
source.close(); source.close();
setEventSource(null); setEventSource(null);
setIsUpdating(false); setIsUpdating(false);
setIsImporting(false); handleError('CSV update', progressData.error || 'Unknown error');
} }
} catch (error) { } catch (error) {
// Silently handle parsing errors // Silently handle parsing errors
@@ -193,10 +201,8 @@ export function Settings() {
setEventSource(null); setEventSource(null);
} }
setIsUpdating(false); 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); setEventSource(null);
setIsUpdating(false); setIsUpdating(false);
setIsImporting(false); setIsImporting(false);
if (!progressData.operation?.includes('cancelled')) {
setTimeout(() => {
setImportProgress(null); setImportProgress(null);
}, 1000); if (!progressData.operation?.includes('cancelled')) {
handleComplete('Data import');
} }
} else if (progressData.status === 'error' && !progressData.operation?.includes('cancelled')) { } else if (progressData.status === 'error') {
source.close(); source.close();
setEventSource(null); setEventSource(null);
setIsUpdating(false); setIsUpdating(false);
setIsImporting(false); setIsImporting(false);
handleError('Data import', progressData.error || 'Unknown error');
} }
} catch (error) { } catch (error) {
// Silently handle parsing errors // Silently handle parsing errors
@@ -316,10 +322,8 @@ export function Settings() {
setEventSource(null); setEventSource(null);
} }
setIsImporting(false); 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(); source.close();
setEventSource(null); setEventSource(null);
setIsResetting(false); setIsResetting(false);
if (!progressData.operation?.includes('cancelled')) {
setTimeout(() => {
setResetProgress(null); setResetProgress(null);
}, 1000); if (!progressData.operation?.includes('cancelled')) {
handleComplete('Database reset');
} }
} else if (progressData.status === 'error' && !progressData.operation?.includes('cancelled')) { } else if (progressData.status === 'error') {
source.close(); source.close();
setEventSource(null); setEventSource(null);
setIsResetting(false); setIsResetting(false);
handleError('Database reset', progressData.error || 'Unknown error');
} }
} catch (error) { } catch (error) {
// Silently handle parsing errors // Silently handle parsing errors
@@ -433,10 +437,8 @@ export function Settings() {
setEventSource(null); setEventSource(null);
} }
setIsResetting(false); 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() {
</div> </div>
</> </>
)} )}
{(progress.elapsed || progress.remaining) && (
<div className="flex justify-between text-sm text-muted-foreground">
{progress.elapsed && <span>Elapsed: {progress.elapsed}</span>}
{progress.remaining && <span>Remaining: {progress.remaining}</span>}
</div>
)}
{progress.message && (
<div className="text-sm text-muted-foreground">
{progress.message}
</div>
)}
{progress.error && (
<Alert variant="destructive" className="mt-2">
<AlertDescription>
{progress.error}
</AlertDescription>
</Alert>
)}
</div> </div>
); );
}; };
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 ( return (
<div className="p-8 space-y-8"> <div className="p-8 space-y-8">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">