updates trail panel view

This commit is contained in:
Christian Beutel
2025-01-28 00:38:27 +01:00
parent 63a83116a9
commit ae3ef0e0a1
9 changed files with 94 additions and 65 deletions

View File

@@ -2,6 +2,7 @@
--primary: 36, 39, 52; --primary: 36, 39, 52;
--primary-hover: 17, 24, 39; --primary-hover: 17, 24, 39;
--secondary-hover: 243, 244, 246; --secondary-hover: 243, 244, 246;
--secondary-hover-inverse: 36, 39, 52;
--background: 255, 255, 255; --background: 255, 255, 255;
--background-inverse: 7, 10, 36; --background-inverse: 7, 10, 36;
@@ -14,6 +15,7 @@
--input-border: 209, 213, 219; --input-border: 209, 213, 219;
--input-border-focus: 36, 39, 52; --input-border-focus: 36, 39, 52;
--input-ring: 148, 163, 184; --input-ring: 148, 163, 184;
--input-ring-inverse: 108, 115, 150;
--menu-background: 255, 255, 255; --menu-background: 255, 255, 255;
--menu-item-background-hover: 243, 244, 246; --menu-item-background-hover: 243, 244, 246;

View File

@@ -123,7 +123,7 @@
<div class="basis-full"></div> <div class="basis-full"></div>
<hr class="border-input-border" /> <hr class="border-input-border" />
<div class="flex gap-4 items-center justify-between m-4"> <div class="flex gap-4 items-center justify-between m-4">
<a href="/profile/{user.id}"> <a class="shrink-0" href="/profile/{user.id}">
<img <img
class="rounded-full w-10 aspect-square" class="rounded-full w-10 aspect-square"
src={getFileURL(user, user.avatar) || src={getFileURL(user, user.avatar) ||
@@ -131,9 +131,9 @@
alt="avatar" alt="avatar"
/> />
</a> </a>
<a href="/profile/{user.id}"> <a href="/profile/{user.id}" style="width: calc(100% - 104px)">
<p class="text-sm">{user.username}</p> <p class="text-sm overflow-hidden text-ellipsis">{user.username}</p>
<p class="text-sm text-gray-500"> <p class="text-sm text-gray-500 overflow-hidden text-ellipsis">
{user.email} {user.email}
</p> </p>
</a> </a>

View File

@@ -132,25 +132,7 @@
adjustTrailFocus(activeTrail); adjustTrailFocus(activeTrail);
}); });
$effect(() => { $effect(() => {
if ($theme == "dark") { toggleEpcTheme();
epc?.toggleTheme({
profileBackgroundColor: "#191b24",
elevationGridColor: "#ddd2",
labelColor: "#ddd8",
crosshairColor: "#fff5",
tooltipBackgroundColor: "#242734",
tooltipTextColor: "#fff",
});
} else {
epc?.toggleTheme({
profileBackgroundColor: "#242734",
elevationGridColor: "#0002",
labelColor: "#0009",
crosshairColor: "#0005",
tooltipBackgroundColor: "#fff",
tooltipTextColor: "#000",
});
}
}); });
$effect(() => { $effect(() => {
if (drawing && map) { if (drawing && map) {
@@ -258,7 +240,7 @@
export function refreshElevationProfile() { export function refreshElevationProfile() {
if (activeTrail !== null && data[activeTrail]) { if (activeTrail !== null && data[activeTrail]) {
epc?.setData(data[activeTrail]!, waypoints); epc?.setData(data[activeTrail]!, waypoints);
} }
} }
@@ -280,7 +262,7 @@
return new M.LngLatBounds([minX, minY, maxX, maxY]); return new M.LngLatBounds([minX, minY, maxX, maxY]);
} }
function flyToBounds() { function flyToBounds() {
const bounds = const bounds =
activeTrail !== null && data[activeTrail] activeTrail !== null && data[activeTrail]
? (data[activeTrail].bbox as M.LngLatBoundsLike) ? (data[activeTrail].bbox as M.LngLatBoundsLike)
@@ -693,6 +675,28 @@
markers = []; markers = [];
} }
function toggleEpcTheme() {
if ($theme == "dark") {
epc?.toggleTheme({
profileBackgroundColor: "#191b24",
elevationGridColor: "#ddd2",
labelColor: "#ddd8",
crosshairColor: "#fff5",
tooltipBackgroundColor: "#242734",
tooltipTextColor: "#fff",
});
} else {
epc?.toggleTheme({
profileBackgroundColor: "#242734",
elevationGridColor: "#0002",
labelColor: "#0009",
crosshairColor: "#0005",
tooltipBackgroundColor: "#fff",
tooltipTextColor: "#000",
});
}
}
onMount(async () => { onMount(async () => {
const initialState = { const initialState = {
lng: 0, lng: 0,
@@ -844,6 +848,7 @@
} }
}, },
}); });
toggleEpcTheme();
map.addControl(epc); map.addControl(epc);
} }

