fix(audit): frontend HIGHs — surface fetch errors, kill href=#, invalidate queries, toast over alert

R2-H10: webhook-delivery-log and audit-log-list both swallowed fetch
errors silently — failed loads showed spinner forever or stale data.
Both now set a loadError state, show an inline retry banner, and fire
a toast.error. Same applies to audit-log loadMore.

R2-H11: audit-log-card rendered as `<a href="#">` — tapping on mobile
inserted `#` in the URL and scrolled to top (back-button trap).
ListCard now treats `href` as optional and renders a non-link `<div>`
when omitted; audit-log-card no longer passes href.

R2-H12: smart-archive-dialog only invalidated ['clients'] / ['berths']
/ ['interests']. Detail header kept showing Archived=false until hard
reload. Now also invalidates ['clients', clientId] and removes the
['client-archive-dossier', clientId] cache so re-open re-fetches.

R2-H13: client-list bulk mutation used native alert() on partial
failure (blocking the page) and had no onError handler. Replaced with
toast.warning / toast.success / toast.error.

1175/1175 vitest passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Ciaccio
2026-05-06 22:18:14 +02:00
parent a8c6c071e6
commit 5fc68a5f34
6 changed files with 79 additions and 31 deletions

View File

@@ -4,6 +4,7 @@ import { useState } from 'react';
import { useParams } from 'next/navigation';
import { Plus, Archive, Tag as TagIcon, TagsIcon, Trash2 } from 'lucide-react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import { DataTable } from '@/components/shared/data-table';
@@ -102,9 +103,14 @@ export function ClientList() {
queryClient.invalidateQueries({ queryKey: ['clients'] });
const s = res.data.summary;
if (s.failed > 0) {
alert(`${s.succeeded} of ${s.total} succeeded. ${s.failed} failed.`);
toast.warning(`${s.succeeded} of ${s.total} succeeded. ${s.failed} failed.`);
} else if (s.succeeded > 0) {
toast.success(`${s.succeeded} client${s.succeeded === 1 ? '' : 's'} updated.`);
}
},
onError: (err: unknown) => {
toast.error(err instanceof Error ? err.message : 'Bulk action failed');
},
});
const columns = getClientColumns({