Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions web/build/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,35 @@
<meta charset="utf-8" />
<link rel="icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="/_app/immutable/entry/start.0EfKWloI.js" rel="modulepreload">
<link href="/_app/immutable/chunks/B6AduMOh.js" rel="modulepreload">
<link href="/_app/immutable/chunks/Cca5XcAr.js" rel="modulepreload">
<link href="/_app/immutable/entry/app.HI1UzXj1.js" rel="modulepreload">
<link href="/_app/immutable/entry/start.BiqjHQnY.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DLVqjwSU.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DtfuHTUv.js" rel="modulepreload">
<link href="/_app/immutable/entry/app.DvuAAeOH.js" rel="modulepreload">
<link href="/_app/immutable/chunks/kNaey6uv.js" rel="modulepreload">
<link href="/_app/immutable/chunks/xihTtKlq.js" rel="modulepreload">
<link href="/_app/immutable/nodes/0.DamGPcfi.js" rel="modulepreload">
<link href="/_app/immutable/nodes/0.Dya_MPtI.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DKyKpwK7.js" rel="modulepreload">
<link href="/_app/immutable/chunks/5Qa-t89S.js" rel="modulepreload">
<link href="/_app/immutable/chunks/hKaPXkrQ.js" rel="modulepreload">
<link href="/_app/immutable/chunks/BscTVQ9J.js" rel="modulepreload">
<link href="/_app/immutable/chunks/D_M18t6X.js" rel="modulepreload">
<link href="/_app/immutable/chunks/B0RXJPsG.js" rel="modulepreload">
<link href="/_app/immutable/chunks/fe7zj1-L.js" rel="modulepreload">