View File

@@ -2,7 +2,6 @@
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import Tabs from "$lib/components/base/tabs.svelte"; import Tabs from "$lib/components/base/tabs.svelte";
import TrailDropdown from "$lib/components/trail/trail_dropdown.svelte"; import TrailDropdown from "$lib/components/trail/trail_dropdown.svelte";
import WaypointCard from "$lib/components/waypoint/waypoint_card.svelte";
import { Comment } from "$lib/models/comment"; import { Comment } from "$lib/models/comment";
import type { Trail } from "$lib/models/trail"; import type { Trail } from "$lib/models/trail";
@@ -21,6 +20,7 @@
formatTimeHHMM, formatTimeHHMM,
} from "$lib/util/format_util"; } from "$lib/util/format_util";
import { browser } from "$app/environment";
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg"; import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg"; import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
import { pb } from "$lib/pocketbase"; import { pb } from "$lib/pocketbase";
@@ -34,15 +34,13 @@
import SkeletonNotificationCard from "../base/skeleton_notification_card.svelte"; import SkeletonNotificationCard from "../base/skeleton_notification_card.svelte";
import Textarea from "../base/textarea.svelte"; import Textarea from "../base/textarea.svelte";
import CommentCard from "../comment/comment_card.svelte"; import CommentCard from "../comment/comment_card.svelte";
import EmptyStateComment from "../empty_states/empty_state_comment.svelte";
import EmptyStateDescription from "../empty_states/empty_state_description.svelte";
import EmptyStatePhotos from "../empty_states/empty_state_photos.svelte";
import PhotoGallery from "../photo_gallery.svelte"; import PhotoGallery from "../photo_gallery.svelte";
import ShareInfo from "../share_info.svelte"; import ShareInfo from "../share_info.svelte";
import SummitLogTable from "../summit_log/summit_log_table.svelte"; import SummitLogTable from "../summit_log/summit_log_table.svelte";
import MapWithElevationMaplibre from "./map_with_elevation_maplibre.svelte"; import MapWithElevationMaplibre from "./map_with_elevation_maplibre.svelte";
import EmptyStateComment from "../empty_states/empty_state_comment.svelte";
import EmptyStatePhotos from "../empty_states/empty_state_photos.svelte";
import EmptyStateWaypoint from "../empty_states/empty_state_waypoint.svelte";
import EmptyStateDescription from "../empty_states/empty_state_description.svelte";
import { browser } from "$app/environment";
import TrailTimeline from "./trail_timeline.svelte"; import TrailTimeline from "./trail_timeline.svelte";
interface Props { interface Props {
@@ -178,7 +176,7 @@
></div> ></div>
{#if (trail.public || trailIsShared) && pb.authStore.model} {#if (trail.public || trailIsShared) && pb.authStore.model}
<div <div
class="flex absolute top-8 left-8 {trail.public && class="flex absolute top-6 right-6 {trail.public &&
trailIsShared trailIsShared
? 'w-16' ? 'w-16'
: 'w-8'} h-8 rounded-full items-center justify-center bg-white text-primary" : 'w-8'} h-8 rounded-full items-center justify-center bg-white text-primary"
@@ -197,6 +195,15 @@
{/if} {/if}
</div> </div>
{/if} {/if}
{#if mode == "map"}
<button
aria-label="Back"
class="btn-icon hover:bg-white hover:text-black ring-input-ring text-white absolute top-6 left-6"
onclick={() => history.back()}
>
<i class="fa fa-arrow-left"></i>
</button>
{/if}
<div <div
class="flex absolute justify-between items-end w-full bottom-8 left-0 px-8 gap-y-4" class="flex absolute justify-between items-end w-full bottom-8 left-0 px-8 gap-y-4"
> >
@@ -262,7 +269,7 @@
class="grid grid-cols-2 sm:grid-cols-5 gap-y-4 py-4 border-b border-input-border px-3" class="grid grid-cols-2 sm:grid-cols-5 gap-y-4 py-4 border-b border-input-border px-3"
> >
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<span class="font-medium" <span class="font-medium text-center"
>{#if mode == "overview"} >{#if mode == "overview"}
{$_("distance")} {$_("distance")}
{:else} {:else}
@@ -272,7 +279,7 @@
<span class="">{formatDistance(trail.distance)}</span> <span class="">{formatDistance(trail.distance)}</span>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<span class="font-medium" <span class="font-medium text-center"
>{#if mode == "overview"} >{#if mode == "overview"}
{$_("est-duration")} {$_("est-duration")}
{:else} {:else}
@@ -282,7 +289,7 @@
<span class="">{formatTimeHHMM(trail.duration)}</span> <span class="">{formatTimeHHMM(trail.duration)}</span>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<span class="font-medium" <span class="font-medium text-center"
>{#if mode == "overview"} >{#if mode == "overview"}
{$_("elevation-gain")} {$_("elevation-gain")}
{:else} {:else}
@@ -292,7 +299,7 @@
<span class="">{formatElevation(trail.elevation_gain)}</span> <span class="">{formatElevation(trail.elevation_gain)}</span>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<span class="font-medium" <span class="font-medium text-center"
>{#if mode == "overview"} >{#if mode == "overview"}
{$_("elevation-loss")} {$_("elevation-loss")}
{:else} {:else}
@@ -303,7 +310,7 @@
</div> </div>
{#if trail.expand?.category} {#if trail.expand?.category}
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<span class="font-medium" <span class="font-medium text-center"
>{#if mode == "overview"} >{#if mode == "overview"}
{$_("category")} {$_("category")}
{:else} {:else}
@@ -327,14 +334,13 @@
<section class="trail-info-panel-content px-8"> <section class="trail-info-panel-content px-8">
<div <div
class="grid grid-cols-1 my-4 gap-8" class="grid grid-cols-1 my-4 gap-8"
class:md:grid-cols-[1fr_18rem]={mode == "overview"} class:xl:grid-cols-[1fr_18rem]={mode == "overview"}
> >
<div> <div class="order-1 xl:-order-1">
<h4 class="text-2xl font-semibold my-4">
{$_("description")}
</h4>
{#if trail.description?.length} {#if trail.description?.length}
<h4 class="text-2xl font-semibold my-4">
{$_("description")}
</h4>
<article class="text-justify whitespace-pre-line text-sm"> <article class="text-justify whitespace-pre-line text-sm">
{!fullDescription {!fullDescription
? trail.description?.substring(0, 300) ? trail.description?.substring(0, 300)
@@ -357,7 +363,12 @@
<EmptyStateDescription></EmptyStateDescription> <EmptyStateDescription></EmptyStateDescription>
{/if} {/if}
<h4 class="text-2xl font-semibold mb-6 mt-12">{$_("route")}</h4> <h4 class="text-2xl font-semibold mb-6 mt-12">{$_("route")}</h4>
<div class="relative border border-input-border rounded-xl p-2 mb-6 text-xs" id="epc-container"></div> {#if mode === "overview"}
<div
class="relative border border-input-border rounded-xl p-2 mb-6 text-xs"
id="epc-container"
></div>
{/if}
<TrailTimeline <TrailTimeline
{trail} {trail}
onmouseenter={openMarkerPopup} onmouseenter={openMarkerPopup}
@@ -469,7 +480,9 @@
</div> </div>
{#if mode == "overview"} {#if mode == "overview"}
<div class="sticky top-4 h-72 rounded-xl overflow-hidden"> <div
class="block xl:sticky top-4 h-72 rounded-xl overflow-hidden"
>
<MapWithElevationMaplibre <MapWithElevationMaplibre
trails={[trail]} trails={[trail]}
activeTrail={0} activeTrail={0}

View File

@@ -11,11 +11,9 @@
onmouseleave?: (index: number) => void; onmouseleave?: (index: number) => void;
}; };
let gallery: PhotoGallery; let gallery: PhotoGallery[] = $state([]);
let { trail, onmouseenter, onmouseleave }: Props = $props(); let { trail, onmouseenter, onmouseleave }: Props = $props();
const photos = trail.expand?.waypoints.map(wp => wp.photos.map((p) => getFileURL(wp, p))).flat() ?? []
</script> </script>
<div <div
@@ -27,10 +25,6 @@
<div class=""> <div class="">
<p class="font-semibold">{$_("start")}</p> <p class="font-semibold">{$_("start")}</p>
</div> </div>
<PhotoGallery
{photos}
bind:this={gallery}
></PhotoGallery>
{#each trail.expand?.waypoints ?? [] as wp, i} {#each trail.expand?.waypoints ?? [] as wp, i}
<div <div
class="bg-background cursor-pointer" class="bg-background cursor-pointer"
@@ -48,20 +42,23 @@
<div class="border border-input-border rounded-xl overflow-hidden"> <div class="border border-input-border rounded-xl overflow-hidden">
{#if wp.photos.length} {#if wp.photos.length}
<PhotoGallery photos={wp.photos.map((p) => getFileURL(wp, p))} bind:this={gallery[i]}
></PhotoGallery>
<div <div
class="grid {wp.photos.length > 1 class="grid {wp.photos.length > 1
? 'grid-cols-[8fr_5fr]' ? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'} cursor-pointer" : 'grid-cols-1'} cursor-pointer"
role="presentation"
onclick={() => gallery.openGallery(i)}
> >
{#each wp.photos as photo, i} {#each wp.photos as photo, j}
<img <button onclick={() => gallery[i].openGallery(j)}>
class="object-cover h-full max-h-80 w-full" <img
class:row-span-2={i == 0 && wp.photos.length > 2} class="object-cover h-full max-h-80 w-full"
src={getFileURL(wp, photo)} class:row-span-2={i == 0 &&
alt="" wp.photos.length > 2}
/> src={getFileURL(wp, photo)}
alt=""
/>
</button>
{/each} {/each}
</div> </div>
{/if} {/if}

View File

@@ -61,8 +61,11 @@ type Address = {
road: string road: string
neighbourhood: string neighbourhood: string
suburb: string suburb: string
city_district: string city_district?: string
city: string city?: string
town?: string
hamlet?: string
village?: string;
state: string state: string
"ISO3166-2-lvl4": string "ISO3166-2-lvl4": string
postcode: string postcode: string
@@ -147,6 +150,7 @@ export async function searchLocationReverse(lat: number, lon: number) {
function getLocationDescription(address: Address) { function getLocationDescription(address: Address) {
let description = "" let description = ""
console.log(address);
if (address.country) { if (address.country) {
description += address.country; description += address.country;
@@ -156,6 +160,12 @@ function getLocationDescription(address: Address) {
} }
if (address.city) { if (address.city) {
description = `${address.city}, ` + description description = `${address.city}, ` + description
} else if (address.town) {
description = `${address.town}, ` + description
}else if (address.hamlet) {
description = `${address.hamlet}, ` + description
} else if (address.village) {
description = `${address.village}, ` + description
} }
return description; return description;
} }

View File

@@ -80,7 +80,7 @@ export function createAnchorMarker(lat: number, lon: number, index: number,
onDragStart: (event: Event) => void, onDragEnd: (event: Event) => void): FontawesomeMarker { onDragStart: (event: Event) => void, onDragEnd: (event: Event) => void): FontawesomeMarker {
const anchorElement = document.createElement("span") const anchorElement = document.createElement("span")
anchorElement.className = "route-anchor cursor-pointer rounded-full w-6 h-6 border border-black text-center bg-background-inverse text-content-inverse" anchorElement.className = "route-anchor cursor-pointer rounded-full w-6 h-6 border border-black text-center bg-primary text-white"
anchorElement.textContent = "" + index anchorElement.textContent = "" + index
const marker = new M.Marker( const marker = new M.Marker(
{ {

View File

@@ -73,6 +73,8 @@ export class ElevationProfileControl implements IControl {
} }
toggleTheme(options: ElevationProfileControlOptions) { toggleTheme(options: ElevationProfileControlOptions) {
console.log(options);
this.settings = { ...this.settings, ...options }; this.settings = { ...this.settings, ...options };
this.elevationProfileChart?.toggleTheme(this.settings) this.elevationProfileChart?.toggleTheme(this.settings)
} }

View File

@@ -59,7 +59,7 @@
</script> </script>
<div <div
class="grid grid-cols-1 md:grid-cols-[356px_minmax(0,_1fr)] gap-6 max-w-6xl mx-auto items-start" class="grid grid-cols-1 md:grid-cols-[356px_minmax(0,_1fr)] gap-6 max-w-6xl mx-4 md:mx-auto items-start"
> >
<div class="border border-input-border rounded-xl md:sticky top-8 md:ml-6"> <div class="border border-input-border rounded-xl md:sticky top-8 md:ml-6">
{#if data.user} {#if data.user}