We use cookies to ensure you get the best experience on our website. By continuing, you agree
to our use of cookies. For details, please see our
+ import { onMount } from 'svelte';
+ import { cubicInOut } from 'svelte/easing';
+ import { slide } from 'svelte/transition';
+
+ export let indicator: boolean = false;
+ export let posRight: boolean = false;
+
+ let isOpen = false;
+ let dropdown: HTMLDivElement;
+
+ const DropdownIcon = {
+ closed: '▼',
+ open: '▲'
+ };
+
+ onMount(() => {
+ const handleClickAnywhere = ({ target }: MouseEvent) => {
+ if (!isOpen || !target) return;
+ const clickTarget = target as HTMLElement;
+ if (!dropdown.contains(clickTarget) || clickTarget.closest('a')) {
+ isOpen = false;
+ }
+ };
+
+ document.addEventListener('click', handleClickAnywhere);
+
+ return () => {
+ document.removeEventListener('click', handleClickAnywhere);
+ };
+ });
+
+
+
+
+
+
+ {#if isOpen}
+
+ {/if}
+
diff --git a/src/lib/components/MagicLink.svelte b/src/lib/components/MagicLink.svelte
index 679e86f..c1df69e 100644
--- a/src/lib/components/MagicLink.svelte
+++ b/src/lib/components/MagicLink.svelte
@@ -1,20 +1,18 @@
-
-Products
-
- {#if isMobile}
- Parent
- {:else}
-
- ▼Parent
-
- {/if}
-
-
-Example Product
diff --git a/src/lib/components/SignOut.svelte b/src/lib/components/SignOut.svelte
index 5d355ae..34b65d2 100644
--- a/src/lib/components/SignOut.svelte
+++ b/src/lib/components/SignOut.svelte
@@ -45,4 +45,4 @@
}
-
+
diff --git a/src/lib/components/navigation/Nav.svelte b/src/lib/components/navigation/Nav.svelte
new file mode 100644
index 0000000..97a91d4
--- /dev/null
+++ b/src/lib/components/navigation/Nav.svelte
@@ -0,0 +1,124 @@
+
+
+
diff --git a/src/lib/components/navigation/NavLink.svelte b/src/lib/components/navigation/NavLink.svelte
new file mode 100644
index 0000000..dbcb775
--- /dev/null
+++ b/src/lib/components/navigation/NavLink.svelte
@@ -0,0 +1,19 @@
+
+
+{#if !linkItem.isSignout}
+ {linkItem.text}
+{:else if supabase && linkItem.isSignout}
+
+{/if}
diff --git a/src/lib/components/navigation/NavLinkParent.svelte b/src/lib/components/navigation/NavLinkParent.svelte
new file mode 100644
index 0000000..b7db981
--- /dev/null
+++ b/src/lib/components/navigation/NavLinkParent.svelte
@@ -0,0 +1,42 @@
+
+
+{#if !isMobile}
+
+ {linkItem.text}
+ {#each linkItem.children ?? [] as child (child.text.replace(' ', '-').toLowerCase())}
+
+ {/each}
+
+{:else}
+
+ {#if isOpen}
+
+ {/if}
+{/if}
diff --git a/src/lib/components/navigation/NavLinks.svelte b/src/lib/components/navigation/NavLinks.svelte
new file mode 100644
index 0000000..25b75ed
--- /dev/null
+++ b/src/lib/components/navigation/NavLinks.svelte
@@ -0,0 +1,76 @@
+
+
+
+ {#each links as link (link.text.replace(' ', '-').toLowerCase())}
+ -
+ {#if link.isParent}
+
+ {:else}
+
+ {/if}
+
+ {/each}
+
diff --git a/src/lib/components/shared/Toast.svelte b/src/lib/components/shared/Toast.svelte
new file mode 100644
index 0000000..8be3f54
--- /dev/null
+++ b/src/lib/components/shared/Toast.svelte
@@ -0,0 +1,65 @@
+
+
+{#if !localToast.hideToast}
+
+ {#if localToast.toastType == 'success'}
+
+ {:else}
+
+ {/if}
+
+
{localToast.toastMessage}
+
+{/if}
diff --git a/src/lib/stores/generalStore.ts b/src/lib/stores/generalStore.ts
deleted file mode 100644
index 622bfc8..0000000
--- a/src/lib/stores/generalStore.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { writable } from 'svelte/store';
-
-export const general = writable({ hideToast: true, toastMessage: '', toastType: 'success' });
diff --git a/src/lib/stores/toastStore.ts b/src/lib/stores/toastStore.ts
new file mode 100644
index 0000000..82785cf
--- /dev/null
+++ b/src/lib/stores/toastStore.ts
@@ -0,0 +1,23 @@
+import type { Toast } from '$lib/types/Shared/Toast';
+import { writable } from 'svelte/store';
+
+const MIN_DELAY = 3000;
+
+export const toast = writable
({ hideToast: true, toastMessage: '', toastType: 'success' });
+export function scheduleToast(message: string, toastType: 'success' | 'error', delay: number = MIN_DELAY) {
+
+ toast.update((value) => {
+ return {
+ ...value,
+ hideToast: false,
+ toastMessage: message,
+ toastType: toastType
+ };
+ });
+
+ setTimeout(() => {
+ toast.update((value) => {
+ return { ...value, hideToast: true, toastMessage: '' };
+ });
+ }, Math.max(delay, MIN_DELAY));
+}
\ No newline at end of file
diff --git a/src/lib/types/Nav/NavLinkItem.ts b/src/lib/types/Nav/NavLinkItem.ts
new file mode 100644
index 0000000..a3cf412
--- /dev/null
+++ b/src/lib/types/Nav/NavLinkItem.ts
@@ -0,0 +1,8 @@
+export interface NavLinkItem {
+ text: string;
+ href?: string;
+ isParent?: boolean;
+ children?: NavLinkItem[];
+ isSignout?: boolean;
+ isUserAccount?: boolean;
+}
diff --git a/src/lib/types/Shared/Toast.ts b/src/lib/types/Shared/Toast.ts
new file mode 100644
index 0000000..d0fe6b5
--- /dev/null
+++ b/src/lib/types/Shared/Toast.ts
@@ -0,0 +1,5 @@
+export type Toast = {
+ hideToast: boolean,
+ toastMessage: string,
+ toastType: 'success' | 'error'
+}
\ No newline at end of file
diff --git a/src/lib/utils/supabase/auth.ts b/src/lib/utils/supabase/auth.ts
new file mode 100644
index 0000000..2388038
--- /dev/null
+++ b/src/lib/utils/supabase/auth.ts
@@ -0,0 +1,6 @@
+import type { SupabaseClient } from '@supabase/supabase-js';
+
+export async function signOut(supabase: SupabaseClient, callback: () => void): Promise {
+ // TODO - #61 use the error from the response
+ const { error } = await supabase.auth.signOut().then(callback);
+}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 7dfb5cd..90aa24c 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,34 +1,16 @@
@@ -69,109 +45,7 @@
@@ -241,52 +115,7 @@
-
- {#if localGeneral.toastType == 'success'}
-
- {:else}
-
- {/if}
-
-
{localGeneral.toastMessage == '' ? 'Added to basket' : localGeneral.toastMessage}
-
+