Files
gpx.studio/website/src/routes/[[language]]/+page.svelte

255 lines
9.9 KiB
Svelte
Raw Normal View History

2024-04-24 16:12:50 +02:00
<script lang="ts">
import { Button } from '$lib/components/ui/button';
2025-10-20 20:17:47 +02:00
import ElevationProfile from '$lib/components/elevation-profile/ElevationProfile.svelte';
2025-10-18 16:10:08 +02:00
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
2025-10-20 19:53:42 +02:00
import Routing from '$lib/components/toolbar/tools/routing/Routing.svelte';
import {
BookOpenText,
Heart,
2026-03-29 20:04:38 +02:00
HeartHandshake,
ChartArea,
Map,
PencilRuler,
Route,
Scale,
2026-03-29 20:04:38 +02:00
HatGlasses,
Languages,
ExternalLink,
2025-06-21 21:07:36 +02:00
} from '@lucide/svelte';
import { i18n } from '$lib/i18n.svelte';
import { getURLForLanguage } from '$lib/utils';
import { exampleGPXFile } from '$lib/assets/example';
import { writable } from 'svelte/store';
2026-03-28 19:31:52 +01:00
import Scissors from '$lib/components/toolbar/tools/scissors/Scissors.svelte';
2025-10-18 16:10:08 +02:00
import { currentTool, Tool } from '$lib/components/toolbar/tools';
import { onDestroy, onMount } from 'svelte';
2024-07-08 15:46:00 +02:00
let gpxStatistics = writable(exampleGPXFile.getStatistics());
let slicedGPXStatistics = writable(undefined);
let hoveredPoint = writable(null);
let additionalDatasets = writable(['speed', 'atemp']);
2025-10-22 19:05:20 +02:00
let elevationFill = writable(undefined);
2024-07-08 15:46:00 +02:00
2025-10-18 16:10:08 +02:00
onMount(() => {
$currentTool = Tool.SCISSORS;
});
2024-07-08 15:46:00 +02:00
2025-10-18 16:10:08 +02:00
$effect(() => {
if ($currentTool !== Tool.SCISSORS) {
$currentTool = Tool.SCISSORS;
}
});
2024-07-18 15:24:56 +02:00
2025-10-18 16:10:08 +02:00
onDestroy(() => {
$currentTool = null;
});
2024-06-26 20:33:01 +02:00
</script>
2024-04-24 16:12:50 +02:00
2026-03-28 19:31:52 +01:00
<div class="w-full px-12 flex flex-col items-center">
<div class="w-full max-w-5xl flex flex-col items-center">
2026-03-29 15:14:21 +02:00
<div class="mt-12 flex flex-col xs:items-center gap-12">
<div class="flex flex-col xs:items-center gap-6 max-w-3xl">
<h1 class="text-4xl xs:text-5xl sm:text-6xl xs:text-center font-black">
2025-06-21 21:07:36 +02:00
{i18n._('metadata.home_title')}
</h1>
2026-03-29 15:14:21 +02:00
<div class="text-lg sm:text-xl text-muted-foreground xs:text-center">
2025-06-21 21:07:36 +02:00
{i18n._('metadata.description')}
</div>
2026-03-29 15:14:21 +02:00
<div class="w-full flex flex-row xs:justify-center gap-3">
2025-11-28 17:48:21 +01:00
<Button
data-sveltekit-reload
href={getURLForLanguage(i18n.lang, '/app')}
class="w-1/3 min-w-fit"
>
2025-11-10 11:51:16 +01:00
<Map size="18" />
2025-06-21 21:07:36 +02:00
{i18n._('homepage.app')}
</Button>
<Button
variant="secondary"
2025-06-21 21:07:36 +02:00
href={getURLForLanguage(i18n.lang, '/help')}
class="w-1/3 min-w-fit"
>
2025-11-10 11:51:16 +01:00
<BookOpenText size="18" />
2025-06-21 21:07:36 +02:00
<span>{i18n._('menu.help')}</span>
</Button>
</div>
</div>
2026-04-02 18:41:49 +02:00
<a href={getURLForLanguage(i18n.lang, '/app')} aria-label="Link to the web app.">
<enhanced:img
src="/src/lib/assets/img/docs/getting-started/interface.webp"
alt="The gpx.studio interface."
class="rounded-xl shadow-2xl w-full"
/></a
>
</div>
2026-03-29 20:04:38 +02:00
<h2>
2026-03-28 19:31:52 +01:00
{i18n._('homepage.features')}
2026-03-29 20:04:38 +02:00
</h2>
2026-03-28 19:31:52 +01:00
<div class="grid md:grid-cols-2 gap-12 border-t pt-6">
<div class="grid md:grid-rows-subgrid md:row-start-1 md:row-end-3 gap-4">
2026-03-29 20:04:38 +02:00
<div>
<h3>
2026-03-28 19:31:52 +01:00
<Route size="20" class="inline-block align-baseline" />
{i18n._('homepage.route_planning')}
2026-03-29 20:04:38 +02:00
</h3>
2026-03-28 19:31:52 +01:00
<p>
{i18n._('homepage.route_planning_description')}
</p>
</div>
<div class="relative">
<div
class="p-3 border rounded-xl shadow-xl origin-top-left scale-45 xs:scale-75 md:scale-45 lg:scale-70 absolute top-1.5 left-1.5 bg-background"
>
<Routing minimizable={false} />
</div>
<enhanced:img
src="/src/lib/assets/img/docs/tools/routing.png"
alt="Route planning illustration."
class="h-full object-cover rounded-xl shadow-lg"
/>
</div>
</div>
<div class="grid md:grid-rows-subgrid md:row-start-1 md:row-end-3 gap-4">
2026-03-29 20:04:38 +02:00
<div>
<h3>
2026-03-28 19:31:52 +01:00
<Map size="20" class="inline-block align-baseline" />
{i18n._('homepage.maps')}
2026-03-29 20:04:38 +02:00
</h3>
2026-03-28 19:31:52 +01:00
<p>{i18n._('homepage.maps_description')}</p>
</div>
2026-03-29 14:06:59 +02:00
<enhanced:img
src="/src/lib/assets/img/home/map-overlay.png"
alt="3D map with multiple layers and points of interest."
class="h-full object-cover rounded-xl shadow-lg"
/>
</div>
2026-03-29 20:04:38 +02:00
<div class="grid md:grid-rows-subgrid md:row-start-3 md:row-end-5 gap-4">
<div>
<h3>
2026-03-28 19:31:52 +01:00
<ChartArea size="20" class="inline-block align-baseline" />
{i18n._('homepage.data_visualization')}
2026-03-29 20:04:38 +02:00
</h3>
2026-03-28 19:31:52 +01:00
<p>
{i18n._('homepage.data_visualization_description')}
</p>
</div>
<div
2026-03-29 20:04:38 +02:00
class="w-full aspect-3/2 overflow-hidden flex flex-col gap-2 rounded-xl pt-6 pb-4 px-6 bg-secondary/50 border shadow-lg"
2026-03-28 19:31:52 +01:00
>
<div class="grow">
<ElevationProfile
{gpxStatistics}
{slicedGPXStatistics}
{hoveredPoint}
{additionalDatasets}
{elevationFill}
/>
</div>
<GPXStatistics
{gpxStatistics}
{slicedGPXStatistics}
orientation={'horizontal'}
/>
</div>
</div>
2026-03-29 20:04:38 +02:00
<div class="grid md:grid-rows-subgrid md:row-start-3 md:row-end-5 gap-4">
<div>
<h3>
2026-03-28 19:31:52 +01:00
<PencilRuler size="20" class="inline-block align-baseline" />
{i18n._('homepage.file_processing')}
2026-03-29 20:04:38 +02:00
</h3>
2026-03-28 19:31:52 +01:00
<p>
{i18n._('homepage.file_processing_description')}
</p>
</div>
<div class="relative">
<div
class="p-3 border rounded-xl shadow-xl origin-top-right scale-45 xs:scale-75 md:scale-45 lg:scale-70 absolute top-1.5 right-1.5 bg-background"
>
<Scissors />
</div>
<enhanced:img
src="/src/lib/assets/img/docs/tools/split.png"
alt="Splitting illustration."
class="h-full object-cover rounded-xl shadow-lg"
/>
</div>
</div>
</div>
2026-03-29 20:04:38 +02:00
<h2>
2026-03-28 19:31:52 +01:00
{i18n._('homepage.philosophy')}
2026-03-29 20:04:38 +02:00
</h2>
<div class="w-full grid md:grid-cols-2 gap-12 border-t pt-6">
<div class="w-full">
<h3>
<Scale size="20" class="inline-block align-baseline" />
{i18n._('homepage.foss')}
</h3>
<p>
{i18n._('homepage.foss_description')}
<Button
variant="link"
href="https://github.com/gpxstudio/gpx.studio"
target="_blank"
class="p-0 has-[>svg]:p-0 h-fit"
>
<ExternalLink size="20" class="inline-block align-baseline" />
</Button>
</p>
</div>
2026-03-29 20:04:38 +02:00
<div>
<h3>
<HatGlasses size="20" class="inline-block align-baseline" />
{i18n._('homepage.privacy')}
</h3>
<p>{i18n._('homepage.privacy_description')}</p>
</div>
</div>
2026-03-29 20:04:38 +02:00
<div
class="md:text-center flex flex-col md:items-center mt-12 mb-24 p-6 border bg-secondary/50 rounded-xl"
>
<h3>
{i18n._('homepage.community')}
</h3>
2026-03-29 22:56:48 +02:00
<p class="md:max-w-3/4">{i18n._('homepage.community_description')}</p>
2026-03-29 20:04:38 +02:00
<HeartHandshake size="80" class="mt-6 self-center" />
<div class="flex flex-row flex-wrap gap-4 justify-center mt-6">
2026-03-28 19:31:52 +01:00
<Button
2026-03-29 20:04:38 +02:00
variant="outline"
2026-03-28 19:31:52 +01:00
href="https://opencollective.com/gpxstudio"
target="_blank"
2026-03-29 23:06:59 +02:00
class="text-support text-base max-w-full h-auto whitespace-normal"
2026-03-28 19:31:52 +01:00
>
<span>{i18n._('homepage.support_button')}</span>
2026-03-29 22:31:57 +02:00
<Heart size="16" fill="var(--support)" color="var(--support)" />
2026-03-28 19:31:52 +01:00
</Button>
<Button
2026-03-29 20:04:38 +02:00
variant="outline"
2026-03-28 19:31:52 +01:00
href="https://crowdin.com/project/gpxstudio"
target="_blank"
2026-03-29 23:06:59 +02:00
class="text-base max-w-full h-auto whitespace-normal"
2026-03-28 19:31:52 +01:00
>
2026-03-29 20:04:38 +02:00
<Languages size="16" />
<span>{i18n._('homepage.translate_button')}</span>
2026-03-28 19:31:52 +01:00
</Button>
</div>
</div>
</div>
2024-07-08 15:46:00 +02:00
</div>
2026-03-28 19:31:52 +01:00
<style lang="postcss">
@reference "../../app.css";
2026-03-29 20:04:38 +02:00
div :global(h2) {
@apply text-center text-4xl font-extrabold mt-24 mb-6;
}
div :global(h3) {
@apply text-2xl pt-0 font-semibold mb-3;
}
div :global(p) {
@apply text-muted-foreground;
2026-03-28 19:31:52 +01:00
}
</style>