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.
This commit is contained in:
+1
-1
@@ -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>
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 }[] };
|
||||
};
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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,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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user