94 lines
2.5 KiB
Svelte
94 lines
2.5 KiB
Svelte
<script lang="ts">
|
|
import { get } from 'svelte/store';
|
|
|
|
import { goto } from '$app/navigation';
|
|
import { resolve } from '$app/paths';
|
|
import { page } from '$app/stores';
|
|
|
|
import { type GeoLocation, storedLocation } from '$lib/stores/settings';
|
|
|
|
import { buildLocationRoute } from '$lib/utils/location';
|
|
|
|
import LocationSearch from '$lib/components/location/location-search.svelte';
|
|
|
|
interface Props {
|
|
onMenuToggle?: () => void;
|
|
}
|
|
|
|
let { onMenuToggle }: Props = $props();
|
|
|
|
let location = $state(get(storedLocation));
|
|
|
|
storedLocation.subscribe((value) => {
|
|
location = value;
|
|
});
|
|
|
|
function navigateToLocation(newLocation: GeoLocation) {
|
|
storedLocation.set(newLocation);
|
|
const locationRoute = buildLocationRoute(newLocation);
|
|
const currentPath = get(page).url.pathname;
|
|
|
|
if (currentPath.startsWith('/weather/compare')) {
|
|
goto(resolve('/weather/compare/[location]', { location: locationRoute }));
|
|
} else if (currentPath.startsWith('/weather/14-day')) {
|
|
goto(resolve('/weather/14-day/[location]', { location: locationRoute }));
|
|
} else {
|
|
goto(resolve('/weather/week/[location]', { location: locationRoute }));
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<header
|
|
class="topbar flex h-14 shrink-0 items-center gap-3 border-b border-topbar-border bg-topbar px-3 md:px-4"
|
|
>
|
|
<!-- Mobile menu toggle -->
|
|
<button
|
|
class="flex h-8 w-8 items-center justify-center rounded-md transition-colors hover:bg-black/5 md:hidden dark:hover:bg-white/10"
|
|
onclick={onMenuToggle}
|
|
aria-label="Toggle menu"
|
|
>
|
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.75">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Current location display -->
|
|
{#if location}
|
|
<div class="hidden items-center gap-2 sm:flex">
|
|
<img
|
|
class="h-5 w-5 rounded-full"
|
|
src="/images/country-flags/{(location.country_code || 'united_nations').toLowerCase()}.svg"
|
|
alt={location.country}
|
|
/>
|
|
<span class="text-sm font-medium text-foreground">
|
|
{location.name}
|
|
</span>
|
|
{#if location.admin1 || location.country}
|
|
<span class="text-xs text-muted-foreground">
|
|
{#if location.admin1}{location.admin1},{/if}
|
|
{location.country}
|
|
</span>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Spacer -->
|
|
<div class="flex-1"></div>
|
|
|
|
<!-- Location search -->
|
|
<div class="w-full max-w-sm md:max-w-md">
|
|
<LocationSearch
|
|
label="Search location..."
|
|
on:location={(event) => {
|
|
navigateToLocation(event.detail);
|
|
}}
|
|
/>
|
|
</div>
|
|
</header>
|
|
|
|
<style>
|
|
.topbar {
|
|
z-index: 40;
|
|
}
|
|
</style>
|