247 lines
8.3 KiB
Svelte
247 lines
8.3 KiB
Svelte
<script lang="ts">
|
|
import { tick } from 'svelte';
|
|
import { goto } from '$app/navigation';
|
|
import { enhance } from '$app/forms';
|
|
|
|
import {
|
|
ShoppingBag,
|
|
CircleUserRound,
|
|
Search,
|
|
SlidersHorizontal,
|
|
LogOut,
|
|
UserRound
|
|
} from '@lucide/svelte';
|
|
import logo from '$lib/assets/img/logo/full_logo.png?enhanced';
|
|
|
|
import { Button } from '$lib/components/ui/button';
|
|
import * as Sheet from '$lib/components/ui/sheet/index.js';
|
|
import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
|
|
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
|
|
import * as NavigationMenu from '$lib/components/ui/navigation-menu/index.js';
|
|
|
|
const languages = [
|
|
{
|
|
value: 'English',
|
|
label: 'English',
|
|
code: 'Us'
|
|
},
|
|
{
|
|
value: 'Nepali',
|
|
label: 'Nepali',
|
|
code: 'Np'
|
|
}
|
|
];
|
|
|
|
let { user, category } = $props();
|
|
let open = $state(false);
|
|
let value = $state(languages[0].value);
|
|
let triggerRef = $state<HTMLButtonElement>(null!);
|
|
let searchInputText = $state('');
|
|
|
|
const selectedValue = $derived(languages.find((f) => f.value === value)?.label);
|
|
function closeAndFocusTrigger() {
|
|
open = false;
|
|
tick().then(() => {
|
|
triggerRef.focus();
|
|
});
|
|
}
|
|
|
|
function searchInput(e: Event) {
|
|
e.preventDefault();
|
|
goto(`/category/search/${searchInputText}?q=${searchInputText}`, {
|
|
invalidateAll: true,
|
|
keepFocus: false,
|
|
replaceState: true
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<header class="sticky top-0 z-50 border-y border-gray-200 bg-white">
|
|
<div
|
|
class="max-xs:gap-0 mx-auto flex max-w-screen-2xl items-center justify-between gap-10 px-10 py-4 max-lg:flex-wrap max-lg:gap-4 max-md:px-6 max-sm:border-y-0 max-sm:border-b max-sm:px-4"
|
|
>
|
|
<div class="max-xs:w-32 w-40 max-sm:w-32">
|
|
<a href="/" aria-label="Logo">
|
|
<enhanced:img src={logo} alt="Logo" class="w-64" />
|
|
</a>
|
|
</div>
|
|
<div class="flex w-full items-center gap-2 max-lg:order-3 max-lg:w-full">
|
|
<Sheet.Root {open}>
|
|
<Sheet.Trigger
|
|
onclick={() => {
|
|
open = true;
|
|
}}
|
|
>
|
|
<!-- <SlidersHorizontal class="md:hidden" strokeWidth={1.8} size={20} /> -->
|
|
<p class="text-sm font-medium md:hidden">Categories</p>
|
|
</Sheet.Trigger>
|
|
<Sheet.Content side="left" class="flex w-full flex-col gap-8 px-4 sm:w-full">
|
|
<Sheet.Header class="text-start">
|
|
<Sheet.Title>Categories</Sheet.Title>
|
|
</Sheet.Header>
|
|
<ScrollArea
|
|
class="w-full [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
scrollbarXClasses="border-none"
|
|
>
|
|
<div class="flex flex-col gap-4">
|
|
<!-- {#await category then categoryItem} -->
|
|
{#each category?.categories as item}
|
|
{#if item?.status !== 'draft'}
|
|
<a
|
|
href="/category/{item?.id}/{item?.slug}"
|
|
class="text-nowrap"
|
|
onclick={() => {
|
|
open = false;
|
|
}}>{item?.title}</a
|
|
>
|
|
{/if}
|
|
{/each}
|
|
<!-- {/await} -->
|
|
</div>
|
|
</ScrollArea>
|
|
</Sheet.Content>
|
|
</Sheet.Root>
|
|
|
|
<NavigationMenu.Root>
|
|
<NavigationMenu.List class="gap-0">
|
|
<NavigationMenu.Item class="max-md:hidden">
|
|
<NavigationMenu.Trigger>Categories</NavigationMenu.Trigger>
|
|
<NavigationMenu.Content>
|
|
<ul class="grid w-[400px] gap-1 p-2 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
|
|
<!-- {#await category then categoryItem} -->
|
|
{#each category?.categories as item}
|
|
{#if item?.status !== 'draft'}
|
|
<li>
|
|
<NavigationMenu.Link
|
|
href="/category/{item?.id}/{item?.slug}"
|
|
class="text-nowrap"
|
|
>
|
|
{item?.title}
|
|
</NavigationMenu.Link>
|
|
</li>
|
|
{/if}
|
|
{/each}
|
|
<!-- {/await} -->
|
|
</ul>
|
|
</NavigationMenu.Content>
|
|
</NavigationMenu.Item>
|
|
<NavigationMenu.Item>
|
|
<NavigationMenu.Link href="/brand" class="text-sm font-medium text-nowrap">
|
|
Brands
|
|
</NavigationMenu.Link>
|
|
</NavigationMenu.Item>
|
|
</NavigationMenu.List>
|
|
</NavigationMenu.Root>
|
|
|
|
<form class="max-xs:mt-2 w-full max-lg:w-full max-md:hidden" onsubmit={searchInput}>
|
|
<div
|
|
class="flex w-full items-center gap-1 rounded-lg border-[1.6px] border-gray-200 p-1 pl-4 focus-within:border-primary/40 max-sm:gap-2 max-sm:pl-3"
|
|
>
|
|
<Search strokeWidth={1.5} class="text-primary/45 max-sm:w-5" />
|
|
<input
|
|
type="text"
|
|
placeholder="Search for products..."
|
|
class="max-xs:text-xs w-full text-sm tracking-tight focus-visible:ring-0 focus-visible:outline-none max-sm:py-2"
|
|
bind:value={searchInputText}
|
|
/>
|
|
<Button
|
|
class="max-xs:text-xs rounded-md border border-primary px-4 py-2 text-sm font-semibold tracking-tight text-primary max-sm:hidden"
|
|
type="submit"
|
|
variant="outline">Search</Button
|
|
>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="flex items-center gap-5 max-sm:gap-3">
|
|
<Sheet.Root>
|
|
<Sheet.Trigger class="flex flex-col items-center justify-center gap-2 md:hidden">
|
|
<Search class="md:hidden" strokeWidth={1.8} size={20} />
|
|
<p class="text-xs font-medium text-nowrap">Search</p>
|
|
</Sheet.Trigger>
|
|
<Sheet.Content side="right" class="flex w-full flex-col gap-0 sm:w-full">
|
|
<Sheet.Header class="text-start">
|
|
<Sheet.Title>Search</Sheet.Title>
|
|
</Sheet.Header>
|
|
<form class="w-full px-2 max-lg:w-full md:hidden" onsubmit={searchInput}>
|
|
<div
|
|
class="flex w-full items-center gap-1 rounded-lg border-[1.6px] border-gray-200 p-1 pl-4 focus-within:border-primary/40 max-sm:gap-2 max-sm:pl-3"
|
|
>
|
|
<Search strokeWidth={1.5} class="text-primary/45 max-sm:w-5" />
|
|
<input
|
|
type="text"
|
|
placeholder="Search for products..."
|
|
class="max-xs:text-xs w-full text-sm tracking-tight focus-visible:ring-0 focus-visible:outline-none max-sm:py-2"
|
|
bind:value={searchInputText}
|
|
/>
|
|
<Button
|
|
class="max-xs:text-xs rounded-md border border-primary px-4 py-2 text-sm font-semibold tracking-tight text-primary max-sm:hidden"
|
|
type="submit"
|
|
variant="outline">Search</Button
|
|
>
|
|
</div>
|
|
</form>
|
|
</Sheet.Content>
|
|
</Sheet.Root>
|
|
<div class="max-xs:gap-4 flex items-center gap-4 max-sm:gap-3">
|
|
<a
|
|
href={user?.authenticated ? '/cart' : '/login'}
|
|
class="max-xs:gap-0 flex flex-col items-center gap-1"
|
|
>
|
|
<ShoppingBag strokeWidth={1.2} class="max-xs:w-5" />
|
|
<p class="text-xs font-medium text-nowrap">Cart</p>
|
|
</a>
|
|
{#if user?.authenticated}
|
|
<DropdownMenu.Root>
|
|
<DropdownMenu.Trigger class="cursor-pointer">
|
|
<div class="flex flex-col items-center">
|
|
{#if user?.user?.profileImage}
|
|
<img
|
|
src={user?.user?.profileImage}
|
|
alt="{user?.user?.name} avatar"
|
|
class="aspect-square h-7 w-7 rounded-full object-cover object-center"
|
|
/>
|
|
{:else}
|
|
<p class="flex h-7 w-7 items-center justify-center rounded-full bg-slate-200">
|
|
{user?.user?.name.slice(0, 1)}
|
|
</p>
|
|
{/if}
|
|
<p class="text-xs font-medium">{user?.user?.name.split(' ')[0]}</p>
|
|
</div>
|
|
</DropdownMenu.Trigger>
|
|
<DropdownMenu.Content align="end" class="min-w-40">
|
|
<DropdownMenu.Group>
|
|
<DropdownMenu.GroupHeading>My Account</DropdownMenu.GroupHeading>
|
|
<DropdownMenu.Separator class="bg-primary/15 " />
|
|
<a href="/profile">
|
|
<DropdownMenu.Item class="cursor-pointer">
|
|
<UserRound size={20} strokeWidth={1.5} />
|
|
<span> Profile </span>
|
|
</DropdownMenu.Item>
|
|
</a>
|
|
<DropdownMenu.Item class="flex cursor-pointer items-center text-primary">
|
|
<form method="POST" action="/logout" use:enhance>
|
|
<button type="submit" class="flex items-center gap-2">
|
|
<LogOut size={20} strokeWidth={1.5} />
|
|
<p>Logout</p>
|
|
</button>
|
|
</form>
|
|
</DropdownMenu.Item>
|
|
</DropdownMenu.Group>
|
|
</DropdownMenu.Content>
|
|
</DropdownMenu.Root>
|
|
{:else}
|
|
<a href="/login" class="max-xs:gap-0 flex flex-col flex-nowrap items-center gap-1">
|
|
<CircleUserRound strokeWidth={1.2} class="max-xs:w-5" />
|
|
<p class="text-xs font-medium text-nowrap">Log in</p>
|
|
</a>
|
|
{/if}
|
|
</div>
|
|
<!-- <a
|
|
href="/booking"
|
|
class="text-nowrap rounded-md bg-primary px-5 py-3 text-sm font-semibold tracking-tight text-white max-md:px-3 max-md:py-3 max-md:text-xs max-xs:hidden"
|
|
>Book Appointment</a
|
|
> -->
|
|
</div>
|
|
</div>
|
|
</header>
|