feat: Add location_name to ReverseGeocode type and implement location fetching in stats view

This commit is contained in:
Sean Morley
2025-02-15 19:44:11 -05:00
parent 60b5bbb3c8
commit b5d6788c11
21 changed files with 1048 additions and 901 deletions

View File

@@ -1,126 +1,141 @@
<script lang="ts">
import { goto } from '$app/navigation';
import AdventureOverlook from '$lib/assets/AdventureOverlook.webp';
import MapWithPins from '$lib/assets/MapWithPins.webp';
import { t } from 'svelte-i18n';
import { DefaultMarker, MapLibre, Marker, Popup } from 'svelte-maplibre';
import MapWithPins from '$lib/assets/MapWithPins.webp';
import InformationSlabCircleOutline from '~icons/mdi/information-slab-circle-outline';
export let data;
</script>
<section class="flex items-center justify-center w-full py-12 md:py-24 lg:py-32">
<div class="container px-4 md:px-6">
<div class="grid gap-6 lg:grid-cols-[1fr_550px] lg:gap-12 xl:grid-cols-[1fr_650px]">
<div class="flex flex-col justify-center space-y-4">
<div class="space-y-2">
{#if data.user}
{#if data.user.first_name && data.user.first_name !== null}
<h1
class="text-3xl font-bold tracking-tighter sm:text-5xl xl:text-6xl/none bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent pb-4"
>
{data.user.first_name.charAt(0).toUpperCase() + data.user.first_name.slice(1)},
{$t('home.hero_1')}
</h1>
{:else}
<h1
class="text-3xl font-bold tracking-tighter sm:text-5xl xl:text-6xl/none bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent pb-4"
>
{$t('home.hero_1')}
</h1>
{/if}
{:else}
<h1
class="text-3xl font-bold tracking-tighter sm:text-5xl xl:text-6xl/none bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent pb-4"
>
{$t('home.hero_1')}
</h1>
{/if}
<p class="max-w-[600px] text-gray-500 md:text-xl dark:text-gray-400">
{$t('home.hero_2')}
</p>
</div>
<div class="flex flex-col gap-2 min-[400px]:flex-row">
{#if data.user}
<button on:click={() => goto('/adventures')} class="btn btn-primary">
{$t('home.go_to')}
</button>
{:else}
<button on:click={() => goto('/login')} class="btn btn-primary">
{$t('auth.login')}
</button>
<button on:click={() => goto('/signup')} class="btn btn-neutral">
{$t('auth.signup')}
</button>
{/if}
</div>
<!-- Hero Section -->
<section class="flex items-center justify-center w-full py-20 bg-gray-50 dark:bg-gray-800">
<div class="container mx-auto px-4 flex flex-col-reverse md:flex-row items-center gap-8">
<!-- Text Content -->
<div class="w-full md:w-1/2 space-y-6">
{#if data.user}
{#if data.user.first_name && data.user.first_name !== null}
<h1
class="text-5xl md:text-6xl font-extrabold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent"
>
{data.user.first_name.charAt(0).toUpperCase() + data.user.first_name.slice(1)}, {$t(
'home.hero_1'
)}
</h1>
{:else}
<h1
class="text-5xl md:text-6xl font-extrabold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent"
>
{$t('home.hero_1')}
</h1>
{/if}
{:else}
<h1
class="text-5xl md:text-6xl font-extrabold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent"
>
{$t('home.hero_1')}
</h1>
{/if}
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-xl">
{$t('home.hero_2')}
</p>
<div class="flex flex-col sm:flex-row gap-4">
{#if data.user}
<button on:click={() => goto('/adventures')} class="btn btn-primary">
{$t('home.go_to')}
</button>
{:else}
<button on:click={() => goto('/login')} class="btn btn-primary">
{$t('auth.login')}
</button>
<button on:click={() => goto('/signup')} class="btn btn-secondary">
{$t('auth.signup')}
</button>
{/if}
</div>
<img
src={AdventureOverlook}
width="550"
height="550"
alt="Hero"
class="mx-auto aspect-video overflow-hidden rounded-xl object-cover sm:w-full lg:order-last"
/>
</div>
<!-- Image -->
<div class="w-full md:w-1/2">
<p class="flex items-center text-neutral-content">
<InformationSlabCircleOutline class="w-4 h-4 mr-1" />
{$t('adventures.welcome_map_info')}
</p>
<MapLibre
style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
class="flex items-center self-center justify-center aspect-[9/16] max-h-[70vh] sm:aspect-video sm:max-h-full w-10/12 rounded-lg"
standardControls
>
{#each data.props.locations as location}
{#if location.latitude && location.longitude}
<DefaultMarker
lngLat={[location.longitude, location.latitude]}
on:click={() => goto(`/locations/${location.id}`)}
>
<span class="text-xl">{location.name}</span>
<Popup openOn="click" offset={[0, -10]}>
<div class="text-lg text-black font-bold">{location.name}</div>
<button
class="btn btn-neutral btn-wide btn-sm mt-4"
on:click={() => goto(`/adventures/${location.id}`)}
>
{$t('map.view_details')}
</button>
</Popup>
</DefaultMarker>
{/if}
{/each}
</MapLibre>
</div>
</div>
</section>
<section
class="flex items-center justify-center w-full py-12 md:py-24 lg:py-32 bg-gray-100 dark:bg-gray-800"
>
<div class="container px-4 md:px-6">
<div class="flex flex-col items-center justify-center space-y-4 text-center">
<div class="space-y-2">
<div
class="inline-block rounded-lg bg-gray-100 px-3 py-1 text-md dark:bg-gray-800 dark:text-gray-400"
>
{$t('home.key_features')}
</div>
<h2
class="text-3xl font-bold tracking-tighter sm:text-5xl bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent"
>
{$t('home.desc_1')}
</h2>
<p
class="max-w-[900px] text-gray-500 md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed dark:text-gray-400"
>
{$t('home.desc_2')}
</p>
<!-- Features Section -->
<section id="features" class="py-16 bg-white dark:bg-gray-900">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<div class="inline-block text-neutral-content bg-neutral px-4 py-2 rounded-full">
{$t('home.key_features')}
</div>
<h2
class="mt-4 text-3xl md:text-4xl font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent"
>
{$t('home.desc_1')}
</h2>
<p class="mt-4 text-gray-600 dark:text-gray-300 max-w-2xl mx-auto text-lg">
{$t('home.desc_2')}
</p>
</div>
<div class="mx-auto grid max-w-5xl items-center gap-6 py-12 lg:grid-cols-2 lg:gap-12">
<!-- svelte-ignore a11y-img-redundant-alt -->
<img
src={MapWithPins}
width="550"
height="310"
alt="Image"
class="mx-auto aspect-video overflow-hidden rounded-xl object-cover object-center sm:w-full lg:order-last"
/>
<div class="flex flex-col justify-center space-y-4">
<ul class="grid gap-6">
<li>
<div class="grid gap-1">
<h3 class="text-xl font-bold dark:text-gray-400">{$t('home.feature_1')}</h3>
<p class="text-gray-500 dark:text-gray-400">
{$t('home.feature_1_desc')}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 items-center">
<!-- Image for Features -->
<div class="order-1 md:order-2">
<img
src={MapWithPins}
alt="World map with pins"
class="rounded-lg shadow-lg object-cover"
/>
</div>
<!-- Feature List -->
<div class="order-2 md:order-1">
<ul class="space-y-6">
<li class="space-y-2">
<h3 class="text-xl font-semibold dark:text-gray-300">{$t('home.feature_1')}</h3>
<p class="text-gray-600 dark:text-gray-400">
{$t('home.feature_1_desc')}
</p>
</li>
<li>
<div class="grid gap-1">
<h3 class="text-xl font-bold dark:text-gray-400">{$t('home.feature_2')}</h3>
<p class="text-gray-500 dark:text-gray-400">
{$t('home.feature_2_desc')}
</p>
</div>
<li class="space-y-2">
<h3 class="text-xl font-semibold dark:text-gray-300">{$t('home.feature_2')}</h3>
<p class="text-gray-600 dark:text-gray-400">
{$t('home.feature_2_desc')}
</p>
</li>
<li>
<div class="grid gap-1">
<h3 class="text-xl font-bold dark:text-gray-400">{$t('home.feature_3')}</h3>
<p class="text-gray-500 dark:text-gray-400">
{$t('home.feature_3_desc')}
</p>
</div>
<li class="space-y-2">
<h3 class="text-xl font-semibold dark:text-gray-300">{$t('home.feature_3')}</h3>
<p class="text-gray-600 dark:text-gray-400">
{$t('home.feature_3_desc')}
</p>
</li>
</ul>
</div>