fix(shopping): address frontend review concerns

- ChecklistItem: use:enhance with reset:false, role=checkbox, aria-checked, focus ring
- RecipeReferencePanel: day abbreviation text-[12px] (was 11px)
- ShoppingHeader: generating pending state disables button during submit
- AddCustomItem: only collapse form on successful submission

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-06 19:54:25 +02:00
parent e3afe1b4f2
commit be43fe94b6
4 changed files with 25 additions and 12 deletions

View File

@@ -27,12 +27,14 @@
method="POST" method="POST"
action="?/addItem" action="?/addItem"
use:enhance={() => { use:enhance={() => {
return async ({ update }) => { return async ({ result, update }) => {
await update(); if (result.type === 'success') {
customName = ''; await update();
quantity = '1'; customName = '';
unit = ''; quantity = '1';
expanded = false; unit = '';
expanded = false;
}
}; };
}} }}
class="flex flex-col gap-2 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface)] p-3" class="flex flex-col gap-2 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface)] p-3"

View File

@@ -32,15 +32,17 @@
); );
</script> </script>
<form method="POST" action="?/check" use:enhance class="group flex items-center gap-3 py-2"> <form method="POST" action="?/check" use:enhance={() => async ({ update }) => update({ reset: false })} class="group flex items-center gap-3 py-2">
<input type="hidden" name="listId" value={listId} /> <input type="hidden" name="listId" value={listId} />
<input type="hidden" name="itemId" value={itemId} /> <input type="hidden" name="itemId" value={itemId} />
<input type="hidden" name="isChecked" value={!isChecked} /> <input type="hidden" name="isChecked" value={!isChecked} />
<button <button
type="submit" type="submit"
role="checkbox"
aria-checked={isChecked}
aria-label="{isChecked ? 'Abhaken rückgängig' : 'Abhaken'}: {name}" aria-label="{isChecked ? 'Abhaken rückgängig' : 'Abhaken'}: {name}"
class="flex h-5 w-5 flex-shrink-0 items-center justify-center rounded border class="flex h-5 w-5 flex-shrink-0 items-center justify-center rounded border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--green)]
{isChecked {isChecked
? 'border-[var(--green)] bg-[var(--green)] text-white' ? 'border-[var(--green)] bg-[var(--green)] text-white'
: 'border-[var(--color-border)] bg-[var(--color-surface)] hover:border-[var(--green-light)]'}" : 'border-[var(--color-border)] bg-[var(--color-surface)] hover:border-[var(--green-light)]'}"

View File

@@ -30,7 +30,7 @@
href="/recipes/{slot.recipe?.id}" href="/recipes/{slot.recipe?.id}"
class="flex items-center gap-2 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-page)] px-3 py-2 hover:border-[var(--green-light)]" class="flex items-center gap-2 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-page)] px-3 py-2 hover:border-[var(--green-light)]"
> >
<span class="min-w-[28px] font-[var(--font-sans)] text-[11px] text-[var(--color-text-muted)]"> <span class="min-w-[28px] font-[var(--font-sans)] text-[12px] text-[var(--color-text-muted)]">
{slot.slotDate ? formatDayAbbr(slot.slotDate, 'short') : ''} {slot.slotDate ? formatDayAbbr(slot.slotDate, 'short') : ''}
</span> </span>
<span class="flex-1 truncate font-[var(--font-sans)] text-[13px] font-medium text-[var(--color-text)]"> <span class="flex-1 truncate font-[var(--font-sans)] text-[13px] font-medium text-[var(--color-text)]">

View File

@@ -14,6 +14,8 @@
let remainingCount = $derived(totalItems - checkedCount); let remainingCount = $derived(totalItems - checkedCount);
let generating = $state(false);
let formattedTime = $derived( let formattedTime = $derived(
generatedAt generatedAt
? new Date(generatedAt).toLocaleString('de-DE', { ? new Date(generatedAt).toLocaleString('de-DE', {
@@ -33,15 +35,22 @@
</h1> </h1>
{#if isPlanner && weekPlanId} {#if isPlanner && weekPlanId}
<form method="POST" action="?/generate" use:enhance> <form method="POST" action="?/generate" use:enhance={() => {
generating = true;
return async ({ update }) => {
await update();
generating = false;
};
}}>
<input type="hidden" name="weekPlanId" value={weekPlanId} /> <input type="hidden" name="weekPlanId" value={weekPlanId} />
<button <button
type="submit" type="submit"
disabled={generating}
class="rounded-[var(--radius-md)] {hasShoppingList class="rounded-[var(--radius-md)] {hasShoppingList
? 'border border-[var(--color-border)] text-[var(--color-text)] hover:bg-[var(--color-surface)]' ? 'border border-[var(--color-border)] text-[var(--color-text)] hover:bg-[var(--color-surface)]'
: 'bg-[var(--green-dark)] text-white'} px-3 py-1.5 text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)]" : 'bg-[var(--green-dark)] text-white'} px-3 py-1.5 text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)] disabled:opacity-50"
> >
{hasShoppingList ? 'Neu generieren' : 'Liste generieren'} {generating ? '…' : hasShoppingList ? 'Neu generieren' : 'Liste generieren'}
</button> </button>
</form> </form>
{/if} {/if}