From c9e65d435cf0f83e5b8c8542e4715d42d5b4fc11 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Fri, 29 May 2026 06:36:18 -0700 Subject: [PATCH] feat(tracker-web): overview MetricCard + ConfirmDialog delete (UX-2.2) Replace the bespoke total-count card chrome with the shared MetricCard on the dashboard overview (breakdown cards stay until the UX-4 chart swap), and surface load errors via AlertBanner. Wrap the items-list delete confirm() in the accessible ConfirmDialog (focus-trapped AlertDialog) instead of the native browser prompt. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../src/app/dashboard/items/page.tsx | 41 +++++++++++++------ .../tracker-web/src/app/dashboard/page.tsx | 14 ++++--- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/dashboards/tracker-web/src/app/dashboard/items/page.tsx b/dashboards/tracker-web/src/app/dashboard/items/page.tsx index f899d046..f11d17a2 100644 --- a/dashboards/tracker-web/src/app/dashboard/items/page.tsx +++ b/dashboards/tracker-web/src/app/dashboard/items/page.tsx @@ -12,6 +12,7 @@ import { Field, FieldLabel, Modal, + ConfirmDialog, StatusBadge, AlertBanner, type StatusTone, @@ -60,6 +61,9 @@ export default function ItemsListPage() { const [newPriority, setNewPriority] = useState<'critical' | 'high' | 'medium' | 'low'>('medium'); const [newDescription, setNewDescription] = useState(''); + // Delete confirmation + const [deleteId, setDeleteId] = useState(null); + const fetchItems = useCallback(async () => { setLoading(true); setError(''); @@ -101,18 +105,19 @@ export default function ItemsListPage() { } }; - const handleDelete = useCallback( - async (id: string) => { - if (!confirm('Delete this item?')) return; - try { - await deleteItem(id); - fetchItems(); - } catch (err: unknown) { - setError(err instanceof Error ? err.message : 'Failed to delete'); - } - }, - [fetchItems] - ); + const handleDelete = useCallback((id: string) => setDeleteId(id), []); + + const confirmDelete = useCallback(async () => { + if (!deleteId) return; + try { + await deleteItem(deleteId); + setDeleteId(null); + fetchItems(); + } catch (err: unknown) { + setDeleteId(null); + setError(err instanceof Error ? err.message : 'Failed to delete'); + } + }, [deleteId, fetchItems]); const columns = useMemo[]>( () => [ @@ -331,6 +336,18 @@ export default function ItemsListPage() { + + {/* Delete confirmation */} + { + if (!open) setDeleteId(null); + }} + title="Delete item" + description="Delete this item? This action cannot be undone." + confirmLabel="Delete" + onConfirm={confirmDelete} + /> ); } diff --git a/dashboards/tracker-web/src/app/dashboard/page.tsx b/dashboards/tracker-web/src/app/dashboard/page.tsx index b39391f1..1ca883f7 100644 --- a/dashboards/tracker-web/src/app/dashboard/page.tsx +++ b/dashboards/tracker-web/src/app/dashboard/page.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { PageHeader, LoadingSpinner } from '@bytelyst/dashboard-components'; +import { MetricCard, AlertBanner } from '@/components/ui/Primitives'; import { useAuth } from '@/lib/auth-context'; import { getStats, type TrackerStats } from '@/lib/tracker-client'; @@ -59,18 +60,19 @@ export default function DashboardOverview() {

Overview of all tracked items

{error && ( -
+ {error} -
+ )} {stats ? (
{/* Total count */} -
-
{stats.total}
-
Total items for {stats.productId}
-
+ {/* Breakdown cards */}