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:
28
apps/web/src/lib/components/ItemSuggestions.svelte
Normal file
28
apps/web/src/lib/components/ItemSuggestions.svelte
Normal 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}
|
||||
Reference in New Issue
Block a user