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:
@@ -9,19 +9,25 @@ export const nodes = [
|
||||
() => import('./nodes/5'),
|
||||
() => import('./nodes/6'),
|
||||
() => import('./nodes/7'),
|
||||
() => import('./nodes/8')
|
||||
() => import('./nodes/8'),
|
||||
() => import('./nodes/9'),
|
||||
() => import('./nodes/10'),
|
||||
() => import('./nodes/11')
|
||||
];
|
||||
|
||||
export const server_loads = [];
|
||||
|
||||
export const dictionary = {
|
||||
"/": [~2],
|
||||
"/accounts": [5],
|
||||
"/items": [~6],
|
||||
"/items/[id]": [~7],
|
||||
"/login": [~8],
|
||||
"/logout": [~3],
|
||||
"/transactions": [4]
|
||||
"/accounts": [8],
|
||||
"/items": [~9],
|
||||
"/items/[id]": [~10],
|
||||
"/login": [~11],
|
||||
"/logout": [~6],
|
||||
"/receipts": [~3],
|
||||
"/receipts/new": [4],
|
||||
"/receipts/[id]": [5],
|
||||
"/transactions": [7]
|
||||
};
|
||||
|
||||
export const hooks = {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default as component } from "../../../../src/routes/items/[id]/+page.svelte";
|
||||
@@ -0,0 +1 @@
|
||||
export { default as component } from "../../../../src/routes/login/+page.svelte";
|
||||
@@ -0,0 +1 @@
|
||||
export { default as component } from "../../../../src/routes/receipts/+page.svelte";
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/transactions/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/receipts/new/+page.svelte";
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/accounts/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/receipts/[id]/+page.svelte";
|
||||
@@ -1 +0,0 @@
|
||||
export { default as component } from "../../../../src/routes/items/+page.svelte";
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/items/[id]/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/transactions/+page.svelte";
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/login/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/accounts/+page.svelte";
|
||||
@@ -0,0 +1 @@
|
||||
export { default as component } from "../../../../src/routes/items/+page.svelte";
|
||||
@@ -21,7 +21,7 @@ export const options = {
|
||||
service_worker: false,
|
||||
service_worker_options: undefined,
|
||||
templates: {
|
||||
app: ({ head, body, assets, nonce, env }) => "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <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>\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\" />\n <meta name=\"theme-color\" content=\"#0f172a\" />\n <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n " + head + "\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">" + body + "</div>\n </body>\n</html>\n",
|
||||
app: ({ head, body, assets, nonce, env }) => "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <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>\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, viewport-fit=cover\" />\n <meta name=\"theme-color\" content=\"#0f172a\" />\n <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n " + head + "\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">" + body + "</div>\n </body>\n</html>\n",
|
||||
error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
|
||||
},
|
||||
version_hash: "ekcm0i"
|
||||
|
||||
Vendored
+7
-3
@@ -27,9 +27,10 @@ export {};
|
||||
|
||||
declare module "$app/types" {
|
||||
export interface AppTypes {
|
||||
RouteId(): "/" | "/access-denied" | "/accounts" | "/items" | "/items/[id]" | "/login" | "/logout" | "/transactions";
|
||||
RouteId(): "/" | "/access-denied" | "/accounts" | "/items" | "/items/[id]" | "/login" | "/logout" | "/receipts" | "/receipts/new" | "/receipts/[id]" | "/transactions";
|
||||
RouteParams(): {
|
||||
"/items/[id]": { id: string }
|
||||
"/items/[id]": { id: string };
|
||||
"/receipts/[id]": { id: string }
|
||||
};
|
||||
LayoutParams(): {
|
||||
"/": { id?: string };
|
||||
@@ -39,9 +40,12 @@ declare module "$app/types" {
|
||||
"/items/[id]": { id: string };
|
||||
"/login": Record<string, never>;
|
||||
"/logout": Record<string, never>;
|
||||
"/receipts": { id?: string };
|
||||
"/receipts/new": Record<string, never>;
|
||||
"/receipts/[id]": { id: string };
|
||||
"/transactions": Record<string, never>
|
||||
};
|
||||
Pathname(): "/" | "/accounts" | "/items" | `/items/${string}` & {} | "/login" | "/logout" | "/transactions";
|
||||
Pathname(): "/" | "/accounts" | "/items" | `/items/${string}` & {} | "/login" | "/logout" | "/receipts" | "/receipts/new" | `/receipts/${string}` & {} | "/transactions";
|
||||
ResolvedPathname(): `${"" | `/${string}`}${ReturnType<AppTypes['Pathname']>}`;
|
||||
Asset(): string & {};
|
||||
}
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
"src/routes/logout/+page.server.ts",
|
||||
"src/routes/+layout.ts"
|
||||
],
|
||||
"/receipts": [
|
||||
"src/routes/receipts/+page.server.ts",
|
||||
"src/routes/+layout.ts"
|
||||
],
|
||||
"/receipts/new": [
|
||||
"src/routes/+layout.ts"
|
||||
],
|
||||
"/receipts/[id]": [
|
||||
"src/routes/+layout.ts"
|
||||
],
|
||||
"/transactions": [
|
||||
"src/routes/+layout.ts"
|
||||
]
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends
|
||||
export type Snapshot<T = any> = Kit.Snapshot<T>;
|
||||
type PageServerParentData = EnsureDefined<LayoutServerData>;
|
||||
type PageParentData = EnsureDefined<LayoutData>;
|
||||
type LayoutRouteId = RouteId | "/" | "/logout" | "/transactions" | "/accounts" | "/items" | "/items/[id]" | "/login" | null
|
||||
type LayoutRouteId = RouteId | "/" | "/receipts" | "/receipts/new" | "/receipts/[id]" | "/logout" | "/transactions" | "/accounts" | "/items" | "/items/[id]" | "/login" | null
|
||||
type LayoutParams = RouteParams & { id?: string }
|
||||
type LayoutParentData = EnsureDefined<{}>;
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import type * as Kit from '@sveltejs/kit';
|
||||
|
||||
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
// @ts-ignore
|
||||
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
|
||||
type RouteParams = { };
|
||||
type RouteId = '/receipts';
|
||||
type MaybeWithVoid<T> = {} extends T ? T | void : T;
|
||||
export type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];
|
||||
type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>
|
||||
type EnsureDefined<T> = T extends null | undefined ? {} : T;
|
||||
type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
|
||||
export type Snapshot<T = any> = Kit.Snapshot<T>;
|
||||
type PageServerParentData = EnsureDefined<import('../$types.js').LayoutServerData>;
|
||||
type PageParentData = EnsureDefined<import('../$types.js').LayoutData>;
|
||||
|
||||
export type PageServerLoad<OutputData extends OutputDataShape<PageServerParentData> = OutputDataShape<PageServerParentData>> = Kit.ServerLoad<RouteParams, PageServerParentData, OutputData, RouteId>;
|
||||
export type PageServerLoadEvent = Parameters<PageServerLoad>[0];
|
||||
export type ActionData = unknown;
|
||||
export type PageServerData = Expand<OptionalUnion<EnsureDefined<Kit.LoadProperties<Awaited<ReturnType<typeof import('./proxy+page.server.js').load>>>>>>;
|
||||
export type PageData = Expand<Omit<PageParentData, keyof PageServerData> & EnsureDefined<PageServerData>>;
|
||||
export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>
|
||||
export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>
|
||||
export type PageProps = { params: RouteParams; data: PageData; form: ActionData }
|
||||
export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;
|
||||
@@ -0,0 +1,19 @@
|
||||
import type * as Kit from '@sveltejs/kit';
|
||||
|
||||
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
// @ts-ignore
|
||||
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
|
||||
type RouteParams = { id: string };
|
||||
type RouteId = '/receipts/[id]';
|
||||
type MaybeWithVoid<T> = {} extends T ? T | void : T;
|
||||
export type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];
|
||||
type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>
|
||||
type EnsureDefined<T> = T extends null | undefined ? {} : T;
|
||||
type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
|
||||
export type Snapshot<T = any> = Kit.Snapshot<T>;
|
||||
type PageParentData = EnsureDefined<import('../../$types.js').LayoutData>;
|
||||
|
||||
export type EntryGenerator = () => Promise<Array<RouteParams>> | Array<RouteParams>;
|
||||
export type PageServerData = null;
|
||||
export type PageData = Expand<PageParentData>;
|
||||
export type PageProps = { params: RouteParams; data: PageData }
|
||||
@@ -0,0 +1,18 @@
|
||||
import type * as Kit from '@sveltejs/kit';
|
||||
|
||||
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
// @ts-ignore
|
||||
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
|
||||
type RouteParams = { };
|
||||
type RouteId = '/receipts/new';
|
||||
type MaybeWithVoid<T> = {} extends T ? T | void : T;
|
||||
export type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];
|
||||
type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>
|
||||
type EnsureDefined<T> = T extends null | undefined ? {} : T;
|
||||
type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
|
||||
export type Snapshot<T = any> = Kit.Snapshot<T>;
|
||||
type PageParentData = EnsureDefined<import('../../$types.js').LayoutData>;
|
||||
|
||||
export type PageServerData = null;
|
||||
export type PageData = Expand<PageParentData>;
|
||||
export type PageProps = { params: RouteParams; data: PageData }
|
||||
@@ -0,0 +1,8 @@
|
||||
// @ts-nocheck
|
||||
import type { PageServerLoad } from "./$types";
|
||||
|
||||
export const load = async () => {
|
||||
// Placeholder: no PocketBase receipts collection yet. Return empty list.
|
||||
return { receipts: [] as { id: string }[] };
|
||||
};
|
||||
;null as any as PageServerLoad;
|
||||
+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