aboutsummaryrefslogtreecommitdiffstats
path: root/code/app/src/routes
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-12-09 03:57:12 +0100
committerivarlovlie <git@ivarlovlie.no>2022-12-09 03:57:12 +0100
commit4dbef3fcd7a14437d55c555cf10d50de8e50d7d1 (patch)
tree632589ecfcfb4dfddeafb71d0077257584b5e7ec /code/app/src/routes
parent914c75e0ceeb3e11ddd55e94bb461c26b0db5b7a (diff)
downloadgreatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.tar.xz
greatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.zip
feat: Move everything out of $lib
Diffstat (limited to 'code/app/src/routes')
-rw-r--r--code/app/src/routes/(main)/(app)/+layout.svelte534
-rw-r--r--code/app/src/routes/(main)/(app)/projects/+page.svelte228
-rw-r--r--code/app/src/routes/(main)/(app)/projects/create/+page.svelte20
-rw-r--r--code/app/src/routes/(main)/(app)/settings/+page.svelte106
-rw-r--r--code/app/src/routes/(main)/(public)/+layout.svelte8
-rw-r--r--code/app/src/routes/(main)/(public)/reset-password/+page.svelte30
-rw-r--r--code/app/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts10
-rw-r--r--code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte33
-rw-r--r--code/app/src/routes/(main)/(public)/sign-in/+page.svelte88
-rw-r--r--code/app/src/routes/(main)/(public)/sign-in/tests/index.spec.ts12
-rw-r--r--code/app/src/routes/(main)/(public)/sign-up/+page.svelte46
-rw-r--r--code/app/src/routes/(main)/+layout.server.ts35
-rw-r--r--code/app/src/routes/(main)/+layout.svelte12
-rw-r--r--code/app/src/routes/(main)/+layout.ts18
-rw-r--r--code/app/src/routes/book/alerts/+page.svelte50
-rw-r--r--code/app/src/routes/book/badges/+page.svelte25
-rw-r--r--code/app/src/routes/book/buttons/+page.svelte16
-rw-r--r--code/app/src/routes/book/inputs/+page.svelte28
-rw-r--r--code/app/src/routes/book/toggles/+page.svelte12
19 files changed, 673 insertions, 638 deletions
diff --git a/code/app/src/routes/(main)/(app)/+layout.svelte b/code/app/src/routes/(main)/(app)/+layout.svelte
index a280fa7..6cb70ef 100644
--- a/code/app/src/routes/(main)/(app)/+layout.svelte
+++ b/code/app/src/routes/(main)/(app)/+layout.svelte
@@ -1,151 +1,162 @@
<script lang="ts">
- import {
- ChevronUpDownIcon,
- MagnifyingGlassIcon,
- Bars3CenterLeftIcon,
- XMarkIcon,
- HomeIcon,
- MegaphoneIcon,
- FolderOpenIcon,
- QueueListIcon,
- CalendarIcon,
- } from "$lib/components/icons";
- import { Dialog, Menu, MenuButton, MenuItem, MenuItems, Transition, TransitionChild, TransitionRoot } from "@rgossiaux/svelte-headlessui";
- import { DialogPanel } from "@developermuch/dev-svelte-headlessui";
- import { Input } from "$lib/components";
- import { end_session } from "$lib/session";
- import { goto } from "$app/navigation";
- import { page } from "$app/stores";
+ import {
+ ChevronUpDownIcon,
+ MagnifyingGlassIcon,
+ Bars3CenterLeftIcon,
+ XMarkIcon,
+ HomeIcon,
+ MegaphoneIcon,
+ FolderOpenIcon,
+ QueueListIcon,
+ CalendarIcon,
+ } from "$components/icons";
+ import {AccountService} from "$services/account-service";
+ import {
+ Dialog,
+ Menu,
+ MenuButton,
+ MenuItem,
+ MenuItems,
+ Transition,
+ TransitionChild,
+ TransitionRoot,
+ } from "@rgossiaux/svelte-headlessui";
+ import {DialogPanel} from "@developermuch/dev-svelte-headlessui";
+ import {Input} from "$components";
+ import {goto} from "$app/navigation";
+ import {page} from "$app/stores";
+
+ const accountService = new AccountService();
- const session = {
- profile: {
- username: "Brukernavn",
- displayName: "epost@adresse.no",
- },
- };
+ const session = {
+ profile: {
+ username: "Brukernavn",
+ displayName: "epost@adresse.no",
+ },
+ };
- let sidebarOpen = false;
- let sidebarSearchValue: string | undefined;
+ let sidebarOpen = false;
+ let sidebarSearchValue: string | undefined;
- function sign_out() {
- end_session(() => goto("/sign-in"));
- }
+ function sign_out() {
+ accountService.end_session(() => goto("/sign-in"));
+ }
- const navigationItems = [
- {
- href: "/home",
- name: "Home",
- icon: HomeIcon,
- },
- {
- href: "/projects",
- name: "Projects",
- icon: CalendarIcon,
- },
- {
- href: "/tickets",
- name: "Tickets",
- icon: MegaphoneIcon,
- },
- {
- href: "/todo",
- name: "Todo",
- icon: QueueListIcon,
- },
- {
- href: "/wiki",
- name: "Wiki",
- icon: FolderOpenIcon,
- },
- ];
+ const navigationItems = [
+ {
+ href: "/home",
+ name: "Home",
+ icon: HomeIcon,
+ },
+ {
+ href: "/projects",
+ name: "Projects",
+ icon: CalendarIcon,
+ },
+ {
+ href: "/tickets",
+ name: "Tickets",
+ icon: MegaphoneIcon,
+ },
+ {
+ href: "/todo",
+ name: "Todo",
+ icon: QueueListIcon,
+ },
+ {
+ href: "/wiki",
+ name: "Wiki",
+ icon: FolderOpenIcon,
+ },
+ ];
</script>
<div class="min-h-full">
- <!-- Mobile sidebar -->
- <TransitionRoot show={sidebarOpen}>
- <Dialog as="div" class="relative z-40 lg:hidden" on:close={() => (sidebarOpen = false)}>
- <TransitionChild
- as="div"
- enter="transition-opacity ease-linear duration-300"
- enterFrom="opacity-0"
- enterTo="opacity-100"
- leave="transition-opacity ease-linear duration-300"
- leaveFrom="opacity-100"
- leaveTo="opacity-0"
- >
- <div class="fixed inset-0 bg-gray-600 bg-opacity-75" />
- </TransitionChild>
-
- <div class="fixed inset-0 z-40 flex">
- <TransitionChild
- as="div"
- enter="transition ease-in-out duration-300 transform"
- enterFrom="-translate-x-full"
- enterTo="translate-x-0"
- leave="transition ease-in-out duration-300 transform"
- leaveFrom="translate-x-0"
- leaveTo="-translate-x-full"
- >
- <DialogPanel class="relative flex w-full max-w-xs flex-1 flex-col bg-white pt-5 pb-4">
+ <!-- Mobile sidebar -->
+ <TransitionRoot show={sidebarOpen}>
+ <Dialog as="div" class="relative z-40 lg:hidden" on:close={() => (sidebarOpen = false)}>
<TransitionChild
- as="div"
- enter="ease-in-out duration-300"
- enterFrom="opacity-0"
- enterTo="opacity-100"
- leave="ease-in-out duration-300"
- leaveFrom="opacity-100"
- leaveTo="opacity-0"
+ as="div"
+ enter="transition-opacity ease-linear duration-300"
+ enterFrom="opacity-0"
+ enterTo="opacity-100"
+ leave="transition-opacity ease-linear duration-300"
+ leaveFrom="opacity-100"
+ leaveTo="opacity-0"
>
- <div class="absolute top-0 right-0 -mr-12 pt-2">
- <button
- type="button"
- class="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
- on:click={() => (sidebarOpen = false)}
- >
- <span class="sr-only">Close sidebar</span>
- <XMarkIcon class="text-white" aria-hidden="true" />
- </button>
- </div>
+ <div class="fixed inset-0 bg-gray-600 bg-opacity-75"/>
</TransitionChild>
- <div class="mt-5 h-0 flex-1 overflow-y-auto">
- <nav class="px-2">
- <div class="space-y-1">
- {#each navigationItems as item}
- {@const current = $page.url.pathname.startsWith(item.href)}
- <a
- href={item.href}
- aria-current={current ? "page" : undefined}
- class="group flex items-center px-2 py-2 text-base leading-5 font-medium rounded-md
+
+ <div class="fixed inset-0 z-40 flex">
+ <TransitionChild
+ as="div"
+ enter="transition ease-in-out duration-300 transform"
+ enterFrom="-translate-x-full"
+ enterTo="translate-x-0"
+ leave="transition ease-in-out duration-300 transform"
+ leaveFrom="translate-x-0"
+ leaveTo="-translate-x-full"
+ >
+ <DialogPanel class="relative flex w-full max-w-xs flex-1 flex-col bg-white pt-5 pb-4">
+ <TransitionChild
+ as="div"
+ enter="ease-in-out duration-300"
+ enterFrom="opacity-0"
+ enterTo="opacity-100"
+ leave="ease-in-out duration-300"
+ leaveFrom="opacity-100"
+ leaveTo="opacity-0"
+ >
+ <div class="absolute top-0 right-0 -mr-12 pt-2">
+ <button
+ type="button"
+ class="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
+ on:click={() => (sidebarOpen = false)}
+ >
+ <span class="sr-only">Close sidebar</span>
+ <XMarkIcon class="text-white" aria-hidden="true"/>
+ </button>
+ </div>
+ </TransitionChild>
+ <div class="mt-5 h-0 flex-1 overflow-y-auto">
+ <nav class="px-2">
+ <div class="space-y-1">
+ {#each navigationItems as item}
+ {@const current = $page.url.pathname.startsWith(item.href)}
+ <a
+ href={item.href}
+ aria-current={current ? "page" : undefined}
+ class="group flex items-center px-2 py-2 text-base leading-5 font-medium rounded-md
{current ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-50'}"
- >
- <svelte:component
- this={item.icon}
- class="mr-3 flex-shrink-0 h-6 w-6 {current ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500'}"
- aria-hidden="true"
- />
- {item.name}
- </a>
- {/each}
+ >
+ <svelte:component
+ this={item.icon}
+ class="mr-3 flex-shrink-0 h-6 w-6 {current ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500'}"
+ aria-hidden="true"
+ />
+ {item.name}
+ </a>
+ {/each}
+ </div>
+ </nav>
+ </div>
+ </DialogPanel>
+ </TransitionChild>
+ <div class="w-14 flex-shrink-0" aria-hidden="true">
+ <!-- Dummy element to force sidebar to shrink to fit close icon -->
</div>
- </nav>
</div>
- </DialogPanel>
- </TransitionChild>
- <div class="w-14 flex-shrink-0" aria-hidden="true">
- <!-- Dummy element to force sidebar to shrink to fit close icon -->
- </div>
- </div>
- </Dialog>
- </TransitionRoot>
+ </Dialog>
+ </TransitionRoot>
- <!-- Static sidebar for desktop -->
- <div class="hidden lg:fixed lg:inset-y-0 lg:flex lg:w-64 lg:flex-col lg:border-r lg:border-gray-200 lg:bg-gray-100 lg:pb-4">
- <div class="flex h-0 flex-1 p-3 flex-col overflow-y-auto">
- <!-- User account dropdown -->
- <Menu class="relative inline-block text-left">
- <MenuButton
- class="group w-full rounded-md bg-gray-100 px-3.5 py-2 text-left text-sm font-medium text-gray-700 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-teal-500 focus:ring-offset-2 focus:ring-offset-gray-100"
- >
+ <!-- Static sidebar for desktop -->
+ <div class="hidden lg:fixed lg:inset-y-0 lg:flex lg:w-64 lg:flex-col lg:border-r lg:border-gray-200 lg:bg-gray-100 lg:pb-4">
+ <div class="flex h-0 flex-1 p-3 flex-col overflow-y-auto">
+ <!-- User account dropdown -->
+ <Menu class="relative inline-block text-left">
+ <MenuButton
+ class="group w-full rounded-md bg-gray-100 px-3.5 py-2 text-left text-sm font-medium text-gray-700 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-teal-500 focus:ring-offset-2 focus:ring-offset-gray-100"
+ >
<span class="flex w-full items-center justify-between">
<span class="flex min-w-0 items-center justify-between space-x-3">
<span class="flex min-w-0 flex-1 flex-col">
@@ -155,142 +166,151 @@
<span class="truncate text-sm text-gray-500">{session.profile.displayName}</span>
</span>
</span>
- <ChevronUpDownIcon class="flex-shrink-0 text-gray-400 group-hover:text-gray-500" aria-hidden="true" />
+ <ChevronUpDownIcon class="flex-shrink-0 text-gray-400 group-hover:text-gray-500" aria-hidden="true"/>
</span>
- </MenuButton>
- <Transition
- leave="transition ease-in duration-75"
- enter="transition ease-out duration-100"
- enterFrom="transform opacity-0 scale-95"
- enterTo="transform opacity-100 scale-100"
- leaveFrom="transform opacity-100 scale-100"
- leaveTo="transform opacity-0 scale-95"
- as="div"
- >
- <MenuItems
- class="absolute right-0 left-0 z-10 mt-1 origin-top divide-y divide-gray-200 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
- >
- <div class="py-1">
- <MenuItem>
- <a href="/profile" class="text-gray-700 block px-4 py-2 text-sm hover:text-gray-900 hover:bg-gray-100"> View profile </a>
- </MenuItem>
- <MenuItem>
- <a href="/settings" class="text-gray-700 block px-4 py-2 text-sm hover:text-gray-900 hover:bg-gray-100"> Settings </a>
- </MenuItem>
- </div>
- <div class="py-1">
- <MenuItem>
+ </MenuButton>
+ <Transition
+ leave="transition ease-in duration-75"
+ enter="transition ease-out duration-100"
+ enterFrom="transform opacity-0 scale-95"
+ enterTo="transform opacity-100 scale-100"
+ leaveFrom="transform opacity-100 scale-100"
+ leaveTo="transform opacity-0 scale-95"
+ as="div"
+ >
+ <MenuItems
+ class="absolute right-0 left-0 z-10 mt-1 origin-top divide-y divide-gray-200 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
+ >
+ <div class="py-1">
+ <MenuItem>
+ <a href="/profile"
+ class="text-gray-700 block px-4 py-2 text-sm hover:text-gray-900 hover:bg-gray-100">
+ View profile </a>
+ </MenuItem>
+ <MenuItem>
+ <a href="/settings"
+ class="text-gray-700 block px-4 py-2 text-sm hover:text-gray-900 hover:bg-gray-100">
+ Settings </a>
+ </MenuItem>
+ </div>
+ <div class="py-1">
+ <MenuItem>
<span
- on:click={() => sign_out()}
- class="text-gray-700 block px-4 py-2 text-sm hover:bg-red-200 hover:text-red-900 cursor-pointer"
+ on:click={() => sign_out()}
+ class="text-gray-700 block px-4 py-2 text-sm hover:bg-red-200 hover:text-red-900 cursor-pointer"
>
Sign out
</span>
- </MenuItem>
+ </MenuItem>
+ </div>
+ </MenuItems>
+ </Transition>
+ </Menu>
+ <!-- Sidebar Search -->
+ <div class="mt-3 hidden">
+ <label for="search" class="sr-only">Search</label>
+ <div class="relative mt-1 rounded-md shadow-sm">
+ <Input type="search" name="search" icon={MagnifyingGlassIcon} placeholder="Search"
+ bind:value={sidebarSearchValue}/>
+ </div>
</div>
- </MenuItems>
- </Transition>
- </Menu>
- <!-- Sidebar Search -->
- <div class="mt-3 hidden">
- <label for="search" class="sr-only">Search</label>
- <div class="relative mt-1 rounded-md shadow-sm">
- <Input type="search" name="search" icon={MagnifyingGlassIcon} placeholder="Search" bind:value={sidebarSearchValue} />
- </div>
- </div>
- <!-- Navigation -->
- <nav class="mt-5">
- <div class="space-y-1">
- {#each navigationItems as item}
- {@const current = $page.url.pathname.startsWith(item.href)}
- <a
- href={item.href}
- aria-current={current ? "page" : undefined}
- class="group flex items-center px-2 py-2 text-base leading-5 font-medium rounded-md
+ <!-- Navigation -->
+ <nav class="mt-5">
+ <div class="space-y-1">
+ {#each navigationItems as item}
+ {@const current = $page.url.pathname.startsWith(item.href)}
+ <a
+ href={item.href}
+ aria-current={current ? "page" : undefined}
+ class="group flex items-center px-2 py-2 text-base leading-5 font-medium rounded-md
{current ? 'bg-gray-200 text-gray-900' : 'text-gray-700 hover:text-gray-900 hover:bg-gray-50'}"
- >
- <svelte:component
- this={item.icon}
- class="mr-3 flex-shrink-0 h-6 w-6 {current ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500'}"
- aria-hidden="true"
- />
- {item.name}
- </a>
- {/each}
+ >
+ <svelte:component
+ this={item.icon}
+ class="mr-3 flex-shrink-0 h-6 w-6 {current ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500'}"
+ aria-hidden="true"
+ />
+ {item.name}
+ </a>
+ {/each}
+ </div>
+ </nav>
</div>
- </nav>
</div>
- </div>
- <!-- Main column -->
- <div class="flex flex-col lg:pl-64">
- <!-- Search header -->
- <div class="sticky top-0 z-10 flex h-16 flex-shrink-0 border-b border-gray-200 bg-white lg:hidden">
- <button
- type="button"
- class="border-r border-gray-200 px-4 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-teal-500 lg:hidden"
- on:click={() => (sidebarOpen = true)}
- >
- <span class="sr-only">Open sidebar</span>
- <Bars3CenterLeftIcon aria-hidden="true" />
- </button>
- <div class="flex flex-1 justify-between px-4 sm:px-6 lg:px-8">
- <div class="flex flex-1">
- <form class="flex w-full md:ml-0" action="#" method="GET">
- <label for="search-field" class="sr-only">Search</label>
- <div class="relative w-full text-gray-400 focus-within:text-gray-600">
- <Input
- bind:value={sidebarSearchValue}
- icon={MagnifyingGlassIcon}
- id="search-field"
- name="search-field"
- placeholder="Search"
- type="search"
- />
- </div>
- </form>
- </div>
- <div class="flex items-center">
- <!-- Profile dropdown -->
- <Menu as="div" class="relative ml-3">
- <div>
- <MenuButton
- class="flex max-w-xs items-center rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-teal-500 focus:ring-offset-2"
- >
- <span class="sr-only">Open user menu</span>
- </MenuButton>
- </div>
- <Transition
- enterFrom="transform opacity-0 scale-95"
- enterTo="transform opacity-100 scale-100"
- leaveFrom="transform opacity-100 scale-100"
- leaveTo="transform opacity-0 scale-95"
- as="div"
+ <!-- Main column -->
+ <div class="flex flex-col lg:pl-64">
+ <!-- Search header -->
+ <div class="sticky top-0 z-10 flex h-16 flex-shrink-0 border-b border-gray-200 bg-white lg:hidden">
+ <button
+ type="button"
+ class="border-r border-gray-200 px-4 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-teal-500 lg:hidden"
+ on:click={() => (sidebarOpen = true)}
>
- <MenuItems
- class="absolute right-0 z-10 mt-2 w-48 origin-top-right divide-y divide-gray-200 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
- >
- <div class="py-1">
- <MenuItem>
- <a href="/profile" class="text-gray-700 block px-4 py-2 text-sm"> View profile </a>
- </MenuItem>
- <MenuItem>
- <a href="/settings" class="text-gray-700 block px-4 py-2 text-sm hover:text-gray-900 hover:bg-gray-100"> Settings </a>
- </MenuItem>
- <div class="py-1">
- <MenuItem>
- <span on:click={() => sign_out()} class="text-gray-700 block px-4 py-2 text-sm"> Sign out </span>
- </MenuItem>
- </div>
+ <span class="sr-only">Open sidebar</span>
+ <Bars3CenterLeftIcon aria-hidden="true"/>
+ </button>
+ <div class="flex flex-1 justify-between px-4 sm:px-6 lg:px-8">
+ <div class="flex flex-1">
+ <form class="flex w-full md:ml-0" action="#" method="GET">
+ <label for="search-field" class="sr-only">Search</label>
+ <div class="relative w-full text-gray-400 focus-within:text-gray-600">
+ <Input
+ bind:value={sidebarSearchValue}
+ icon={MagnifyingGlassIcon}
+ id="search-field"
+ name="search-field"
+ placeholder="Search"
+ type="search"
+ />
+ </div>
+ </form>
</div>
- </MenuItems>
- </Transition>
- </Menu>
+ <div class="flex items-center">
+ <!-- Profile dropdown -->
+ <Menu as="div" class="relative ml-3">
+ <div>
+ <MenuButton
+ class="flex max-w-xs items-center rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-teal-500 focus:ring-offset-2"
+ >
+ <span class="sr-only">Open user menu</span>
+ </MenuButton>
+ </div>
+ <Transition
+ enterFrom="transform opacity-0 scale-95"
+ enterTo="transform opacity-100 scale-100"
+ leaveFrom="transform opacity-100 scale-100"
+ leaveTo="transform opacity-0 scale-95"
+ as="div"
+ >
+ <MenuItems
+ class="absolute right-0 z-10 mt-2 w-48 origin-top-right divide-y divide-gray-200 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
+ >
+ <div class="py-1">
+ <MenuItem>
+ <a href="/profile" class="text-gray-700 block px-4 py-2 text-sm"> View
+ profile </a>
+ </MenuItem>
+ <MenuItem>
+ <a href="/settings"
+ class="text-gray-700 block px-4 py-2 text-sm hover:text-gray-900 hover:bg-gray-100">
+ Settings </a>
+ </MenuItem>
+ <div class="py-1">
+ <MenuItem>
+ <span on:click={() => sign_out()}
+ class="text-gray-700 block px-4 py-2 text-sm"> Sign out </span>
+ </MenuItem>
+ </div>
+ </div>
+ </MenuItems>
+ </Transition>
+ </Menu>
+ </div>
+ </div>
</div>
- </div>
+ <main class="flex-1 p-3">
+ <slot/>
+ </main>
</div>
- <main class="flex-1 p-3">
- <slot />
- </main>
- </div>
</div>
diff --git a/code/app/src/routes/(main)/(app)/projects/+page.svelte b/code/app/src/routes/(main)/(app)/projects/+page.svelte
index e39a886..1508118 100644
--- a/code/app/src/routes/(main)/(app)/projects/+page.svelte
+++ b/code/app/src/routes/(main)/(app)/projects/+page.svelte
@@ -1,137 +1,143 @@
<script lang="ts">
- import { Button, ProjectStatusBadge, Input } from "$lib/components";
- import type { Project } from "$lib/models/projects/Project";
- import { onMount } from "svelte";
- import { faker } from "@faker-js/faker";
- import { Temporal } from "temporal-polyfill";
- import { createTable, Subscribe, Render } from "svelte-headless-table";
- import { addSortBy, addTableFilter } from "svelte-headless-table/plugins";
- import { ProjectStatus } from "$lib/models/projects/ProjectStatus";
- import { writable, type Writable } from "svelte/store";
- import { ChevronDownIcon, ChevronUpIcon, ChevronUpDownIcon, MagnifyingGlassIcon, FunnelIcon } from "$lib/components/icons";
- import LL from "$lib/i18n/i18n-svelte";
- import { goto } from "$app/navigation";
+ import {Button, ProjectStatusBadge, Input} from "$components";
+ import type {Project} from "$models/projects/Project";
+ import {onMount} from "svelte";
+ import {faker} from "@faker-js/faker";
+ import {Temporal} from "temporal-polyfill";
+ import {createTable, Subscribe, Render} from "svelte-headless-table";
+ import {addSortBy, addTableFilter} from "svelte-headless-table/plugins";
+ import {ProjectStatus} from "$models/projects/ProjectStatus";
+ import {writable, type Writable} from "svelte/store";
+ import {
+ ChevronDownIcon,
+ ChevronUpIcon,
+ ChevronUpDownIcon,
+ MagnifyingGlassIcon,
+ FunnelIcon,
+ } from "$components/icons";
+ import LL from "$i18n/i18n-svelte";
+ import {goto} from "$app/navigation";
- let projects: Writable<Array<Project>> = writable([]);
+ let projects: Writable<Array<Project>> = writable([]);
- onMount(() => {
- let i = 0;
- const tempProjects = [];
- while (i < 101) {
- tempProjects.push({
- id: crypto.randomUUID(),
- name: faker.lorem.word(),
- start: Temporal.Now.plainDateISO().toLocaleString(),
- description: faker.lorem.words(3),
- members: [],
- status: ProjectStatus.IDLE,
- });
- i++;
- }
- projects.set(tempProjects);
- });
+ onMount(() => {
+ let i = 0;
+ const tempProjects = [];
+ while (i < 101) {
+ tempProjects.push({
+ id: crypto.randomUUID(),
+ name: faker.lorem.word(),
+ start: Temporal.Now.plainDateISO().toLocaleString(),
+ description: faker.lorem.words(3),
+ members: [],
+ status: ProjectStatus.IDLE,
+ });
+ i++;
+ }
+ projects.set(tempProjects);
+ });
- function on_open_project(event) {
- if (event.code && (event.code !== "Enter" || event.code !== "Space")) return;
- const name = event.target.innerText;
- const projectId = $projects.find((p) => p.name === name).id;
- goto("/projects/" + projectId);
- }
+ function on_open_project(event) {
+ if (event.code && (event.code !== "Enter" || event.code !== "Space")) return;
+ const name = event.target.innerText;
+ const projectId = $projects.find((p) => p.name === name).id;
+ goto("/projects/" + projectId);
+ }
- const table = createTable(projects, {
- sort: addSortBy(),
- filter: addTableFilter(),
- });
+ const table = createTable(projects, {
+ sort: addSortBy(),
+ filter: addTableFilter(),
+ });
- const columns = table.createColumns([
- table.column({ header: $LL.name(), accessor: "name" }),
- table.column({ header: "Status", accessor: "status" }),
- table.column({ header: "Start", accessor: "start" }),
- table.column({ header: "Description", accessor: "description", plugins: { sort: { disable: true } } }),
- ]);
+ const columns = table.createColumns([
+ table.column({header: $LL.name(), accessor: "name"}),
+ table.column({header: "Status", accessor: "status"}),
+ table.column({header: "Start", accessor: "start"}),
+ table.column({header: "Description", accessor: "description", plugins: {sort: {disable: true}}}),
+ ]);
- const { headerRows, rows, tableAttrs, tableBodyAttrs, pluginStates } = table.createViewModel(columns);
- const { filterValue } = pluginStates.filter;
+ const {headerRows, rows, tableAttrs, tableBodyAttrs, pluginStates} = table.createViewModel(columns);
+ const {filterValue} = pluginStates.filter;
</script>
<div class="sm:flex sm:items-center">
- <div class="sm:flex-auto">
- <h1 class="text-xl font-semibold text-gray-900">Projects</h1>
- <p class="mt-2 text-sm text-gray-700">A list of all the projects in your organsation.</p>
- </div>
- <div class="mt-4 sm:mt-0 sm:ml-16 inline-flex gap-1 sm:flex-none">
- <Input icon={MagnifyingGlassIcon} placeholder="Search" bind:value={$filterValue} />
- <Button text="Create project" href="/projects/create" />
- </div>
+ <div class="sm:flex-auto">
+ <h1 class="text-xl font-semibold text-gray-900">Projects</h1>
+ <p class="mt-2 text-sm text-gray-700">A list of all the projects in your organsation.</p>
+ </div>
+ <div class="mt-4 sm:mt-0 sm:ml-16 inline-flex gap-1 sm:flex-none">
+ <Input icon={MagnifyingGlassIcon} placeholder="Search" bind:value={$filterValue}/>
+ <Button text="Create project" href="/projects/create"/>
+ </div>
</div>
<div class="-mx-2 mt-6 rounded-md shadow overflow-auto max-h-[80vh] sm:-mx-6 md:mx-0">
- <table {...$tableAttrs} class="min-w-full divide-y divide-gray-300">
- <thead class="bg-gray-50">
- {#each $headerRows as headerRow (headerRow.id)}
- <Subscribe rowAttrs={headerRow.attrs()} let:rowAttrs>
- <tr {...rowAttrs} class="shadow-sm">
- {#each headerRow.cells as cell (cell.id)}
- <Subscribe attrs={cell.attrs()} let:attrs props={cell.props()} let:props>
- <th
- {...attrs}
- scope="col"
- class="sticky top-0 bg-gray-50 bg-opacity-100 whitespace-nowrap px-2 py-3.5 text-left text-sm font-semibold text-gray-900"
- >
- <div class="group inline-flex">
- <Render of={cell.render()} />
- <span
- on:click={props.sort.toggle}
- on:keypress={props.sort.toggle}
- class="{props.sort.disabled
+ <table {...$tableAttrs} class="min-w-full divide-y divide-gray-300">
+ <thead class="bg-gray-50">
+ {#each $headerRows as headerRow (headerRow.id)}
+ <Subscribe rowAttrs={headerRow.attrs()} let:rowAttrs>
+ <tr {...rowAttrs} class="shadow-sm">
+ {#each headerRow.cells as cell (cell.id)}
+ <Subscribe attrs={cell.attrs()} let:attrs props={cell.props()} let:props>
+ <th
+ {...attrs}
+ scope="col"
+ class="sticky top-0 bg-gray-50 bg-opacity-100 whitespace-nowrap px-2 py-3.5 text-left text-sm font-semibold text-gray-900"
+ >
+ <div class="group inline-flex">
+ <Render of={cell.render()}/>
+ <span
+ on:click={props.sort.toggle}
+ on:keypress={props.sort.toggle}
+ class="{props.sort.disabled
? 'bg-gray-200 text-gray-900 group-hover:bg-gray-300'
: 'invisible text-gray-400 group-hover:visible group-focus:visible'}
{props.sort.disabled ? '' : 'cursor-pointer'}
ml-2 flex-none rounded"
- >
+ >
{#if props.sort.order === "asc"}
- <ChevronUpIcon />
+ <ChevronUpIcon/>
{:else if props.sort.order === "desc"}
- <ChevronDownIcon />
+ <ChevronDownIcon/>
{:else if !props.sort.disabled}
- <ChevronUpDownIcon />
+ <ChevronUpDownIcon/>
{/if}
</span>
- {#if cell.id === "status"}
+ {#if cell.id === "status"}
<span class="invisible text-gray-400 cursor-pointer group-hover:visible group-focus:visible ml-2 flex-none rounded">
- <FunnelIcon />
+ <FunnelIcon/>
</span>
- {/if}
- </div>
- </th>
- </Subscribe>
- {/each}
- </tr>
- </Subscribe>
- {/each}
- </thead>
- <tbody {...$tableBodyAttrs} class="divide-y divide-gray-200 bg-white">
- {#each $rows as row (row.id)}
- <Subscribe rowAttrs={row.attrs()} let:rowAttrs>
- <tr {...rowAttrs}>
- {#each row.cells as cell (cell.id)}
- {@const materialisedCell = cell.render()}
- <Subscribe attrs={cell.attrs()} let:attrs>
- <td {...attrs} class="whitespace-nowrap px-2 py-2 text-sm">
- {#if cell.id === "name"}
+ {/if}
+ </div>
+ </th>
+ </Subscribe>
+ {/each}
+ </tr>
+ </Subscribe>
+ {/each}
+ </thead>
+ <tbody {...$tableBodyAttrs} class="divide-y divide-gray-200 bg-white">
+ {#each $rows as row (row.id)}
+ <Subscribe rowAttrs={row.attrs()} let:rowAttrs>
+ <tr {...rowAttrs}>
+ {#each row.cells as cell (cell.id)}
+ {@const materialisedCell = cell.render()}
+ <Subscribe attrs={cell.attrs()} let:attrs>
+ <td {...attrs} class="whitespace-nowrap px-2 py-2 text-sm">
+ {#if cell.id === "name"}
<span class="link" title="Open project" on:click={on_open_project} on:keypress={on_open_project}>
- <Render of={materialisedCell} />
+ <Render of={materialisedCell}/>
</span>
- {:else if cell.id === "status"}
- <ProjectStatusBadge status={materialisedCell.toString()} />
- {:else}
- <Render of={materialisedCell} />
- {/if}
- </td>
- </Subscribe>
- {/each}
- </tr>
- </Subscribe>
- {/each}
- </tbody>
- </table>
+ {:else if cell.id === "status"}
+ <ProjectStatusBadge status={materialisedCell.toString()}/>
+ {:else}
+ <Render of={materialisedCell}/>
+ {/if}
+ </td>
+ </Subscribe>
+ {/each}
+ </tr>
+ </Subscribe>
+ {/each}
+ </tbody>
+ </table>
</div>
diff --git a/code/app/src/routes/(main)/(app)/projects/create/+page.svelte b/code/app/src/routes/(main)/(app)/projects/create/+page.svelte
index 1741506..ab38b2e 100644
--- a/code/app/src/routes/(main)/(app)/projects/create/+page.svelte
+++ b/code/app/src/routes/(main)/(app)/projects/create/+page.svelte
@@ -1,8 +1,8 @@
<script lang="ts">
- import { useSWR } from "sswr";
- import { Input, TextArea, Combobox, Button } from "$lib/components";
- import type { ProjectMember } from "$lib/models/projects/ProjectMember";
- import LL from "$lib/i18n/i18n-svelte";
+ import {useSWR} from "sswr";
+ import {Input, TextArea, Combobox, Button} from "$components";
+ import type {ProjectMember} from "$models/projects/ProjectMember";
+ import LL from "$i18n/i18n-svelte";
const formData = {
name: {
@@ -36,16 +36,16 @@
alert("Submitted");
}
- const { data: members } = useSWR("projectMembers");
+ const {data: members} = useSWR("projectMembers");
</script>
<h1>Create a new project</h1>
<form on:submit|preventDefault={submit_form_async} class="max-w-md flex flex-col gap-2">
- <Input label="Name" bind:value={formData.name.value} errors={formData.name.errors} required />
- <TextArea label="Description" bind:value={formData.description.value} errors={formData.description.errors} />
+ <Input label="Name" bind:value={formData.name.value} errors={formData.name.errors} required/>
+ <TextArea label="Description" bind:value={formData.description.value} errors={formData.description.errors}/>
<section class="grid grid-flow-row sm:grid-flow-col gap-2">
- <Input type="date" label="Start" bind:value={formData.start.value} errors={formData.start.errors} />
- <Input type="date" label="Stop" bind:value={formData.stop.value} errors={formData.stop.errors} />
+ <Input type="date" label="Start" bind:value={formData.start.value} errors={formData.start.errors}/>
+ <Input type="date" label="Stop" bind:value={formData.stop.value} errors={formData.stop.errors}/>
</section>
<Combobox options={$members} label={$LL.app.members()}>
<svelte:fragment slot="no-records">
@@ -57,5 +57,5 @@
{/if}
</svelte:fragment>
</Combobox>
- <Button text={$LL.submit()} />
+ <Button text={$LL.submit()}/>
</form>
diff --git a/code/app/src/routes/(main)/(app)/settings/+page.svelte b/code/app/src/routes/(main)/(app)/settings/+page.svelte
index 1f0cc67..1c9a910 100644
--- a/code/app/src/routes/(main)/(app)/settings/+page.svelte
+++ b/code/app/src/routes/(main)/(app)/settings/+page.svelte
@@ -1,5 +1,5 @@
<script lang="ts">
- import { Input, Button, Switch } from "$lib/components";
+ import {Input, Button, Switch} from "$components";
</script>
<div class="relative mx-auto max-w-4xl md:px-8 xl:px-0">
@@ -13,9 +13,9 @@
<div class="lg:hidden">
<label for="selected-tab" class="sr-only">Select a tab</label>
<select
- id="selected-tab"
- name="selected-tab"
- class="mt-1 block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-purple-500 focus:outline-none focus:ring-purple-500 sm:text-sm"
+ id="selected-tab"
+ name="selected-tab"
+ class="mt-1 block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-purple-500 focus:outline-none focus:ring-purple-500 sm:text-sm"
>
<option selected>General</option>
@@ -34,38 +34,39 @@
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8">
<!-- Current: "border-purple-500 text-purple-600", Default: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" -->
- <a href="#" class="border-purple-500 text-purple-600 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
- >General</a
+ <a href="#"
+ class="border-purple-500 text-purple-600 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+ >General</a
>
<a
- href="#"
- class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
- >Password</a
+ href="#"
+ class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+ >Password</a
>
<a
- href="#"
- class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
- >Notifications</a
+ href="#"
+ class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+ >Notifications</a
>
<a
- href="#"
- class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
- >Plan</a
+ href="#"
+ class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+ >Plan</a
>
<a
- href="#"
- class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
- >Billing</a
+ href="#"
+ class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+ >Billing</a
>
<a
- href="#"
- class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
- >Team Members</a
+ href="#"
+ class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+ >Team Members</a
>
</nav>
</div>
@@ -87,9 +88,9 @@
<span class="flex-grow">Chelsea Hagon</span>
<span class="ml-4 flex-shrink-0">
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Update</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Update</button
>
</span>
</dd>
@@ -99,22 +100,22 @@
<dd class="mt-1 flex text-sm text-gray-900 sm:col-span-2 sm:mt-0">
<span class="flex-grow">
<img
- class="h-8 w-8 rounded-full"
- src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
- alt=""
+ class="h-8 w-8 rounded-full"
+ src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
+ alt=""
/>
</span>
<span class="ml-4 flex flex-shrink-0 items-start space-x-4">
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Update</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Update</button
>
<span class="text-gray-300" aria-hidden="true">|</span>
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Remove</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Remove</button
>
</span>
</dd>
@@ -125,9 +126,9 @@
<span class="flex-grow">chelsea.hagon@example.com</span>
<span class="ml-4 flex-shrink-0">
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Update</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Update</button
>
</span>
</dd>
@@ -138,9 +139,9 @@
<span class="flex-grow">Human Resources Manager</span>
<span class="ml-4 flex-shrink-0">
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Update</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Update</button
>
</span>
</dd>
@@ -152,7 +153,8 @@
<div class="mt-10 divide-y divide-gray-200">
<div class="space-y-1">
<h3 class="text-lg font-medium leading-6 text-gray-900">Account</h3>
- <p class="max-w-2xl text-sm text-gray-500">Manage how information is displayed on your account.</p>
+ <p class="max-w-2xl text-sm text-gray-500">Manage how information is displayed on your
+ account.</p>
</div>
<div class="mt-6">
<dl class="divide-y divide-gray-200">
@@ -162,9 +164,9 @@
<span class="flex-grow">English</span>
<span class="ml-4 flex-shrink-0">
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Update</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Update</button
>
</span>
</dd>
@@ -175,22 +177,24 @@
<span class="flex-grow">DD-MM-YYYY</span>
<span class="ml-4 flex flex-shrink-0 items-start space-x-4">
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Update</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Update</button
>
<span class="text-gray-300" aria-hidden="true">|</span>
<button
- type="button"
- class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
- >Remove</button
+ type="button"
+ class="rounded-md bg-white font-medium text-purple-600 hover:text-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
+ >Remove</button
>
</span>
</dd>
</div>
<div class="py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:py-5 sm:pt-5">
- <dt class="text-sm font-medium text-gray-500" id="timezone-option-label">Automatic timezone</dt>
- <Switch />
+ <dt class="text-sm font-medium text-gray-500" id="timezone-option-label">Automatic
+ timezone
+ </dt>
+ <Switch/>
</div>
</dl>
</div>
diff --git a/code/app/src/routes/(main)/(public)/+layout.svelte b/code/app/src/routes/(main)/(public)/+layout.svelte
index cbda776..0d84f9a 100644
--- a/code/app/src/routes/(main)/(public)/+layout.svelte
+++ b/code/app/src/routes/(main)/(public)/+layout.svelte
@@ -1,10 +1,10 @@
<script>
- import { LocaleSwitcher } from "$lib/components";
- import LL from "$lib/i18n/i18n-svelte";
+ import {LocaleSwitcher} from "$components";
+ import LL from "$i18n/i18n-svelte";
</script>
-<LocaleSwitcher tabindex={-1} />
-<slot />
+<LocaleSwitcher tabindex={-1}/>
+<slot/>
<footer class="grid sm:gap-5 grid-flow-row sm:justify-center px-2 sm:grid-flow-col">
<a href="https://greatoffice.life/privacy" class="link">
{$LL.privacyPolicy()}
diff --git a/code/app/src/routes/(main)/(public)/reset-password/+page.svelte b/code/app/src/routes/(main)/(public)/reset-password/+page.svelte
index 2b34dfc..34dabae 100644
--- a/code/app/src/routes/(main)/(public)/reset-password/+page.svelte
+++ b/code/app/src/routes/(main)/(public)/reset-password/+page.svelte
@@ -1,8 +1,8 @@
<script lang="ts">
- import { Alert, Input, Button } from "$lib/components";
- import LL from "$lib/i18n/i18n-svelte";
- import { FormError } from "$lib/models/internal/FormError";
- import { PasswordResetService } from "$lib/services/password-reset-service";
+ import {Alert, Input, Button} from "$components";
+ import LL from "$i18n/i18n-svelte";
+ import {FormError} from "$models/internal/FormError";
+ import {PasswordResetService} from "$services/password-reset-service";
const formData = {
email: {
@@ -61,21 +61,21 @@
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<form class="space-y-6" on:submit|preventDefault={submit_form_async}>
{#if showErrorAlert}
- <Alert title={formError.title} message={formError.subtitle} type="error" />
+ <Alert title={formError.title} message={formError.subtitle} type="error"/>
{:else if showSuccessAlert}
- <Alert type="success" title={$LL.success()} message={$LL.resetPasswordPage.requestSentMessage()} />
+ <Alert type="success" title={$LL.success()} message={$LL.resetPasswordPage.requestSentMessage()}/>
{/if}
<Input
- id="email"
- name="email"
- type="email"
- autocomplete="email"
- errors={formData.email.errors}
- bind:value={formData.email.value}
- required
- label={$LL.emailAddress()}
+ id="email"
+ name="email"
+ type="email"
+ autocomplete="email"
+ errors={formData.email.errors}
+ bind:value={formData.email.value}
+ required
+ label={$LL.emailAddress()}
/>
- <Button text={$LL.submit()} type="submit" {loading} fullWidth />
+ <Button text={$LL.submit()} type="submit" {loading} fullWidth/>
</form>
</div>
</div>
diff --git a/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts b/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts
index 389d04c..907b444 100644
--- a/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts
+++ b/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts
@@ -1,11 +1,11 @@
-import { is_guid } from '$lib/helpers';
-import { redirect } from '@sveltejs/kit';
-import type { PageServerLoad } from './$types';
+import {is_guid} from "$help";
+import {redirect} from "@sveltejs/kit";
+import type {PageServerLoad} from "./$types";
-export const load: PageServerLoad = async ({ params }) => {
+export const load: PageServerLoad = async ({params}) => {
const resetRequestId = params.id ?? "";
if (!is_guid(resetRequestId)) throw redirect(302, "/reset-password");
return {
- resetRequestId
+ resetRequestId,
};
}; \ No newline at end of file
diff --git a/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte b/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte
index ba59a8f..8f817bf 100644
--- a/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte
+++ b/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte
@@ -1,11 +1,11 @@
<script lang="ts">
- import { onMount } from "svelte";
- import LL from "$lib/i18n/i18n-svelte";
- import { Alert, Input, Button } from "$lib/components";
- import type { PageServerData } from "./$types";
- import { goto } from "$app/navigation";
- import { SignInPageMessage, signInPageMessageQueryKey } from "$routes/(main)/(public)/sign-in";
- import { PasswordResetService } from "$lib/services/password-reset-service";
+ import {onMount} from "svelte";
+ import LL from "$i18n/i18n-svelte";
+ import {Alert, Input, Button} from "$components";
+ import type {PageServerData} from "./$types";
+ import {goto} from "$app/navigation";
+ import {SignInPageMessage, signInPageMessageQueryKey} from "$routes/(main)/(public)/sign-in";
+ import {PasswordResetService} from "$services/password-reset-service";
export let data: PageServerData;
const passwordResets = new PasswordResetService();
@@ -57,18 +57,19 @@
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<form class="space-y-6" on:submit|preventDefault={submitFormAsync}>
{#if requestIsInvalid}
- <Alert title={$LL.resetPasswordPage.invalidRequestTitle()} message={$LL.resetPasswordPage.invalidRequestMessage()} />
+ <Alert title={$LL.resetPasswordPage.invalidRequestTitle()}
+ message={$LL.resetPasswordPage.invalidRequestMessage()}/>
{/if}
<Input
- id="password"
- name="password"
- type="password"
- autocomplete="new-password"
- required
- bind:value={formData.newPassword.value}
- label={$LL.resetPasswordPage.newPassword()}
+ id="password"
+ name="password"
+ type="password"
+ autocomplete="new-password"
+ required
+ bind:value={formData.newPassword.value}
+ label={$LL.resetPasswordPage.newPassword()}
/>
- <Button text={$LL.submit()} type="submit" {loading} fullWidth />
+ <Button text={$LL.submit()} type="submit" {loading} fullWidth/>
</form>
</div>
</div>
diff --git a/code/app/src/routes/(main)/(public)/sign-in/+page.svelte b/code/app/src/routes/(main)/(public)/sign-in/+page.svelte
index 12801c5..e862050 100644
--- a/code/app/src/routes/(main)/(public)/sign-in/+page.svelte
+++ b/code/app/src/routes/(main)/(public)/sign-in/+page.svelte
@@ -1,13 +1,13 @@
<script lang="ts">
- import { goto } from "$app/navigation";
- import { Button, Checkbox, Input, Alert } from "$lib/components";
- import LL from "$lib/i18n/i18n-svelte";
+ import {goto} from "$app/navigation";
+ import {Button, Checkbox, Input, Alert} from "$components";
+ import LL from "$i18n/i18n-svelte";
import pwKey from "$actions/pwKey";
- import { onMount } from "svelte";
- import { signInPageMessageQueryKey, signInPageTestKeys, type SignInPageMessage } from ".";
- import { AccountService } from "$lib/services/account-service";
- import type { LoginPayload } from "$lib/services/abstractions/IAccountService";
- import { FormError } from "$lib/models/internal/FormError";
+ import {onMount} from "svelte";
+ import {signInPageMessageQueryKey, signInPageTestKeys, type SignInPageMessage} from ".";
+ import {AccountService} from "$services/account-service";
+ import type {LoginPayload} from "$services/abstractions/IAccountService";
+ import {FormError} from "$models/internal/FormError";
let loading = false;
let showErrorAlert = false;
@@ -71,24 +71,24 @@
<div class="sm:max-w-md sm:mx-auto sm:w-full">
{#if messageType === "after-password-reset"}
<Alert
- title={$LL.signInPage.yourNewPasswordIsApplied()}
- _pwKey={signInPageTestKeys.afterPasswordResetAlert}
- message={$LL.signInPage.signInBelow()}
- closeable
+ title={$LL.signInPage.yourNewPasswordIsApplied()}
+ _pwKey={signInPageTestKeys.afterPasswordResetAlert}
+ message={$LL.signInPage.signInBelow()}
+ closeable
/>
{:else if messageType === "user-disabled"}
<Alert
- title={$LL.signInPage.yourAccountIsDisabled()}
- _pwKey={signInPageTestKeys.userDisabledAlert}
- message={$LL.signInPage.contactYourAdminIfDisabled()}
- closeable
+ title={$LL.signInPage.yourAccountIsDisabled()}
+ _pwKey={signInPageTestKeys.userDisabledAlert}
+ message={$LL.signInPage.contactYourAdminIfDisabled()}
+ closeable
/>
{:else if messageType === "user-inactivity"}
<Alert
- title={$LL.signInPage.youHaveReachedInactivityLimit()}
- _pwKey={signInPageTestKeys.userInactivityAlert}
- message={$LL.signInPage.feelFreeToSignInAgain()}
- closeable
+ title={$LL.signInPage.youHaveReachedInactivityLimit()}
+ _pwKey={signInPageTestKeys.userInactivityAlert}
+ message={$LL.signInPage.feelFreeToSignInAgain()}
+ closeable
/>
{/if}
</div>
@@ -107,37 +107,39 @@
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
{#if showErrorAlert}
- <Alert title={formError.title} message={formError.subtitle} type="error" _pwKey={signInPageTestKeys.formErrorAlert} />
+ <Alert title={formError.title} message={formError.subtitle} type="error"
+ _pwKey={signInPageTestKeys.formErrorAlert}/>
{/if}
- <form class="space-y-6 mt-2" use:pwKey={signInPageTestKeys.signInForm} on:submit|preventDefault={submit_form_async}>
+ <form class="space-y-6 mt-2" use:pwKey={signInPageTestKeys.signInForm}
+ on:submit|preventDefault={submit_form_async}>
<Input
- id="username"
- _pwKey={signInPageTestKeys.usernameInput}
- name="username"
- type="email"
- label={$LL.emailAddress()}
- required
- bind:value={formData.username.value}
+ id="username"
+ _pwKey={signInPageTestKeys.usernameInput}
+ name="username"
+ type="email"
+ label={$LL.emailAddress()}
+ required
+ bind:value={formData.username.value}
/>
<Input
- id="password"
- name="password"
- type="password"
- label={$LL.password()}
- _pwKey={signInPageTestKeys.passwordInput}
- autocomplete="current-password"
- required
- bind:value={formData.password.value}
+ id="password"
+ name="password"
+ type="password"
+ label={$LL.password()}
+ _pwKey={signInPageTestKeys.passwordInput}
+ autocomplete="current-password"
+ required
+ bind:value={formData.password.value}
/>
<div class="flex items-center justify-between">
<Checkbox
- id="remember-me"
- _pwKey={signInPageTestKeys.rememberMeCheckbox}
- name="remember-me"
- bind:checked={formData.persist.value}
- label={$LL.signInPage.notMyComputer()}
+ id="remember-me"
+ _pwKey={signInPageTestKeys.rememberMeCheckbox}
+ name="remember-me"
+ bind:checked={formData.persist.value}
+ label={$LL.signInPage.notMyComputer()}
/>
<div class="text-sm">
<a href="/reset-password" class="link" use:pwKey={signInPageTestKeys.resetPasswordAnchor}>
@@ -146,7 +148,7 @@
</div>
</div>
- <Button text={$LL.submit()} fullWidth type="submit" {loading} />
+ <Button text={$LL.submit()} fullWidth type="submit" {loading}/>
</form>
</div>
</div>
diff --git a/code/app/src/routes/(main)/(public)/sign-in/tests/index.spec.ts b/code/app/src/routes/(main)/(public)/sign-in/tests/index.spec.ts
index ea8c494..9a9f7a5 100644
--- a/code/app/src/routes/(main)/(public)/sign-in/tests/index.spec.ts
+++ b/code/app/src/routes/(main)/(public)/sign-in/tests/index.spec.ts
@@ -1,12 +1,12 @@
-import { test, expect } from "@playwright/test";
-import { signInPageTestKeys } from "../index";
-import { get_test_context } from "$lib/configuration";
-import { get_pw_key_selector } from "$lib/helpers";
+import {test, expect} from "@playwright/test";
+import {signInPageTestKeys} from "../index";
+import {get_test_context} from "$configuration";
+import {get_pw_key_selector} from "$help";
const context = get_test_context();
-test("form loads", async ({ page }) => {
+test("form loads", async ({page}) => {
page.goto("/sign-in");
const form = page.locator(get_pw_key_selector(signInPageTestKeys.signInForm));
expect(form.isVisible()).toBeTruthy();
-})
+});
diff --git a/code/app/src/routes/(main)/(public)/sign-up/+page.svelte b/code/app/src/routes/(main)/(public)/sign-up/+page.svelte
index 9fa8dfa..58940ea 100644
--- a/code/app/src/routes/(main)/(public)/sign-up/+page.svelte
+++ b/code/app/src/routes/(main)/(public)/sign-up/+page.svelte
@@ -1,10 +1,10 @@
<script lang="ts">
- import { goto } from "$app/navigation";
- import type { CreateAccountPayload } from "$lib/api/account";
- import { Button, Input, Alert } from "$lib/components";
- import LL from "$lib/i18n/i18n-svelte";
- import { FormError } from "$lib/models/internal/FormError";
- import { AccountService } from "$lib/services/account-service";
+ import {goto} from "$app/navigation";
+ import type {CreateAccountPayload} from "$api/account";
+ import {Button, Input, Alert} from "$components";
+ import LL from "$i18n/i18n-svelte";
+ import {FormError} from "$models/internal/FormError";
+ import {AccountService} from "$services/account-service";
const formData = {
username: {
@@ -76,30 +76,30 @@
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
{#if showErrorAlert}
- <Alert title={formError.title} message={formError.subtitle} type="error" class="mb-2" />
+ <Alert title={formError.title} message={formError.subtitle} type="error" class="mb-2"/>
{/if}
<form class="space-y-6" on:submit|preventDefault={submit_form_async}>
<Input
- label={$LL.emailAddress()}
- id="email"
- name="email"
- autocomplete="email"
- required
- type="email"
- bind:value={formData.username.value}
- errors={formData.username.errors}
+ label={$LL.emailAddress()}
+ id="email"
+ name="email"
+ autocomplete="email"
+ required
+ type="email"
+ bind:value={formData.username.value}
+ errors={formData.username.errors}
/>
<Input
- label={$LL.password()}
- id="password"
- name="password"
- required
- type="password"
- bind:value={formData.password.value}
- errors={formData.password.errors}
+ label={$LL.password()}
+ id="password"
+ name="password"
+ required
+ type="password"
+ bind:value={formData.password.value}
+ errors={formData.password.errors}
/>
- <Button type="submit" text={$LL.submit()} {loading} fullWidth />
+ <Button type="submit" text={$LL.submit()} {loading} fullWidth/>
</form>
</div>
</div>
diff --git a/code/app/src/routes/(main)/+layout.server.ts b/code/app/src/routes/(main)/+layout.server.ts
index cd41734..086d1c0 100644
--- a/code/app/src/routes/(main)/+layout.server.ts
+++ b/code/app/src/routes/(main)/+layout.server.ts
@@ -1,27 +1,27 @@
-import { api_base, CookieNames } from "$lib/configuration";
-import { log_debug, log_error } from "$lib/logger";
-import { error, redirect } from "@sveltejs/kit";
-import { Temporal } from "temporal-polyfill";
-import type { LayoutServerLoad } from "./$types";
+import {api_base, CookieNames} from "$configuration";
+import {log_debug, log_error} from "$help/logger";
+import {error, redirect} from "@sveltejs/kit";
+import {Temporal} from "temporal-polyfill";
+import type {LayoutServerLoad} from "./$types";
-export const load: LayoutServerLoad = async ({ route, cookies, locals }) => {
+export const load: LayoutServerLoad = async ({route, cookies, locals}) => {
const isBaseRoute = route.id === "/(main)";
const isPublicRoute = (route.id?.startsWith("/(main)/(public)") || isBaseRoute) ?? true;
const sessionIsValid = (await cached_result<Response>("sessionCheck", 120, () => fetch(api_base("_/valid-session"), {
headers: {
- Cookie: CookieNames.session + "=" + cookies.get(CookieNames.session)
- }
+ Cookie: CookieNames.session + "=" + cookies.get(CookieNames.session),
+ },
}).catch((e) => {
log_error(e);
throw error(503, {
- message: "We are experiencing a service disruption! Have patience while we resolve the issue."
- })
+ message: "We are experiencing a service disruption! Have patience while we resolve the issue.",
+ });
}))).ok;
log_debug("Base Layout loaded", {
sessionIsValid,
isPublicRoute,
- routeId: route.id
+ routeId: route.id,
});
if (sessionIsValid && isPublicRoute) {
@@ -31,17 +31,18 @@ export const load: LayoutServerLoad = async ({ route, cookies, locals }) => {
}
return {
- locale: locals.locale
- }
-}
+ locale: locals.locale,
+ };
+};
let resultCache = {};
+
async function cached_result<T>(key: string, staleAfterSeconds: number, code: any) {
if (!resultCache[key]) {
resultCache[key] = {
l: 0,
- c: undefined as T
- }
+ c: undefined as T,
+ };
}
const staleEpoch = ((resultCache[key]?.l ?? 0) + staleAfterSeconds);
const isStale = staleEpoch < Temporal.Now.instant().epochSeconds;
@@ -54,7 +55,7 @@ async function cached_result<T>(key: string, staleAfterSeconds: number, code: an
cacheKey: key,
isStale,
cache: resultCache[key],
- staleEpoch
+ staleEpoch,
});
return resultCache[key].c as T;
diff --git a/code/app/src/routes/(main)/+layout.svelte b/code/app/src/routes/(main)/+layout.svelte
index 7d4ce05..2b96527 100644
--- a/code/app/src/routes/(main)/+layout.svelte
+++ b/code/app/src/routes/(main)/+layout.svelte
@@ -1,21 +1,21 @@
<script lang="ts">
import "../../app.pcss";
- import { setLocale } from "$lib/i18n/i18n-svelte";
- import { ExclamationTriangleIcon } from "$lib/components/icons";
- import type { LayoutData } from "./$types";
+ import {setLocale} from "$i18n/i18n-svelte";
+ import {ExclamationTriangleIcon} from "$components/icons";
+ import type {LayoutData} from "./$types";
let online = true;
export let data: LayoutData;
setLocale(data.locale);
</script>
-<svelte:window bind:online />
+<svelte:window bind:online/>
{#if !online}
<div class="bg-yellow-50 relative z-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
- <ExclamationTriangleIcon class="bg-yellow-50 text-yellow-500" />
+ <ExclamationTriangleIcon class="bg-yellow-50 text-yellow-500"/>
</div>
<div class="ml-3">
<p class="text-sm text-yellow-700">You seem to be offline, please check your internet connection.</p>
@@ -24,4 +24,4 @@
</div>
{/if}
-<slot />
+<slot/>
diff --git a/code/app/src/routes/(main)/+layout.ts b/code/app/src/routes/(main)/+layout.ts
index cf08d66..0509aaf 100644
--- a/code/app/src/routes/(main)/+layout.ts
+++ b/code/app/src/routes/(main)/+layout.ts
@@ -1,10 +1,10 @@
-import type { LayoutLoad } from './$types'
-import type { Locales } from '$lib/i18n/i18n-types'
-import { loadLocaleAsync } from '$lib/i18n/i18n-util.async'
-import { setLocale } from '$lib/i18n/i18n-svelte'
+import type {LayoutLoad} from "./$types";
+import type {Locales} from "$i18n/i18n-types";
+import {loadLocaleAsync} from "$i18n/i18n-util.async";
+import {setLocale} from "$i18n/i18n-svelte";
-export const load: LayoutLoad<{ locale: Locales }> = async ({ data: { locale } }) => {
- await loadLocaleAsync(locale)
- setLocale(locale)
- return { locale }
-} \ No newline at end of file
+export const load: LayoutLoad<{ locale: Locales }> = async ({data: {locale}}) => {
+ await loadLocaleAsync(locale);
+ setLocale(locale);
+ return {locale};
+}; \ No newline at end of file
diff --git a/code/app/src/routes/book/alerts/+page.svelte b/code/app/src/routes/book/alerts/+page.svelte
index d008d85..ed4c92b 100644
--- a/code/app/src/routes/book/alerts/+page.svelte
+++ b/code/app/src/routes/book/alerts/+page.svelte
@@ -1,31 +1,31 @@
<script>
- import Alert from "$lib/components/alert.svelte";
+ import Alert from "$components/alert.svelte";
</script>
<section>
<h2>Info</h2>
- <Alert type="info" message="This is message" title="This is title" />
+ <Alert type="info" message="This is message" title="This is title"/>
</section>
<section>
<h2>Warning</h2>
- <Alert type="warning" message="This is message" title="This is title" />
+ <Alert type="warning" message="This is message" title="This is title"/>
</section>
<section>
<h2>Error</h2>
- <Alert type="error" message="This is message" title="This is title" />
+ <Alert type="error" message="This is message" title="This is title"/>
</section>
<section>
<h2>Success</h2>
- <Alert type="success" message="This is message" title="This is title" />
+ <Alert type="success" message="This is message" title="This is title"/>
</section>
<section>
<h2>Actions</h2>
<Alert
- type="info"
- message="This is message"
- title="This is title"
- closeable
- actions={[
+ type="info"
+ message="This is message"
+ title="This is title"
+ closeable
+ actions={[
{
id: "confirm",
text: "Yes!",
@@ -41,30 +41,30 @@
<section>
<h2>Right link</h2>
<Alert
- on:rightLinkCliked={() => alert("Right link clicked")}
- rightLinkText="Link or action"
- title="Go here"
- message="Hehe"
- type="error"
+ on:rightLinkCliked={() => alert("Right link clicked")}
+ rightLinkText="Link or action"
+ title="Go here"
+ message="Hehe"
+ type="error"
/>
</section>
<section>
<h2>List</h2>
<Alert
- title="This is title"
- listItems={["Message 1", "Message 2"]}
- type="error"
- message="This is bad dude"
- closeable
- closeableCooldown="60"
- id="alert-1"
- on:actrepeat={() => {
+ title="This is title"
+ listItems={["Message 1", "Message 2"]}
+ type="error"
+ message="This is bad dude"
+ closeable
+ closeableCooldown="60"
+ id="alert-1"
+ on:actrepeat={() => {
alert("Repeat requested");
}}
- actions={[{ id: "repeat", text: "Try again" }]}
+ actions={[{ id: "repeat", text: "Try again" }]}
/>
</section>
<section>
<h2>Closeable</h2>
- <Alert message="This is message" closeable type="info" />
+ <Alert message="This is message" closeable type="info"/>
</section>
diff --git a/code/app/src/routes/book/badges/+page.svelte b/code/app/src/routes/book/badges/+page.svelte
index cd5120a..50ae61e 100644
--- a/code/app/src/routes/book/badges/+page.svelte
+++ b/code/app/src/routes/book/badges/+page.svelte
@@ -1,18 +1,19 @@
<script lang="ts">
- import Badge from "$lib/components/badge.svelte";
+ import Badge from "$components/badge.svelte";
</script>
<section>
<h2>Variants</h2>
- <Badge text="default" />
- <Badge type="blue" text="blue" />
- <Badge type="green" text="green" />
- <Badge type="red" text="red" />
- <Badge type="tame" text="tame" />
- <Badge type="yellow" text="yellow" />
- <Badge size="large" text="large" />
- <Badge text="with dot" withDot type="blue" />
- <Badge text="removable" removable id="badge-1" on:remove={(e) => alert("removed " + e.detail.id)} />
- <Badge text="with dot" size="large" withDot type="blue" />
- <Badge text="removable" removable size="large" id="badge-2" uppercase on:remove={(e) => alert("removed " + e.detail.id)} />
+ <Badge text="default"/>
+ <Badge type="blue" text="blue"/>
+ <Badge type="green" text="green"/>
+ <Badge type="red" text="red"/>
+ <Badge type="tame" text="tame"/>
+ <Badge type="yellow" text="yellow"/>
+ <Badge size="large" text="large"/>
+ <Badge text="with dot" withDot type="blue"/>
+ <Badge text="removable" removable id="badge-1" on:remove={(e) => alert("removed " + e.detail.id)}/>
+ <Badge text="with dot" size="large" withDot type="blue"/>
+ <Badge text="removable" removable size="large" id="badge-2" uppercase
+ on:remove={(e) => alert("removed " + e.detail.id)}/>
</section>
diff --git a/code/app/src/routes/book/buttons/+page.svelte b/code/app/src/routes/book/buttons/+page.svelte
index 19ba163..6668a64 100644
--- a/code/app/src/routes/book/buttons/+page.svelte
+++ b/code/app/src/routes/book/buttons/+page.svelte
@@ -1,23 +1,23 @@
<script>
- import Button from "$lib/components/button.svelte";
+ import Button from "$components/button.svelte";
</script>
<section>
<h2>Primary</h2>
- <Button kind="primary" text="Small" size="sm" />
- <Button kind="primary" text="Medium/Default" />
- <Button kind="primary" text="Large" size="lg" />
- <Button kind="primary" text="Extra large" size="xl" />
+ <Button kind="primary" text="Small" size="sm"/>
+ <Button kind="primary" text="Medium/Default"/>
+ <Button kind="primary" text="Large" size="lg"/>
+ <Button kind="primary" text="Extra large" size="xl"/>
</section>
<section>
<h2>Secondary</h2>
- <Button kind="secondary" text="Click me!" />
+ <Button kind="secondary" text="Click me!"/>
</section>
<section>
<h2>White</h2>
- <Button kind="white" text="Click me!" />
+ <Button kind="white" text="Click me!"/>
</section>
<section>
<h2>Loading</h2>
- <Button kind="primary" loading={true} text="Wait" />
+ <Button kind="primary" loading={true} text="Wait"/>
</section>
diff --git a/code/app/src/routes/book/inputs/+page.svelte b/code/app/src/routes/book/inputs/+page.svelte
index 7ca0d31..d5566ed 100644
--- a/code/app/src/routes/book/inputs/+page.svelte
+++ b/code/app/src/routes/book/inputs/+page.svelte
@@ -1,7 +1,6 @@
<script lang="ts">
- import { TextArea, Input, Combobox } from "$lib/components";
- import { DatabaseIcon } from "$lib/components/icons";
- import LL from "$lib/i18n/i18n-svelte";
+ import {TextArea, Input, Combobox} from "$components";
+ import {DatabaseIcon} from "$components/icons";
let value;
let i = 0;
@@ -16,7 +15,7 @@
i++;
}
- async function add({ name }) {
+ async function add({name}) {
const copy = options;
copy.push({
id: crypto.randomUUID(),
@@ -28,48 +27,49 @@
<section>
<h2>Combobox</h2>
- <Combobox {options} label="Wiii" multiple createable on_create_async={add} />
+ <Combobox {options} label="Wiii" multiple createable on_create_async={add}/>
</section>
<section>
<h2>Default</h2>
- <Input label="Input me" placeholder="Hello" bind:value />
+ <Input label="Input me" placeholder="Hello" bind:value/>
</section>
<section>
<h2>With icon</h2>
- <Input label="Input me" placeholder="Hello" icon={DatabaseIcon} bind:value />
+ <Input label="Input me" placeholder="Hello" icon={DatabaseIcon} bind:value/>
</section>
<section>
<h2>With corner hint</h2>
- <Input label="Input me ->" placeholder="Hello" cornerHint="Hint hint" bind:value />
+ <Input label="Input me ->" placeholder="Hello" cornerHint="Hint hint" bind:value/>
</section>
<section>
<h2>Disabled</h2>
- <Input label="No" placeholder="Sorry" disabled bind:value />
+ <Input label="No" placeholder="Sorry" disabled bind:value/>
</section>
<section>
<h2>Errored</h2>
- <Input label="No" placeholder="Sorry" errorText="That's not right" bind:value icon={DatabaseIcon} />
+ <Input label="No" placeholder="Sorry" errorText="That's not right" bind:value icon={DatabaseIcon}/>
</section>
<section>
<h2>Many errors</h2>
- <Input label="No" placeholder="Sorry" errors={["That's not right", "Call help!", "Get it together"]} bind:value icon={DatabaseIcon} />
+ <Input label="No" placeholder="Sorry" errors={["That's not right", "Call help!", "Get it together"]} bind:value
+ icon={DatabaseIcon}/>
</section>
<section>
<h2>Help</h2>
- <Input label="Go ahead" placeholder="Write here" helpText="Write above" bind:value />
+ <Input label="Go ahead" placeholder="Write here" helpText="Write above" bind:value/>
</section>
<section>
<h2>Addon</h2>
- <Input label="Go ahead" placeholder="Write here" bind:value helpText="Write above" addon="To the right" />
+ <Input label="Go ahead" placeholder="Write here" bind:value helpText="Write above" addon="To the right"/>
</section>
<section>
<h2>Textarea</h2>
- <TextArea bind:value errorText="oh no" label="Hi" />
+ <TextArea bind:value errorText="oh no" label="Hi"/>
</section>
diff --git a/code/app/src/routes/book/toggles/+page.svelte b/code/app/src/routes/book/toggles/+page.svelte
index 730e6f2..71c9298 100644
--- a/code/app/src/routes/book/toggles/+page.svelte
+++ b/code/app/src/routes/book/toggles/+page.svelte
@@ -1,27 +1,27 @@
<script>
- import Switch from "$lib/components/switch.svelte";
+ import Switch from "$components/switch.svelte";
</script>
<section>
<h2>Default</h2>
- <Switch />
+ <Switch/>
</section>
<section>
<h2>Short</h2>
- <Switch type="short" />
+ <Switch type="short"/>
</section>
<section>
<h2>Icon</h2>
- <Switch type="icon" />
+ <Switch type="icon"/>
</section>
<section>
<h2>Label / Description</h2>
<div class="max-w-md">
- <Switch label="Label" description="Some text" />
+ <Switch label="Label" description="Some text"/>
</div>
</section>
<section>
<h2>Label / Description (right aligned)</h2>
- <Switch label="Label" description="Some text" rightAlignedLabelDescription />
+ <Switch label="Label" description="Some text" rightAlignedLabelDescription/>
</section>