aboutsummaryrefslogtreecommitdiffstats
path: root/code/app/src/routes/(main)/(app)/+layout.svelte
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/(main)/(app)/+layout.svelte
parent914c75e0ceeb3e11ddd55e94bb461c26b0db5b7a (diff)
downloadgreatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.tar.xz
greatoffice-4dbef3fcd7a14437d55c555cf10d50de8e50d7d1.zip
feat: Move everything out of $lib
Diffstat (limited to 'code/app/src/routes/(main)/(app)/+layout.svelte')
-rw-r--r--code/app/src/routes/(main)/(app)/+layout.svelte534
1 files changed, 277 insertions, 257 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>