<link href="/_app/immutable/assets/0.BNL21c07.css" rel="stylesheet">
<link href="/_app/immutable/assets/0.DWoDaaiW.css" rel="stylesheet">
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">
<script>
{
__sveltekit_xkujp8 = {
__sveltekit_mtser5 = {
base: ""
};

const element = document.currentScript.parentElement;

Promise.all([
import("/_app/immutable/entry/start.0EfKWloI.js"),
import("/_app/immutable/entry/app.HI1UzXj1.js")
import("/_app/immutable/entry/start.BiqjHQnY.js"),
import("/_app/immutable/entry/app.DvuAAeOH.js")
]).then(([kit, app]) => {
kit.start(app, element);
});
Expand Down
56 changes: 51 additions & 5 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"devDependencies": {
"@internationalized/date": "^3.12.2",
"@lucide/svelte": "^1.39.0",
"@playwright/test": "^1.61.0",
"@sveltejs/adapter-auto": "^7.0.1",
"@sveltejs/adapter-static": "^3.0.10",
Expand All @@ -34,8 +35,9 @@
"mode-watcher": "^1.1.0",
"svelte": "^5.55.2",
"svelte-check": "^4.4.6",
"svelte-sonner": "^1.2.1",
"tailwind-merge": "^3.6.0",
"tailwind-variants": "^3.2.2",
"tailwind-variants": "^3.3.1",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.2",
"vite": "^8.0.7",
Expand Down
22 changes: 22 additions & 0 deletions web/src/lib/components/EmptyState.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import type { Snippet } from 'svelte';

interface Props {
title: string;
description?: string;
/** Optional action (e.g. a Button) rendered below the description. */
children?: Snippet;
}

let { title, description, children }: Props = $props();
</script>

<div class="flex flex-col items-center justify-center py-16 text-center">
<h3 class="text-lg font-medium text-foreground">{title}</h3>
{#if description}
<p class="mt-1 max-w-md text-sm text-muted-foreground">{description}</p>
{/if}
{#if children}
<div class="mt-4">{@render children()}</div>
{/if}
</div>
47 changes: 47 additions & 0 deletions web/src/lib/components/Pagination.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script lang="ts">
import { Button } from '$lib/components/ui/button/index.js';

interface Props {
page: number;
totalPages: number;
total: number;
perPage: number;
onPageChange: (page: number) => void;
}

let { page, totalPages, total, perPage, onPageChange }: Props = $props();

function goTo(p: number) {
if (p < 1 || p > totalPages || p === page) return;
onPageChange(p);
}
</script>

{#if totalPages > 1}
<div class="flex flex-wrap items-center justify-between gap-2">
<p class="text-xs text-muted-foreground tabular-nums">
Showing {(page - 1) * perPage + 1}–{Math.min(page * perPage, total)} of {total}
</p>
<div class="flex items-center gap-1">
<Button variant="outline" size="sm" disabled={page <= 1} onclick={() => goTo(page - 1)}>
Prev
</Button>
{#each Array(Math.min(totalPages, 5)) as _, i}
{@const pageNum = page <= 3 ? i + 1 : page - 2 + i}
{#if pageNum <= totalPages}
<Button
variant={pageNum === page ? 'default' : 'outline'}
size="sm"
class="w-9"
onclick={() => goTo(pageNum)}
>
{pageNum}
</Button>
{/if}
{/each}
<Button variant="outline" size="sm" disabled={page >= totalPages} onclick={() => goTo(page + 1)}>
Next
</Button>
</div>
</div>
{/if}
27 changes: 27 additions & 0 deletions web/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import {
buttonVariants,
type ButtonVariant,
type ButtonSize,
} from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";

let {
ref = $bindable(null),
class: className,
variant = "default",
size = "default",
...restProps
}: AlertDialogPrimitive.ActionProps & {
variant?: ButtonVariant;
size?: ButtonSize;
} = $props();
</script>

<AlertDialogPrimitive.Action
bind:ref
data-slot="alert-dialog-action"
class={cn(buttonVariants({ variant, size }), "cn-alert-dialog-action", className)}
{...restProps}
/>
27 changes: 27 additions & 0 deletions web/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import {
buttonVariants,
type ButtonVariant,
type ButtonSize,
} from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";

let {
ref = $bindable(null),
class: className,
variant = "outline",
size = "default",
...restProps
}: AlertDialogPrimitive.CancelProps & {
variant?: ButtonVariant;
size?: ButtonSize;
} = $props();
</script>

<AlertDialogPrimitive.Cancel
bind:ref
data-slot="alert-dialog-cancel"
class={cn(buttonVariants({ variant, size }), "cn-alert-dialog-cancel", className)}
{...restProps}
/>
32 changes: 32 additions & 0 deletions web/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { cn, type WithoutChild, type WithoutChildrenOrChild } from "$lib/utils.js";
import AlertDialogOverlay from "./alert-dialog-overlay.svelte";
import AlertDialogPortal from "./alert-dialog-portal.svelte";
import type { ComponentProps } from "svelte";

let {
ref = $bindable(null),
class: className,
size = "default",
portalProps,
...restProps
}: WithoutChild<AlertDialogPrimitive.ContentProps> & {
size?: "default" | "sm";
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof AlertDialogPortal>>;
} = $props();
</script>

<AlertDialogPortal {...portalProps}>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
bind:ref
data-slot="alert-dialog-content"
data-size={size}
class={cn(
"gap-6 rounded-xl bg-popover p-6 text-popover-foreground ring-1 ring-foreground/10 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",
className
)}
{...restProps}
/>
</AlertDialogPortal>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";

let {
ref = $bindable(null),
class: className,
...restProps
}: AlertDialogPrimitive.DescriptionProps = $props();
</script>

<AlertDialogPrimitive.Description
bind:ref
data-slot="alert-dialog-description"
class={cn("text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className)}
{...restProps}
/>
23 changes: 23 additions & 0 deletions web/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn, type WithElementRef } from "$lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";

let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>

<div
bind:this={ref}
data-slot="alert-dialog-footer"
class={cn(
"cn-alert-dialog-footer flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
className
)}
{...restProps}
>
{@render children?.()}
</div>
20 changes: 20 additions & 0 deletions web/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import { cn, type WithElementRef } from "$lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";

let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>

<div
bind:this={ref}
data-slot="alert-dialog-header"
class={cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className)}
{...restProps}
>
{@render children?.()}
</div>
Loading
Loading