DEV Community

Cover image for Day 2: The Secret Gift List (Purchase Tracker) 🎁
Michael Amachree
Michael Amachree Subscriber

Posted on

Day 2: The Secret Gift List (Purchase Tracker) 🎁

It's Day 2 of the #12DaysOfSvelteApps! πŸŽ„

Yesterday, we managed the cost of the holidays with the Budget Tracker. Today, we're managing the chaos of the gifts themselves.

The App: Purchase Tracker

The Purchase Tracker is your digital shopping assistant. While generic note-taking apps are fine, they lack structure. This app treats every potential gift as an "Item" with properties like category, default currency, and unit measurements.

πŸ”— Try the App Live
πŸ’» View the Code

The "Use Case": The Anti-Spoiler List 🀫

We all have that one family member who snoops on the shared "To-Do" list or the fridge notepad.
Use the Purchase Tracker to create a "Gifts" category.

  • Name: The person you are buying for (or the item code name).
  • Description: The actual item detail (e.g., "Size M, Blue, from that one vintage store").
  • Privacy: Since the app functions essentially as a local database, your surprise plans remain on your device (or secured in your account).

Tech Spotlight: Optimistic UI ⚑

One of the best UX patterns we implemented here is Optimistic UI. When you create a new Item, we don't want the user to wait for the server to say "Okay." We want it to appear instantly.

In our Svelte component:

function handleLocalCreateItem(e: SubmitEvent) {
    e.preventDefault();
    // ... extract form data ...

    // 1. Update the local state IMMEDIATELY
    const newItem = addItem(name, category, description, unit, currency);

    // The UI updates instantly because 'items' is a reactive Svelte state
    // items.current = [...oldItems, newItem];

    toast.success('Item created successfully');
}
Enter fullscreen mode Exit fullscreen mode

If the user is logged in, we perform the server request in the background. If it fails, we roll back. But 99% of the time, the user experiences zero latency.

Dealing with Complex Lists

We used shadcn-svelte components to quickly scaffold a beautiful Table view.

<Table>
    <TableHeader>
        <TableRow>
            <TableHead>Name</TableHead>
            <TableHead>Category</TableHead>
            <!-- ... -->
        </TableRow>
    </TableHeader>
    <TableBody>
        {#each items.current as item (item.id)}
            <TableRow onclick={() => navigateToPurchases(item.id)}>
                <TableCell>{item.name}</TableCell>
                <TableCell>
                    <!-- Category Icon + Name lookup -->
                    {categories.find(c => c.id === item.category)?.name}
                </TableCell>
            </TableRow>
        {/each}
    </TableBody>
</Table>
Enter fullscreen mode Exit fullscreen mode

Using Svelte's {#each key} block (the (item.id) part) is crucial here. It ensures that when we delete or reorder items, the DOM updates efficiently without weird rendering artifactsβ€”a must-have for any list-heavy application.

Next Up

Now that we have a Budget and a Shopping List, we need to actually get things done. Join us tomorrow for Day 3.

Top comments (1)

Collapse
 
gooserv profile image
Gooserv • Edited

I like how you tied mindset work into the scents because that combo really does shift the vibe. I’ve found incense for good energy makes it easier to settle into visualization without my thoughts running off. Your take on weaving these habits into daily routines fits the way Nothing But Scents lays out their options, so readers can play around with what actually clicks for them.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.