mirror of
https://github.com/jcreek/SvelteKitSaasBoilerplate.git
synced 2026-07-15 20:13:50 +00:00
refactor(#35): move nav into component
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Session, SupabaseClient } from "@supabase/supabase-js";
|
||||||
|
import MagicLink from "./MagicLink.svelte";
|
||||||
|
import NavLinks from "./NavLinks.svelte";
|
||||||
|
import SignOut from "./SignOut.svelte";
|
||||||
|
import { basket, type Basket } from '$lib/stores/basket.js';
|
||||||
|
import { onDestroy } from "svelte";
|
||||||
|
|
||||||
|
export let session: Session;
|
||||||
|
export let supabase: SupabaseClient<any, "public", any>;
|
||||||
|
|
||||||
|
let isMobileMenuOpen = false;
|
||||||
|
|
||||||
|
function toggleMobileMenu() {
|
||||||
|
isMobileMenuOpen = !isMobileMenuOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
let localBasket: Basket;
|
||||||
|
const unsubscribeToBasket = basket.subscribe((value) => {
|
||||||
|
localBasket = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
unsubscribeToBasket();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav class="bg-primary text-primary-content p-4">
|
||||||
|
<div class="container mx-auto flex justify-between items-center">
|
||||||
|
<a href="/" class="text-white font-bold text-xl">SvelteKit SaaS Boilerplate</a>
|
||||||
|
|
||||||
|
<!-- Hamburger Menu Button (Mobile) -->
|
||||||
|
<button on:click={toggleMobileMenu} class="block md:hidden text-white focus:outline-none">
|
||||||
|
<svg
|
||||||
|
class="w-6 h-6"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M4 6h16M4 12h8m-8 6h16"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Navbar Links (hidden on mobile, visible on larger screens) -->
|
||||||
|
<div class="hidden md:flex space-x-4">
|
||||||
|
<ul class="flex flex-col md:flex-row md:space-x-4">
|
||||||
|
<NavLinks isMobile={false} />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Side: Basket & User Account -->
|
||||||
|
<div class="flex items-center space-x-4">
|
||||||
|
<!-- Basket/Checkout Icon -->
|
||||||
|
<a href="/checkout" class="btn btn-ghost btn-circle">
|
||||||
|
<div class="indicator">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="badge badge-sm indicator-item">{localBasket.items.length}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- User Account Dropdown -->
|
||||||
|
<details class="dropdown dropdown-end">
|
||||||
|
<summary tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
|
||||||
|
<div class="w-10 rounded-full">
|
||||||
|
{#if session?.user}
|
||||||
|
<div class="user-circle text-primary-content border-primary-content">
|
||||||
|
{session?.user.email[0].toUpperCase()}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M18.685 19.097A9.723 9.723 0 0 0 21.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 0 0 3.065 7.097A9.716 9.716 0 0 0 12 21.75a9.716 9.716 0 0 0 6.685-2.653Zm-12.54-1.285A7.486 7.486 0 0 1 12 15a7.486 7.486 0 0 1 5.855 2.812A8.224 8.224 0 0 1 12 20.25a8.224 8.224 0 0 1-5.855-2.438ZM15.75 9a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
{#if session?.user}
|
||||||
|
<ul
|
||||||
|
tabindex="-1"
|
||||||
|
class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 text-base-content rounded-box min-w-[13rem] w-auto"
|
||||||
|
>
|
||||||
|
<li><a href="/account">Account</a></li>
|
||||||
|
<li><a href="/settings">Settings</a></li>
|
||||||
|
<li><SignOut {supabase} /></li>
|
||||||
|
</ul>
|
||||||
|
{:else}
|
||||||
|
<div
|
||||||
|
class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 text-base-content rounded-box min-w-[13rem] w-auto"
|
||||||
|
>
|
||||||
|
<MagicLink {supabase} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile Menu -->
|
||||||
|
<div
|
||||||
|
class="bg-base-100 text-base-content shadow rounded-box p-4 transition duration-300 ease-in-out md:hidden"
|
||||||
|
class:block={isMobileMenuOpen}
|
||||||
|
class:hidden={!isMobileMenuOpen}
|
||||||
|
>
|
||||||
|
<ul class="flex flex-col space-y-4">
|
||||||
|
<NavLinks isMobile={true} />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
+5
-116
@@ -2,22 +2,16 @@
|
|||||||
import '../app.postcss';
|
import '../app.postcss';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { isBrowser } from '@supabase/ssr';
|
import { isBrowser } from '@supabase/ssr';
|
||||||
import { basket, type Basket, type Item } from '$lib/stores/basket.js';
|
|
||||||
import { general } from '$lib/stores/generalStore.js';
|
import { general } from '$lib/stores/generalStore.js';
|
||||||
import { invalidate } from '$app/navigation';
|
import { invalidate } from '$app/navigation';
|
||||||
import SignOut from '$lib/components/SignOut.svelte';
|
|
||||||
import CookieConsent from '$lib/components/CookieConsent.svelte';
|
import CookieConsent from '$lib/components/CookieConsent.svelte';
|
||||||
import NavLinks from '$lib/components/NavLinks.svelte';
|
import Nav from '$lib/components/Nav.svelte';
|
||||||
import MagicLink from '$lib/components/MagicLink.svelte';
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
let { supabase, session } = data;
|
let { supabase, session } = data;
|
||||||
$: ({ supabase, session } = data);
|
$: ({ supabase, session } = data);
|
||||||
|
|
||||||
let localBasket: Basket;
|
|
||||||
const unsubscribeToBasket = basket.subscribe((value) => {
|
|
||||||
localBasket = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
let localGeneral: any;
|
let localGeneral: any;
|
||||||
const unsubscribeToGeneralStore = general.subscribe((value) => {
|
const unsubscribeToGeneralStore = general.subscribe((value) => {
|
||||||
@@ -25,7 +19,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
unsubscribeToBasket();
|
|
||||||
unsubscribeToGeneralStore();
|
unsubscribeToGeneralStore();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -48,11 +41,9 @@
|
|||||||
return () => data.subscription.unsubscribe();
|
return () => data.subscription.unsubscribe();
|
||||||
});
|
});
|
||||||
|
|
||||||
let isMobileMenuOpen = false;
|
|
||||||
|
|
||||||
function toggleMobileMenu() {
|
|
||||||
isMobileMenuOpen = !isMobileMenuOpen;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -69,109 +60,7 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<nav class="bg-primary text-primary-content p-4">
|
<Nav {session} {supabase} />
|
||||||
<div class="container mx-auto flex justify-between items-center">
|
|
||||||
<a href="/" class="text-white font-bold text-xl">SvelteKit SaaS Boilerplate</a>
|
|
||||||
|
|
||||||
<!-- Hamburger Menu Button (Mobile) -->
|
|
||||||
<button on:click={toggleMobileMenu} class="block md:hidden text-white focus:outline-none">
|
|
||||||
<svg
|
|
||||||
class="w-6 h-6"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M4 6h16M4 12h8m-8 6h16"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Navbar Links (hidden on mobile, visible on larger screens) -->
|
|
||||||
<div class="hidden md:flex space-x-4">
|
|
||||||
<ul class="flex flex-col md:flex-row md:space-x-4">
|
|
||||||
<NavLinks isMobile={false} />
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Right Side: Basket & User Account -->
|
|
||||||
<div class="flex items-center space-x-4">
|
|
||||||
<!-- Basket/Checkout Icon -->
|
|
||||||
<a href="/checkout" class="btn btn-ghost btn-circle">
|
|
||||||
<div class="indicator">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span class="badge badge-sm indicator-item">{localBasket.items.length}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- User Account Dropdown -->
|
|
||||||
<details class="dropdown dropdown-end">
|
|
||||||
<summary tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
|
|
||||||
<div class="w-10 rounded-full">
|
|
||||||
{#if session?.user}
|
|
||||||
<div class="user-circle text-primary-content border-primary-content">
|
|
||||||
{session?.user.email[0].toUpperCase()}
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
d="M18.685 19.097A9.723 9.723 0 0 0 21.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 0 0 3.065 7.097A9.716 9.716 0 0 0 12 21.75a9.716 9.716 0 0 0 6.685-2.653Zm-12.54-1.285A7.486 7.486 0 0 1 12 15a7.486 7.486 0 0 1 5.855 2.812A8.224 8.224 0 0 1 12 20.25a8.224 8.224 0 0 1-5.855-2.438ZM15.75 9a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
{#if session?.user}
|
|
||||||
<ul
|
|
||||||
tabindex="-1"
|
|
||||||
class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 text-base-content rounded-box min-w-[13rem] w-auto"
|
|
||||||
>
|
|
||||||
<li><a href="/account">Account</a></li>
|
|
||||||
<li><a href="/settings">Settings</a></li>
|
|
||||||
<li><SignOut {supabase} /></li>
|
|
||||||
</ul>
|
|
||||||
{:else}
|
|
||||||
<div
|
|
||||||
class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 text-base-content rounded-box min-w-[13rem] w-auto"
|
|
||||||
>
|
|
||||||
<MagicLink {supabase} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</details>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile Menu -->
|
|
||||||
<div
|
|
||||||
class="bg-base-100 text-base-content shadow rounded-box p-4 transition duration-300 ease-in-out md:hidden"
|
|
||||||
class:block={isMobileMenuOpen}
|
|
||||||
class:hidden={!isMobileMenuOpen}
|
|
||||||
>
|
|
||||||
<ul class="flex flex-col space-y-4">
|
|
||||||
<NavLinks isMobile={true} />
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|||||||
Reference in New Issue
Block a user