fix(notification-dropdown): handle error result type, add role=alert, fix update ordering

- Add role="alert" to error banner so screen-reader users hear failures
- Handle result.type === 'error' (network failure) alongside 'failure' in both enhance callbacks
- Clear errorMessage at the start of each submit so stale errors don't persist on retry
- On dismiss success: skip update() entirely since goto() navigates away from the page
- On dismiss failure: await update() then set error message
- On mark-all success: skip update() (optimistic state already applied)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-20 07:05:50 +02:00
committed by marcel
parent 30efb54aac
commit 978a2b3cdb

View File

@@ -39,12 +39,13 @@ function handleViewAll() {
action="/aktivitaeten?/mark-all-read" action="/aktivitaeten?/mark-all-read"
method="POST" method="POST"
use:enhance={() => { use:enhance={() => {
errorMessage = null;
optimisticMarkAllRead(); optimisticMarkAllRead();
return async ({ result, update }) => { return async ({ result, update }) => {
if (result.type === 'failure') { if (result.type === 'failure' || result.type === 'error') {
errorMessage = (result.data as { error?: string } | undefined)?.error ?? m.notification_error_generic(); errorMessage = (result as { data?: { error?: string } }).data?.error ?? m.notification_error_generic();
await update({ reset: false, invalidateAll: false });
} }
await update({ reset: false, invalidateAll: false });
}; };
}} }}
> >
@@ -60,7 +61,7 @@ function handleViewAll() {
<!-- Error banner (shown when a dismiss or mark-all action fails) --> <!-- Error banner (shown when a dismiss or mark-all action fails) -->
{#if errorMessage} {#if errorMessage}
<p class="px-4 py-2 text-sm text-red-600">{errorMessage}</p> <p role="alert" class="px-4 py-2 text-sm text-red-600">{errorMessage}</p>
{/if} {/if}
<!-- Notification list --> <!-- Notification list -->
@@ -93,11 +94,14 @@ function handleViewAll() {
method="POST" method="POST"
class="contents" class="contents"
use:enhance={() => { use:enhance={() => {
errorMessage = null;
optimisticMarkRead(notification.id); optimisticMarkRead(notification.id);
return async ({ result, update }) => { return async ({ result, update }) => {
if (result.type === 'failure') { if (result.type === 'failure' || result.type === 'error') {
errorMessage = (result.data as { error?: string } | undefined)?.error ?? m.notification_error_generic(); errorMessage = (result as { data?: { error?: string } }).data?.error ?? m.notification_error_generic();
await update({ reset: false, invalidateAll: false });
} else { } else {
// Navigate away — no need to update the store since we're leaving the page
onClose(); onClose();
goto( goto(
buildCommentHref( buildCommentHref(
@@ -107,7 +111,6 @@ function handleViewAll() {
) )
); );
} }
await update({ reset: false, invalidateAll: false });
}; };
}} }}
> >