Files
wanderer/web/src/lib/components/trail/trail_timeline.svelte
Christian Beutel 8706fe7ac9 adds video support
2025-03-16 18:01:12 +01:00

121 lines
4.3 KiB
Svelte

<script lang="ts">
import type { Trail } from "$lib/models/trail";
import { getFileURL, isVideoURL } from "$lib/util/file_util";
import { formatDistance } from "$lib/util/format_util";
import { _ } from "svelte-i18n";
import PhotoGallery from "../photo_gallery.svelte";
type Props = {
trail: Trail;
onmouseenter?: (index: number) => void;
onmouseleave?: (index: number) => void;
};
let gallery: PhotoGallery[] = $state([]);
let { trail, onmouseenter, onmouseleave }: Props = $props();
</script>
<div
class="trail-timeline relative grid grid-cols-[auto_1fr] items-start gap-x-4 gap-y-6"
>
<div class="bg-background">
<i class="fa fa-bullseye"></i>
</div>
<div class="">
<p class="font-semibold">{$_("start")}</p>
</div>
{#each trail.expand?.waypoints ?? [] as wp, i}
<div
class="bg-background cursor-pointer"
role="presentation"
onmouseenter={() => onmouseenter?.(i)}
onmouseleave={() => onmouseleave?.(i)}
>
<i class="fa fa-{wp.icon ?? 'circle'}"></i>
{#if wp.distance_from_start}
<p class="text-sm text-gray-500">
{formatDistance(wp.distance_from_start)}
</p>
{/if}
</div>
<div class="border border-input-border rounded-xl overflow-hidden">
{#if wp.photos.length}
<PhotoGallery
photos={wp.photos.map((p) => getFileURL(wp, p))}
bind:this={gallery[i]}
></PhotoGallery>
<div
class="grid gap-[1px] {wp.photos.length > 1
? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'} cursor-pointer"
>
{#each wp.photos as photo, j}
{#if isVideoURL(photo)}
<!-- svelte-ignore a11y_media_has_caption -->
<video
controls={false}
loop
class="w-full object-cover {j == 0 &&
wp.photos.length > 2
? 'row-span-2 h-80'
: 'h-[159.5px]'}"
onclick={() => gallery[i].openGallery(j)}
onmouseenter={(e) => (e.target as any).play()}
onmouseleave={(e) => (e.target as any).pause()}
src={getFileURL(wp, photo)}
></video>
{:else}
<img
onclick={() => gallery[i].openGallery(j)}
role="presentation"
class="w-full object-cover {j == 0 &&
wp.photos.length > 2
? 'row-span-2 h-80'
: 'h-[159.5px]'}"
src={getFileURL(wp, photo)}
alt=""
/>
{/if}
{/each}
</div>
{/if}
<div class="p-4">
<h5 class="text-xl font-semibold">{wp.name}</h5>
<span class="text-sm text-gray-500"
><i class="fa fa-location-dot mr-1"></i>
{wp.lat.toFixed(5)}, {wp.lon.toFixed(5)}</span
>
<p class="whitespace-pre-line">
{wp.description}
</p>
</div>
</div>
{/each}
<div class="bg-background">
<i class="fa fa-flag-checkered"></i>
{#if trail.distance}
<p class="text-sm text-gray-500">
{formatDistance(trail.distance)}
</p>
{/if}
</div>
<div class="">
<p class="font-semibold">{$_("finish")}</p>
</div>
</div>
<style>
.trail-timeline::before {
border-right: 2px dotted rgba(var(--input-border));
bottom: 0;
content: "";
left: 7.2px;
position: absolute;
top: 0;
width: 1px;
z-index: -1;
}
</style>