feat: Fase 2a — shopping lists CRUD

DB: shopping_lists + shopping_items tables with full RLS, pg_cron jobs
(archive completed lists after 7 days, purge trash after 7 days).
item_frequency table with SECURITY DEFINER trigger that normalises and
upserts on every shopping_items INSERT.

Frontend: /lists overview (featured card + 2-col grid + trash toggle),
/lists/[id] detail (qty stepper, inline edit, swipe-to-reveal-delete,
drag & drop reorder via svelte-dnd-action, ItemSuggestions chips).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-12 22:25:31 +02:00
parent ce1bcfb7a6
commit 3af1276c15
11 changed files with 1609 additions and 12 deletions

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import type { ItemFrequency } from '@colectivo/types';
interface Props {
suggestions: ItemFrequency[];
activePrefix: string;
onselect: (name: string) => void;
}
let { suggestions, activePrefix, onselect }: Props = $props();
</script>
{#if suggestions.length > 0}
<div class="flex flex-wrap gap-1.5 px-4 pb-2 pt-1">
{#each suggestions as item (item.name)}
<button
type="button"
onclick={() => onselect(item.name)}
class="rounded-full px-3 py-1 text-[13px] font-medium transition-colors
{activePrefix && item.name.startsWith(activePrefix.toLowerCase().trim())
? 'bg-slate-900 text-white dark:bg-white dark:text-slate-900'
: 'bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700'}"
>
{item.name}
</button>
{/each}
</div>
{/if}