Enhance routing in SvelteKit project by adding new receipt-related routes, updating existing route parameters, and improving layout handling. Refactor components to streamline UI interactions and remove unused imports for better performance.
CI / build (push) Has been skipped
CI / deploy (push) Successful in 1m19s

This commit is contained in:
eewing
2026-02-18 10:51:09 -06:00
parent a82c89674a
commit 809c784209
31 changed files with 253 additions and 104 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='4' fill='%231e293b'/><text x='16' y='22' font-size='18' font-family='system-ui' fill='%2394a3b8' text-anchor='middle'>S</text></svg>" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, viewport-fit=cover" />
<meta name="theme-color" content="#0f172a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
@@ -2,7 +2,6 @@
import { Button } from "$lib/components/ui/button";
import { Input } from "$lib/components/ui/input";
import * as Dialog from "$lib/components/ui/dialog";
import { Search, X } from "@lucide/svelte";
let {
open = $bindable(false),
@@ -152,7 +151,6 @@
class="min-h-11 flex-1"
/>
<Button type="button" class="min-h-11 shrink-0" onclick={submitSearch} disabled={!searchInput.trim()}>
<Search class="mr-2 size-4" />
Search
</Button>
</div>
@@ -176,7 +174,6 @@
class="min-h-12 flex-1"
onclick={() => { stopScan(); open = false; }}
>
<X class="mr-2 size-4" />
Cancel
</Button>
</div>
+14 -41
View File
@@ -4,8 +4,6 @@
import ItemForm from "./items/ItemForm.svelte";
import BarcodeScanDialog from "$lib/components/BarcodeScanDialog.svelte";
import { goto } from "$app/navigation";
import { Camera, Package, Receipt, Wallet } from "@lucide/svelte";
let {
data,
}: {
@@ -37,58 +35,33 @@
<h1 class="w-full max-w-xs text-center text-2xl font-semibold">Stackq</h1>
<div class="flex w-full max-w-xs flex-col gap-3">
<p class="text-muted-foreground text-center text-sm font-medium">Quick actions</p>
<Button class="h-16 min-h-16 w-full" onclick={() => (scanDialogOpen = true)}>
<span class="flex w-full flex-col items-center justify-center gap-1">
<Camera class="size-5" />
<span class="text-sm font-medium leading-none">Scan</span>
</span>
</Button>
<Button class="h-16 min-h-16 w-full" onclick={() => (scanDialogOpen = true)}>Scan</Button>
<a href="/transactions" class="block">
<Button class="h-16 min-h-16 w-full" variant="outline">
<span class="flex w-full flex-col items-center justify-center gap-1">
<Receipt class="size-5" />
<span class="text-sm font-medium leading-none">New Transaction</span>
</span>
</Button>
<Button class="h-16 min-h-16 w-full" variant="outline">New Transaction</Button>
</a>
<Button class="h-16 min-h-16 w-full" variant="outline" onclick={() => (dialogOpen = true)}>
<span class="flex w-full flex-col items-center justify-center gap-1">
<Package class="size-5" />
<span class="text-sm font-medium leading-none">New Item</span>
</span>
</Button>
<a href="/receipts/new" class="block">
<Button class="h-16 min-h-16 w-full" variant="outline">New receipt</Button>
</a>
<Button class="h-16 min-h-16 w-full" variant="outline" onclick={() => (dialogOpen = true)}>New Item</Button>
</div>
<div class="text-muted-foreground w-full max-w-xs border-t pt-4 text-center text-sm">Go to</div>
<div class="w-full max-w-xs border-t pt-4"></div>
<div class="flex w-full max-w-xs flex-col gap-2">
<a href="/items" class="block">
<Button class="h-16 min-h-16 w-full" variant="outline">
<span class="flex w-full flex-col items-center justify-center gap-1">
<Package class="size-4" />
<span class="text-sm font-medium leading-none">Items</span>
</span>
</Button>
<Button class="h-16 min-h-16 w-full" variant="outline">Items</Button>
</a>
<a href="/transactions" class="block">
<Button class="h-16 min-h-16 w-full" variant="outline">
<span class="flex w-full flex-col items-center justify-center gap-1">
<Receipt class="size-4" />
<span class="text-sm font-medium leading-none">Transactions</span>
</span>
</Button>
<Button class="h-16 min-h-16 w-full" variant="outline">Transactions</Button>
</a>
<a href="/receipts" class="block">
<Button class="h-16 min-h-16 w-full" variant="outline">Receipts</Button>
</a>
<a href="/accounts" class="block">
<Button class="h-16 min-h-16 w-full" variant="outline">
<span class="flex w-full flex-col items-center justify-center gap-1">
<Wallet class="size-4" />
<span class="text-sm font-medium leading-none">Accounts</span>
</span>
</Button>
<Button class="h-16 min-h-16 w-full" variant="outline">Accounts</Button>
</a>
<a href="/logout" class="block">
<Button class="h-16 min-h-16 w-full justify-center" variant="outline">Log out</Button>
<Button class="h-16 min-h-16 w-full" variant="outline">Log out</Button>
</a>
</div>
</main>
+1 -4
View File
@@ -1,7 +1,6 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button";
import { Card, CardContent } from "$lib/components/ui/card";
import { Home } from "@lucide/svelte";
</script>
<svelte:head>
@@ -10,9 +9,7 @@
<main class="container mx-auto flex flex-col gap-6 px-4 py-6 sm:px-6 sm:py-8">
<div class="flex items-center gap-3">
<a href="/" class="touch-target text-muted-foreground hover:text-foreground shrink-0" title="Back to main">
<Home class="size-5" />
</a>
<a href="/" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to main">Back</a>
<h1 class="text-xl font-semibold sm:text-2xl">Accounts</h1>
</div>
+1 -5
View File
@@ -3,7 +3,6 @@
import { Input } from "$lib/components/ui/input";
import { Label } from "$lib/components/ui/label";
import { enhance } from "$app/forms";
import { Camera, X } from "@lucide/svelte";
import { POCKETBASE_BASE_URL } from "$lib/pocketbase";
import { UOM_OPTIONS, CATAGORY_OPTIONS, SUB_CATAGORY_OPTIONS } from "$lib/constants/items";
import type { StackqItem } from "$lib/types/items";
@@ -169,9 +168,7 @@
<Label for="SKU">SKU</Label>
<div class="flex gap-2">
<Input id="SKU" name="SKU" bind:value={skuValue} class="flex-1" />
<Button type="button" variant="outline" size="icon" onclick={startScan} title="Scan barcode">
<Camera class="size-4" />
</Button>
<Button type="button" variant="outline" onclick={startScan} title="Scan barcode">Scan</Button>
</div>
</div>
</div>
@@ -195,7 +192,6 @@
{/if}
<div class="flex gap-2">
<Button type="button" variant="outline" class="flex-1" onclick={stopScan}>
<X class="mr-2 size-4" />
Cancel
</Button>
</div>
+7 -20
View File
@@ -9,7 +9,6 @@
import { goto } from "$app/navigation";
import BarcodeScanDialog from "$lib/components/BarcodeScanDialog.svelte";
import ItemForm from "./ItemForm.svelte";
import { Camera, Ellipsis, ExternalLink, Home, Pencil, Plus, Search, Trash2 } from "@lucide/svelte";
import type { StackqItem } from "$lib/types/items";
let {
@@ -118,19 +117,16 @@
<main class="container mx-auto flex flex-col gap-4 px-4 py-6 sm:gap-6 sm:px-6 sm:py-8">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div class="flex items-center gap-2 min-w-0">
<a href="/" class="touch-target text-muted-foreground hover:text-foreground shrink-0" title="Back to main">
<Home class="size-5" />
</a>
<a href="/" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to main">Back</a>
<h1 class="text-xl font-semibold truncate sm:text-2xl">Stackq Items</h1>
</div>
<div class="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:gap-2">
<div class="relative w-full sm:w-64 sm:min-w-0">
<Search class="text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2" />
<div class="w-full sm:w-64 sm:min-w-0">
<Input
type="search"
placeholder="Search items, SKU…"
bind:value={searchQuery}
class="h-11 w-full pl-9 sm:h-9"
class="h-11 w-full sm:h-9"
/>
</div>
<span class="text-muted-foreground text-sm shrink-0">
@@ -138,11 +134,9 @@
</span>
<div class="flex gap-2">
<Button variant="outline" onclick={() => (scanDialogOpen = true)} title="Scan barcode to look up item" class="min-h-11 flex-1 sm:flex-none">
<Camera class="mr-2 size-4 shrink-0" />
Scan
</Button>
<Button onclick={openCreate} class="min-h-11 flex-1 sm:flex-none">
<Plus class="mr-2 size-4 shrink-0" />
New item
</Button>
</div>
@@ -197,20 +191,14 @@
</div>
<DropdownMenu.Root>
<DropdownMenu.Trigger
class="border-0 bg-transparent hover:bg-muted inline-flex min-h-9 min-w-9 shrink-0 items-center justify-center rounded-md"
class="border-0 bg-transparent hover:bg-muted inline-flex min-h-9 min-w-9 shrink-0 items-center justify-center rounded-md text-sm"
>
<Ellipsis class="size-4" />
Actions
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content align="end">
<DropdownMenu.Item onclick={() => goto("/items/" + item.id)}>
<ExternalLink class="mr-2 size-4" />
View
</DropdownMenu.Item>
<DropdownMenu.Item onclick={() => openEdit(item)}>
<Pencil class="mr-2 size-4" />
Edit
</DropdownMenu.Item>
<DropdownMenu.Item onclick={() => goto("/items/" + item.id)}>View</DropdownMenu.Item>
<DropdownMenu.Item onclick={() => openEdit(item)}>Edit</DropdownMenu.Item>
<form
id="delete-form-{item.id}"
method="POST"
@@ -228,7 +216,6 @@
}
}}
>
<Trash2 class="mr-2 size-4" />
Delete
</DropdownMenu.Item>
</DropdownMenu.Content>
+2 -9
View File
@@ -6,7 +6,6 @@
import * as Dialog from "$lib/components/ui/dialog";
import { enhance } from "$app/forms";
import ItemForm from "../ItemForm.svelte";
import { ArrowLeft, Home, Pencil, Trash2 } from "@lucide/svelte";
let {
data,
@@ -63,17 +62,12 @@
{#if item}
<main class="container mx-auto flex flex-col gap-4 px-4 py-6 sm:gap-6 sm:px-6 sm:py-8">
<div class="flex flex-wrap items-center gap-2 sm:gap-4 min-w-0">
<a href="/" class="touch-target text-muted-foreground hover:text-foreground shrink-0" title="Back to main">
<Home class="size-5" />
</a>
<a href="/items" class="touch-target text-muted-foreground hover:text-foreground shrink-0" title="Back to items">
<ArrowLeft class="size-5" />
</a>
<a href="/" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to main">Home</a>
<a href="/items" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to items">Back to items</a>
<h1 class="text-xl font-semibold truncate min-w-0 flex-1 sm:text-2xl">{item.Item ?? "—"}</h1>
{#if browser}
<div class="flex gap-2 w-full sm:w-auto">
<Button variant="outline" onclick={() => (dialogOpen = true)} class="min-h-11 flex-1 sm:flex-none">
<Pencil class="mr-2 size-4" />
Edit
</Button>
<form
@@ -93,7 +87,6 @@
}
}}
>
<Trash2 class="mr-2 size-4" />
Delete
</Button>
</form>
+7
View File
@@ -102,6 +102,13 @@
* {
@apply border-border;
}
html {
/* Match device text scaling (prevent iOS from inflating text) */
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
/* Slightly smaller base so layout scales better on small screens */
font-size: clamp(14px, 2.5vw + 12px, 16px);
}
body {
@apply bg-background text-foreground;
/* Safe area for notched devices */
+6
View File
@@ -0,0 +1,6 @@
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async () => {
// Placeholder: no PocketBase receipts collection yet. Return empty list.
return { receipts: [] as { id: string }[] };
};
+48
View File
@@ -0,0 +1,48 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button";
import { Card, CardContent } from "$lib/components/ui/card";
let { data }: { data: { receipts: { id: string }[] } } = $props();
const receipts = $derived(data?.receipts ?? []);
</script>
<svelte:head>
<title>Receipts Stackq</title>
</svelte:head>
<main class="container mx-auto flex flex-col gap-6 px-4 py-6 sm:px-6 sm:py-8">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div class="flex items-center gap-3">
<a href="/" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to main">Back</a>
<h1 class="text-xl font-semibold sm:text-2xl">Receipts</h1>
</div>
<a href="/receipts/new" class="block shrink-0">
<Button class="w-full sm:w-auto">New receipt</Button>
</a>
</div>
{#if receipts.length === 0}
<Card>
<CardContent class="flex flex-col items-center justify-center gap-4 py-12">
<p class="text-muted-foreground text-center text-sm">No receipts yet.</p>
<p class="text-muted-foreground text-center text-xs">Create a receipt to get started.</p>
<a href="/receipts/new">
<Button variant="outline">New receipt</Button>
</a>
<a href="/">
<Button variant="ghost">Back to home</Button>
</a>
</CardContent>
</Card>
{:else}
<div class="flex flex-col gap-2">
{#each receipts as receipt (receipt.id)}
<Card>
<CardContent class="p-4">
<a href="/receipts/{receipt.id}" class="font-medium hover:underline">Receipt {receipt.id}</a>
</CardContent>
</Card>
{/each}
</div>
{/if}
</main>
+26
View File
@@ -0,0 +1,26 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button";
import { Card, CardContent } from "$lib/components/ui/card";
let { data, params }: { data: unknown; params: { id: string } } = $props();
</script>
<svelte:head>
<title>Receipt Stackq</title>
</svelte:head>
<main class="container mx-auto flex flex-col gap-6 px-4 py-6 sm:px-6 sm:py-8">
<div class="flex items-center gap-3">
<a href="/receipts" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to receipts">Back</a>
<h1 class="text-xl font-semibold sm:text-2xl">Receipt</h1>
</div>
<Card>
<CardContent class="flex flex-col gap-4 py-8">
<p class="text-muted-foreground text-sm">Receipt {params.id}</p>
<a href="/receipts">
<Button variant="outline">Back to receipts</Button>
</a>
</CardContent>
</Card>
</main>
+29
View File
@@ -0,0 +1,29 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button";
import { Card, CardContent } from "$lib/components/ui/card";
</script>
<svelte:head>
<title>New receipt Stackq</title>
</svelte:head>
<main class="container mx-auto flex flex-col gap-6 px-4 py-6 sm:px-6 sm:py-8">
<div class="flex items-center gap-3">
<a href="/receipts" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to receipts">Back</a>
<h1 class="text-xl font-semibold sm:text-2xl">New receipt</h1>
</div>
<Card>
<CardContent class="flex flex-col gap-4 py-8">
<p class="text-muted-foreground text-center text-sm">Receipt creation will be available here.</p>
<div class="flex justify-center gap-2">
<a href="/receipts">
<Button variant="outline">Back to receipts</Button>
</a>
<a href="/">
<Button variant="ghost">Home</Button>
</a>
</div>
</CardContent>
</Card>
</main>
+1 -4
View File
@@ -1,7 +1,6 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button";
import { Card, CardContent } from "$lib/components/ui/card";
import { Home } from "@lucide/svelte";
</script>
<svelte:head>
@@ -10,9 +9,7 @@
<main class="container mx-auto flex flex-col gap-6 px-4 py-6 sm:px-6 sm:py-8">
<div class="flex items-center gap-3">
<a href="/" class="touch-target text-muted-foreground hover:text-foreground shrink-0" title="Back to main">
<Home class="size-5" />
</a>
<a href="/" class="text-muted-foreground hover:text-foreground shrink-0 text-sm" title="Back to main">Back</a>
<h1 class="text-xl font-semibold sm:text-2xl">Transactions</h1>
</div>