finishes profile page

This commit is contained in:
Christian Beutel
2024-11-05 00:47:47 +01:00
parent bab22301af
commit 87eb879c7f
20 changed files with 541 additions and 187 deletions

View File

@@ -2,7 +2,7 @@
import type { SummitLog } from "$lib/models/summit_log"; import type { SummitLog } from "$lib/models/summit_log";
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import { isSameDay, isToday } from "../../util/date_util"; import { isSameDay, isToday } from "../../util/date_util";
import { _ } from "svelte-i18n";
export let logs: SummitLog[] = []; export let logs: SummitLog[] = [];
export let colorMap: Record<string, string> = {}; export let colorMap: Record<string, string> = {};
@@ -15,6 +15,7 @@
start: Date; start: Date;
end: Date; end: Date;
}; };
click: Date;
}>(); }>();
const weekdays = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]; const weekdays = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
@@ -74,9 +75,11 @@
i + 1 - firstDay, i + 1 - firstDay,
); );
const today = isToday(date); const today = isToday(date);
const logAtDate = logs.find((l) => const logAtDate = logs.find((l) =>
isSameDay(date, new Date(l.date)), isSameDay(date, new Date(l.date)),
); );
a.push({ date: date, today: today, log: logAtDate }); a.push({ date: date, today: today, log: logAtDate });
} }
} }
@@ -108,6 +111,21 @@
end: new Date(currentYear, currentMonth + 1, 0), end: new Date(currentYear, currentMonth + 1, 0),
}); });
} }
function colorKey(i: number) {
return $_(
currentMonthArray[i]?.log?.expand.trails_via_summit_logs?.at(0)
?.expand?.category?.name ?? "",
);
}
function handleDateClick(date?: Date) {
if (!date) {
return;
}
dispatch("click", date);
}
</script> </script>
<div class="calendar-header w-full flex items-center justify-between mb-6"> <div class="calendar-header w-full flex items-center justify-between mb-6">
@@ -134,18 +152,14 @@
</div> </div>
<div class="grid grid-cols-7 grid-rows-6" style="aspect-ratio: 1.17/1"> <div class="grid grid-cols-7 grid-rows-6" style="aspect-ratio: 1.17/1">
{#each { length: 42 } as _, i} {#each { length: 42 } as _, i}
<div <button
class="calendar-day flex items-center justify-center rounded-xl cursor-pointer" class="calendar-day flex items-center justify-center rounded-xl"
on:click={() => handleDateClick(currentMonthArray[i]?.date)}
class:today={currentMonthArray[i]?.today} class:today={currentMonthArray[i]?.today}
style="background-color: {colorMap[ style="background-color: {colorMap[colorKey(i)] ?? ''}"
currentMonthArray[
i
]?.log?.expand.trails_via_summit_logs?.at(0)?.expand
?.category?.name ?? ''
] ?? ''}"
> >
{currentMonthArray[i]?.date?.getDate() ?? ""} {currentMonthArray[i]?.date?.getDate() ?? ""}
</div> </button>
{/each} {/each}
</div> </div>
</div> </div>

View File

@@ -0,0 +1,83 @@
<script lang="ts">
import { writable } from "svelte/store";
import type { SelectItem } from "./select.svelte";
import { createEventDispatcher } from "svelte";
export let items: SelectItem[] = [];
export let value: SelectItem[] = [];
export let label: string = "";
export let name: string = "";
export let placeholder: string = "";
let showDropdown = false;
let dropdownRef;
const dispatch = createEventDispatcher();
function toggleItem(item: SelectItem) {
if (value.includes(item)) {
value = value.filter((i) => i !== item);
} else {
value = [...value, item];
}
dispatch("change", value);
}
function removeItem(item: SelectItem) {
value = value.filter((i) => i !== item);
dispatch("change", value);
}
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="relative max-w-full">
{#if label.length}
<label for={name} class="text-sm font-medium pb-1 block">
{label}
</label>
{/if}
<button
class="min-w-44 flex flex-wrap items-center gap-2 border bg-input-background min-h-[50px] p-3 rounded-md transition-colors focus:border-input-border-focus focus:outline-none focus:ring-0"
on:click={() => (showDropdown = !showDropdown)}
>
{#if value.length === 0}
<span class="text-gray-400">{placeholder}</span>
{/if}
{#each value as item}
<div
class="bg-primary text-white px-2 py-1 rounded-full flex items-center gap-1"
>
<span class="text-sm">{item.text}</span>
<button
on:click|stopPropagation={() => removeItem(item)}
class="text-white hover:bg-primary-hover rounded-full w-4 h-4 flex items-center justify-center"
>
<i class="fa fa-close"></i>
</button>
</div>
{/each}
</button>
<!-- Dropdown menu -->
{#if showDropdown}
<div
bind:this={dropdownRef}
class="absolute z-10 mt-1 w-full bg-white border border-gray-300 rounded shadow-lg max-h-40 overflow-y-auto"
>
{#each items as item}
<button
on:click={() => toggleItem(item)}
class="px-3 py-2 hover:bg-blue-100 cursor-pointer flex justify-between items-center w-full"
>
<span>{item.text}</span>
{#if value.includes(item)}
<div class="ml-auto">
<i class="fa fa-check"></i>
</div>
{/if}
</button>
{/each}
</div>
{/if}
</div>

View File

@@ -5,24 +5,28 @@
import Modal from "../base/modal.svelte"; import Modal from "../base/modal.svelte";
import SummitLogTableRow from "./summit_log_table_row.svelte"; import SummitLogTableRow from "./summit_log_table_row.svelte";
import type { Map } from "leaflet";
import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";
import { endIcon, startIcon } from "$lib/util/leaflet_util";
import { _ } from "svelte-i18n";
import MapWithElevation from "../trail/map_with_elevation.svelte";
import type { Trail } from "$lib/models/trail"; import type { Trail } from "$lib/models/trail";
import { gpx2trail } from "$lib/util/gpx_util"; import { gpx2trail } from "$lib/util/gpx_util";
import type { Map } from "leaflet";
import { _ } from "svelte-i18n";
import MapWithElevation from "../trail/map_with_elevation.svelte";
export let summitLogs: SummitLog[]; export let summitLogs: SummitLog[];
export let showCategory: boolean = false; export let showCategory: boolean = false;
export let showTrail: boolean = false;
let openModal: () => void; let openMapModal: () => void;
let closeModal: () => void; let closeMapModal: () => void;
let openTextModal: () => void;
let closeTextModal: () => void;
let map: Map; let map: Map;
let trail: Trail | null = null; let trail: Trail | null = null;
let currentText: string = "";
onMount(async () => { onMount(async () => {
// L = (await import("leaflet")).default; // L = (await import("leaflet")).default;
// map = L.map("summit-log-table-map"); // map = L.map("summit-log-table-map");
@@ -42,12 +46,17 @@
trail = (await gpx2trail(log.expand.gpx_data)).trail; trail = (await gpx2trail(log.expand.gpx_data)).trail;
trail.expand.gpx_data = log.expand.gpx_data; trail.expand.gpx_data = log.expand.gpx_data;
openModal(); openMapModal();
await tick(); await tick();
map.invalidateSize(); map.invalidateSize();
return; return;
} }
async function openText(log: SummitLog) {
currentText = log.text ?? "";
openTextModal();
}
</script> </script>
<table class="w-full"> <table class="w-full">
@@ -64,7 +73,12 @@
{$_("category")} {$_("category")}
</th> </th>
{/if} {/if}
<th></th> {#if showTrail}
<th>
{$_("trail", { values: { n: 1 } })}
</th>
{/if}
<th>{$_("description")}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -72,24 +86,37 @@
<SummitLogTableRow <SummitLogTableRow
index={i} index={i}
{log} {log}
on:open={() => openMap(log)} on:open={(e) => openMap(e.detail)}
on:text={(e) => openText(e.detail)}
{showCategory} {showCategory}
{showTrail}
></SummitLogTableRow> ></SummitLogTableRow>
{/each} {/each}
</tbody> </tbody>
</table> </table>
{#if !summitLogs.length}
<p class="text-center w-full my-8 text-gray-500 text-sm">{$_("no-data")}</p>
{/if}
<Modal <Modal
id="summit-log-table-modal" id="summit-log-table-map-modal"
size="max-w-4xl" size="max-w-4xl"
title="" title=""
bind:openModal bind:openModal={openMapModal}
bind:closeModal bind:closeModal={closeMapModal}
> >
<div slot="content" id="summit-log-table-map" class="h-[32rem]"> <div slot="content" id="summit-log-table-map" class="h-[32rem]">
<MapWithElevation {trail} bind:map></MapWithElevation> <MapWithElevation {trail} bind:map></MapWithElevation>
</div> </div>
</Modal> </Modal>
<Modal
id="summit-log-table-text-modal"
size="max-w-xl"
title={$_("description")}
bind:openModal={openTextModal}
bind:closeModal={closeTextModal}
>
<p slot="content" class="whitespace-pre-wrap">{currentText}</p>
</Modal>
<style> <style>
th { th {

View File

@@ -15,11 +15,10 @@
export let index: number; export let index: number;
export let log: SummitLog; export let log: SummitLog;
export let showCategory: boolean = false; export let showCategory: boolean = false;
export let showTrail: boolean = false;
let map: Map; let map: Map;
let showText: boolean = false;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
onMount(async () => { onMount(async () => {
@@ -59,6 +58,20 @@
function openMap() { function openMap() {
dispatch("open", log); dispatch("open", log);
} }
function openText() {
dispatch("text", log);
}
function colCount() {
if (showCategory && showTrail) {
return 9;
} else if (showCategory || showTrail) {
return 8;
}
return 7;
}
</script> </script>
<tr class="text-center"> <tr class="text-center">
@@ -100,23 +113,24 @@
)} )}
</td> </td>
{/if} {/if}
{#if showTrail}
<td>
<a
class="btn-icon aspect-square"
href="/trail/view/{log.expand.trails_via_summit_logs?.at(0)
?.id ?? ''}"
><i class="fa fa-arrow-up-right-from-square px-[3px]"></i></a
>
</td>
{/if}
<td> <td>
{#if log.text} {#if log.text}
<button on:click={() => (showText = !showText)} class="btn-icon" <button on:click={openText} class="btn-icon"
><i class="fa{showText ? '' : '-regular'} fa-message text-gray-500" ><i class="fa-regular fa-message"></i></button
></i></button
> >
{/if} {/if}
</td> </td>
</tr> </tr>
{#if showText}
<tr
><td
class="text-left text-sm whitespace-pre-wrap pb-4"
colspan={showCategory ? 8 : 7}>{log.text}</td
></tr
>
{/if}
<tr> <tr>
<td colspan={showCategory ? 8 : 7}> <hr class="border-input-border" /> </td> <td colspan={colCount()}> <hr class="border-input-border" /> </td>
</tr> </tr>

View File

@@ -243,13 +243,13 @@
<div class="space-y-2"> <div class="space-y-2">
<Datepicker <Datepicker
name="startDate" name="startDate"
label="After" label={$_('after')}
bind:value={filter.startDate} bind:value={filter.startDate}
on:change={update} on:change={update}
></Datepicker> ></Datepicker>
<Datepicker <Datepicker
name="endDate" name="endDate"
label="Before" label={$_('before')}
bind:value={filter.endDate} bind:value={filter.endDate}
on:change={update} on:change={update}
></Datepicker> ></Datepicker>

View File

@@ -7,18 +7,21 @@
"Walking": "Laufen", "Walking": "Laufen",
"about": "Über", "about": "Über",
"account-delete-confirm": "Du bist dabei, dein Konto zu löschen. Alle deine Routen werden ebenfalls gelöscht. Möchtest du fortfahren?", "account-delete-confirm": "Du bist dabei, dein Konto zu löschen. Alle deine Routen werden ebenfalls gelöscht. Möchtest du fortfahren?",
"activity": "", "activity": "{n, plural, =1 {Aktivität} other {Aktivitäten}}",
"add-entry": "Eintrag hinzufügen", "add-entry": "Eintrag hinzufügen",
"add-to-list": "Zu Liste hinzufügen", "add-to-list": "Zu Liste hinzufügen",
"add-waypoint": "Wegpunkt hinzufügen", "add-waypoint": "Wegpunkt hinzufügen",
"added-trail-to": "Route hinzugefügt zu", "added-trail-to": "Route hinzugefügt zu",
"all-activities": "", "after": "Nach",
"all-activities": "Alle Aktivitäten",
"alphabetical": "Alphabetisch", "alphabetical": "Alphabetisch",
"already-account": "Du hast bereits ein Konto?", "already-account": "Du hast bereits ein Konto?",
"altitude": "Höhe", "altitude": "Höhe",
"api-documentation": "API Dokumentation", "api-documentation": "API Dokumentation",
"avatar": "Avatar", "avatar": "Avatar",
"average-speed": "Durschn. Geschwindigkeit",
"basic-info": "Basisinformation", "basic-info": "Basisinformation",
"before": "Vor",
"can": "kann", "can": "kann",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"card": "{n, plural, =1 {Karte} other {Karten}}", "card": "{n, plural, =1 {Karte} other {Karten}}",
@@ -33,9 +36,9 @@
"comment": "{n, plural, =1 {Kommentar} other {Kommentare}}", "comment": "{n, plural, =1 {Kommentar} other {Kommentare}}",
"completed": "Abgeschlossen", "completed": "Abgeschlossen",
"completion-status": "Abschlussstatus", "completion-status": "Abschlussstatus",
"confirm": "", "confirm": "Bestätigen",
"confirm-deletion": "", "confirm-deletion": "Löschen bestätigen",
"confirm-share": "", "confirm-share": "Teilen bestätigen",
"contribute": "Mitwirken", "contribute": "Mitwirken",
"copy-link": "Link kopieren", "copy-link": "Link kopieren",
"create-new-list": "Neue Liste erstellen", "create-new-list": "Neue Liste erstellen",
@@ -61,15 +64,15 @@
"documentation": "Dokumentation", "documentation": "Dokumentation",
"draw-a-route": "Route zeichnen", "draw-a-route": "Route zeichnen",
"driving": "Auto", "driving": "Auto",
"duration": "", "duration": "Dauer",
"dutch": "Niederländisch", "dutch": "Niederländisch",
"easy": "Einfach", "easy": "Einfach",
"edit": "Bearbeiten", "edit": "Bearbeiten",
"edit-entry": "Eintrag bearbeiten", "edit-entry": "Eintrag bearbeiten",
"edit-list": "Liste bearbeiten", "edit-list": "Liste bearbeiten",
"edit-waypoint": "Wegpunkt bearbeiten", "edit-waypoint": "Wegpunkt bearbeiten",
"elevation-gain": "Höhenunterschied", "elevation-gain": "Höhenunterschied (aufw.)",
"elevation-loss": "", "elevation-loss": "Höhenunterschied (abw.)",
"email": "Email", "email": "Email",
"english": "Englisch", "english": "Englisch",
"entry": "Eintrag", "entry": "Eintrag",
@@ -78,8 +81,8 @@
"error-exporting-trail": "Fehler beim Exportieren des Trails", "error-exporting-trail": "Fehler beim Exportieren des Trails",
"error-printing-map": "Fehler beim Drucken der Karte", "error-printing-map": "Fehler beim Drucken der Karte",
"error-reading-file": "Fehler beim Lesen der Datei", "error-reading-file": "Fehler beim Lesen der Datei",
"error-saving-list": "", "error-saving-list": "Fehler beim Speichern der Liste",
"error-saving-trail": "Fehler bei Speichern der Route", "error-saving-trail": "Fehler beim Speichern der Route",
"error-updating-password": "Fehler beim Aktualisieren des Passworts", "error-updating-password": "Fehler beim Aktualisieren des Passworts",
"est-duration": "Gesch. Dauer", "est-duration": "Gesch. Dauer",
"explore": "Erkunden", "explore": "Erkunden",
@@ -88,6 +91,7 @@
"export-all-trails": "Alle Routen exportieren", "export-all-trails": "Alle Routen exportieren",
"features": "Features", "features": "Features",
"file-format": "Dateiformat", "file-format": "Dateiformat",
"filter-categories": "Kategorien filtern",
"focus-map-on": "Karte fokussieren auf", "focus-map-on": "Karte fokussieren auf",
"french": "Französisch", "french": "Französisch",
"german": "Deutsch", "german": "Deutsch",
@@ -114,10 +118,10 @@
"license": "Lizenz", "license": "Lizenz",
"link-copied": "Link kopiert", "link-copied": "Link kopiert",
"list": "{n, plural, =1 {Liste} other {Listen}}", "list": "{n, plural, =1 {Liste} other {Listen}}",
"list-not-shared": "", "list-not-shared": "Mit niemandem geteilt",
"list-saved-successfully": "", "list-saved-successfully": "Liste gespeichert",
"list-share-warning": "", "list-share-warning": "Durch das Teilen einer Liste werden automatisch alle darin enthaltenen Routen freigegeben.",
"list-share-warning-update": "", "list-share-warning-update": "Hinzugefügte Routen werden mit allen geteilt, die Zugriff auf diese Liste haben.",
"location": "Standort", "location": "Standort",
"login": "Login", "login": "Login",
"login-details": "Login Details", "login-details": "Login Details",
@@ -142,6 +146,7 @@
"new-password": "Neues Passwort", "new-password": "Neues Passwort",
"new-trail": "Neue Route", "new-trail": "Neue Route",
"no-account": "Du hast noch kein Konto?", "no-account": "Du hast noch kein Konto?",
"no-data": "Keine Daten",
"no-preference": "Keine Präferenz", "no-preference": "Keine Präferenz",
"no-results": "Keine Ergebnisse gefunden", "no-results": "Keine Ergebnisse gefunden",
"not-a-valid-email-address": "Keine gültige Email-Adresse", "not-a-valid-email-address": "Keine gültige Email-Adresse",
@@ -160,12 +165,12 @@
"profile": "Profil", "profile": "Profil",
"public": "Öffentlich", "public": "Öffentlich",
"radius": "Radius", "radius": "Radius",
"read-more": "", "read-more": "Mehr Info",
"register": "Registrieren", "register": "Registrieren",
"removed-trail-from": "Route entfernt aus", "removed-trail-from": "Route entfernt aus",
"required": "Pflichtfeld", "required": "Pflichtfeld",
"save": "Speichern", "save": "Speichern",
"save-list": "", "save-list": "Liste speichern",
"save-trail": "Route speichern", "save-trail": "Route speichern",
"save-your-trail-first": "Route zuerst speichern", "save-your-trail-first": "Route zuerst speichern",
"search-cities": "Städte suchen", "search-cities": "Städte suchen",
@@ -174,7 +179,7 @@
"select-list": "Liste auswählen", "select-list": "Liste auswählen",
"settings": "Einstellungen", "settings": "Einstellungen",
"share": "Teilen", "share": "Teilen",
"share-this-list": "", "share-this-list": "Diese Liste teilen",
"share-this-trail": "Diese Route teilen", "share-this-trail": "Diese Route teilen",
"shared-by": "Geteilt von", "shared-by": "Geteilt von",
"shared-with": "Geteilt mit", "shared-with": "Geteilt mit",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Add to list", "add-to-list": "Add to list",
"add-waypoint": "Add Waypoint", "add-waypoint": "Add Waypoint",
"added-trail-to": "Added trail to", "added-trail-to": "Added trail to",
"after": "After",
"all-activities": "All activities", "all-activities": "All activities",
"alphabetical": "Alphabetical", "alphabetical": "Alphabetical",
"already-account": "Already have an account?", "already-account": "Already have an account?",
"altitude": "Altitude", "altitude": "Altitude",
"api-documentation": "API Documentation", "api-documentation": "API Documentation",
"avatar": "Avatar", "avatar": "Avatar",
"average-speed": "Avg. Speed",
"basic-info": "Basic Info", "basic-info": "Basic Info",
"before": "Before",
"can": "can", "can": "can",
"cancel": "Cancel", "cancel": "Cancel",
"card": "{n, plural, =1 {Card} other {Cards}}", "card": "{n, plural, =1 {Card} other {Cards}}",
@@ -88,6 +91,7 @@
"export-all-trails": "Export all trails", "export-all-trails": "Export all trails",
"features": "Features", "features": "Features",
"file-format": "File format", "file-format": "File format",
"filter-categories": "Filter categories",
"focus-map-on": "Focus map on", "focus-map-on": "Focus map on",
"french": "French", "french": "French",
"german": "German", "german": "German",
@@ -142,6 +146,7 @@
"new-password": "New password", "new-password": "New password",
"new-trail": "New Trail", "new-trail": "New Trail",
"no-account": "Don't have an account?", "no-account": "Don't have an account?",
"no-data": "No data",
"no-preference": "No preference", "no-preference": "No preference",
"no-results": "No results found", "no-results": "No results found",
"not-a-valid-email-address": "Not a valid email address", "not-a-valid-email-address": "Not a valid email address",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Ajouter à une liste", "add-to-list": "Ajouter à une liste",
"add-waypoint": "Ajouter un point de repère", "add-waypoint": "Ajouter un point de repère",
"added-trail-to": "Ajouter un itinéraire à", "added-trail-to": "Ajouter un itinéraire à",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "Alphabétique", "alphabetical": "Alphabétique",
"already-account": "Déjà un compte ?", "already-account": "Déjà un compte ?",
"altitude": "Altitude", "altitude": "Altitude",
"api-documentation": "Documentation API", "api-documentation": "Documentation API",
"avatar": "Avatar", "avatar": "Avatar",
"average-speed": "",
"basic-info": "Informations de base", "basic-info": "Informations de base",
"before": "",
"can": "", "can": "",
"cancel": "Annuler", "cancel": "Annuler",
"card": "{n, plural, =1 {Carte} other {Cartes}}", "card": "{n, plural, =1 {Carte} other {Cartes}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "Fonctionnalités", "features": "Fonctionnalités",
"file-format": "", "file-format": "",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "Français", "french": "Français",
"german": "Allemand", "german": "Allemand",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "Nouvel itinéraire", "new-trail": "Nouvel itinéraire",
"no-account": "Pas encore de compte ?", "no-account": "Pas encore de compte ?",
"no-data": "",
"no-preference": "Pas de préférence", "no-preference": "Pas de préférence",
"no-results": "Pas de résultat", "no-results": "Pas de résultat",
"not-a-valid-email-address": "Adresse email invalide", "not-a-valid-email-address": "Adresse email invalide",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Hozzáadás a listához", "add-to-list": "Hozzáadás a listához",
"add-waypoint": "Útvonalpont hozzáadása", "add-waypoint": "Útvonalpont hozzáadása",
"added-trail-to": "Hozzáadott nyomvonal a", "added-trail-to": "Hozzáadott nyomvonal a",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "Betűrendben", "alphabetical": "Betűrendben",
"already-account": "Már rendelkezik fiókkal?", "already-account": "Már rendelkezik fiókkal?",
"altitude": "Magasság", "altitude": "Magasság",
"api-documentation": "API Dokumentáció", "api-documentation": "API Dokumentáció",
"avatar": "Avatar", "avatar": "Avatar",
"average-speed": "",
"basic-info": "Alap információk", "basic-info": "Alap információk",
"before": "",
"can": "", "can": "",
"cancel": "Mégsem", "cancel": "Mégsem",
"card": "{n, plural, =1 {Kártya} other {Kártyák}}", "card": "{n, plural, =1 {Kártya} other {Kártyák}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "Jellemzők", "features": "Jellemzők",
"file-format": "", "file-format": "",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "Francia", "french": "Francia",
"german": "Német", "german": "Német",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "Új útvonal", "new-trail": "Új útvonal",
"no-account": "Nincs még fiókja?", "no-account": "Nincs még fiókja?",
"no-data": "",
"no-preference": "Nincs preferált", "no-preference": "Nincs preferált",
"no-results": "Nincs eredmény", "no-results": "Nincs eredmény",
"not-a-valid-email-address": "Érvénytelen e-mail cím", "not-a-valid-email-address": "Érvénytelen e-mail cím",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Aggiungi alla lista", "add-to-list": "Aggiungi alla lista",
"add-waypoint": "Aggiungere un waypoint", "add-waypoint": "Aggiungere un waypoint",
"added-trail-to": "Percorso aggiunto a", "added-trail-to": "Percorso aggiunto a",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "Alfabetico", "alphabetical": "Alfabetico",
"already-account": "Hai già un account?", "already-account": "Hai già un account?",
"altitude": "Altitudine", "altitude": "Altitudine",
"api-documentation": "Documentazione API", "api-documentation": "Documentazione API",
"avatar": "Avatar", "avatar": "Avatar",
"average-speed": "",
"basic-info": "Informazioni di base", "basic-info": "Informazioni di base",
"before": "",
"can": "può", "can": "può",
"cancel": "Annulla", "cancel": "Annulla",
"card": "{n, plural, =1 {Carta} other {Carte}}", "card": "{n, plural, =1 {Carta} other {Carte}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "Caratteristiche", "features": "Caratteristiche",
"file-format": "Formato del file", "file-format": "Formato del file",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "Francese", "french": "Francese",
"german": "Tedesco", "german": "Tedesco",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "Nuovo percorso", "new-trail": "Nuovo percorso",
"no-account": "Non hai ancora un account?", "no-account": "Non hai ancora un account?",
"no-data": "",
"no-preference": "Nessuna preferenza", "no-preference": "Nessuna preferenza",
"no-results": "Nessun risultato trovato", "no-results": "Nessun risultato trovato",
"not-a-valid-email-address": "Indirizzo email non valido", "not-a-valid-email-address": "Indirizzo email non valido",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Toevoegen aan lijst", "add-to-list": "Toevoegen aan lijst",
"add-waypoint": "Routepunt toevoegen", "add-waypoint": "Routepunt toevoegen",
"added-trail-to": "Wandelroute toegevoegd aan", "added-trail-to": "Wandelroute toegevoegd aan",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "Alfabetisch", "alphabetical": "Alfabetisch",
"already-account": "Heb je al een account?", "already-account": "Heb je al een account?",
"altitude": "Hoogte", "altitude": "Hoogte",
"api-documentation": "API-documentatie", "api-documentation": "API-documentatie",
"avatar": "Profielfoto", "avatar": "Profielfoto",
"average-speed": "",
"basic-info": "Algemene informatie", "basic-info": "Algemene informatie",
"before": "",
"can": "", "can": "",
"cancel": "Annuleren", "cancel": "Annuleren",
"card": "{n, plural, =1 {kaart} other {kaarten}}", "card": "{n, plural, =1 {kaart} other {kaarten}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "Kenmerken", "features": "Kenmerken",
"file-format": "", "file-format": "",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "Frans", "french": "Frans",
"german": "Duits", "german": "Duits",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "Nieuwe wandelroute", "new-trail": "Nieuwe wandelroute",
"no-account": "Heb je nog geen account?", "no-account": "Heb je nog geen account?",
"no-data": "",
"no-preference": "Geen voorkeur", "no-preference": "Geen voorkeur",
"no-results": "Er zijn geen zoekresultaten", "no-results": "Er zijn geen zoekresultaten",
"not-a-valid-email-address": "Het e-mailadres is ongeldig", "not-a-valid-email-address": "Het e-mailadres is ongeldig",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Dodaj do listy", "add-to-list": "Dodaj do listy",
"add-waypoint": "Dodaj Punkt", "add-waypoint": "Dodaj Punkt",
"added-trail-to": "Dodaj ścieżkę do", "added-trail-to": "Dodaj ścieżkę do",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "Alfabetyczne", "alphabetical": "Alfabetyczne",
"already-account": "Czy masz już konto?", "already-account": "Czy masz już konto?",
"altitude": "Wysokość", "altitude": "Wysokość",
"api-documentation": "Dokumentacja API", "api-documentation": "Dokumentacja API",
"avatar": "Awatar", "avatar": "Awatar",
"average-speed": "",
"basic-info": "Podstawowe informacje", "basic-info": "Podstawowe informacje",
"before": "",
"can": "", "can": "",
"cancel": "Anuluj", "cancel": "Anuluj",
"card": "{n, plural, =1 {Karta} other {Karty}}", "card": "{n, plural, =1 {Karta} other {Karty}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "Funkcje", "features": "Funkcje",
"file-format": "", "file-format": "",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "Francuski", "french": "Francuski",
"german": "Niemiecki", "german": "Niemiecki",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "Nowa ścieżka", "new-trail": "Nowa ścieżka",
"no-account": "Nie masz konta?", "no-account": "Nie masz konta?",
"no-data": "",
"no-preference": "Brak preferencji", "no-preference": "Brak preferencji",
"no-results": "Brak wyników", "no-results": "Brak wyników",
"not-a-valid-email-address": "Nieprawidłowy adres email", "not-a-valid-email-address": "Nieprawidłowy adres email",

View File

@@ -12,13 +12,16 @@
"add-to-list": "Adicionar à lista", "add-to-list": "Adicionar à lista",
"add-waypoint": "Adicionar ponto de vista", "add-waypoint": "Adicionar ponto de vista",
"added-trail-to": "Trilha adicionada para", "added-trail-to": "Trilha adicionada para",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "Alfabético", "alphabetical": "Alfabético",
"already-account": "Já tem uma conta?", "already-account": "Já tem uma conta?",
"altitude": "Altitude", "altitude": "Altitude",
"api-documentation": "Documentação da API", "api-documentation": "Documentação da API",
"avatar": "Avatar", "avatar": "Avatar",
"average-speed": "",
"basic-info": "Informações básicas", "basic-info": "Informações básicas",
"before": "",
"can": "", "can": "",
"cancel": "Cancelar", "cancel": "Cancelar",
"card": "{n, plural, =1 {Cartão} other {cartãos}}", "card": "{n, plural, =1 {Cartão} other {cartãos}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "Características", "features": "Características",
"file-format": "", "file-format": "",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "Francês", "french": "Francês",
"german": "Alemão", "german": "Alemão",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "Nova trilha", "new-trail": "Nova trilha",
"no-account": "Não tem uma conta?", "no-account": "Não tem uma conta?",
"no-data": "",
"no-preference": "Nenhuma preferência", "no-preference": "Nenhuma preferência",
"no-results": "Nenhum resultado encontrado", "no-results": "Nenhum resultado encontrado",
"not-a-valid-email-address": "Não um endereço de e-mail válido", "not-a-valid-email-address": "Não um endereço de e-mail válido",

View File

@@ -12,13 +12,16 @@
"add-to-list": "添加到列表", "add-to-list": "添加到列表",
"add-waypoint": "添加坐标", "add-waypoint": "添加坐标",
"added-trail-to": "添加路线到", "added-trail-to": "添加路线到",
"after": "",
"all-activities": "", "all-activities": "",
"alphabetical": "字母", "alphabetical": "字母",
"already-account": "已注册账户?", "already-account": "已注册账户?",
"altitude": "海拔", "altitude": "海拔",
"api-documentation": "API 文档", "api-documentation": "API 文档",
"avatar": "头像", "avatar": "头像",
"average-speed": "",
"basic-info": "基本信息", "basic-info": "基本信息",
"before": "",
"can": "", "can": "",
"cancel": "取消", "cancel": "取消",
"card": "{n, plural, =1 {卡片} other {卡片}}", "card": "{n, plural, =1 {卡片} other {卡片}}",
@@ -88,6 +91,7 @@
"export-all-trails": "", "export-all-trails": "",
"features": "特性", "features": "特性",
"file-format": "", "file-format": "",
"filter-categories": "",
"focus-map-on": "", "focus-map-on": "",
"french": "法语", "french": "法语",
"german": "德语", "german": "德语",
@@ -142,6 +146,7 @@
"new-password": "", "new-password": "",
"new-trail": "创建新路线", "new-trail": "创建新路线",
"no-account": "还未注册?", "no-account": "还未注册?",
"no-data": "",
"no-preference": "尚未规划", "no-preference": "尚未规划",
"no-results": "没有找到结果", "no-results": "没有找到结果",
"not-a-valid-email-address": "无效电子邮箱地址", "not-a-valid-email-address": "无效电子邮箱地址",

View File

@@ -26,5 +26,10 @@ class SummitLog {
} }
} }
interface SummitLogFilter {
category: string[],
startDate?: string;
endDate?: string;
}
export { SummitLog }; export { SummitLog, type SummitLogFilter };

View File

@@ -1,13 +1,18 @@
import { SummitLog } from "$lib/models/summit_log"; import { SummitLog, type SummitLogFilter } from "$lib/models/summit_log";
import { pb } from "$lib/pocketbase"; import { pb } from "$lib/pocketbase";
import { ClientResponseError } from "pocketbase"; import { ClientResponseError } from "pocketbase";
import { writable, type Writable } from "svelte/store"; import { writable, type Writable } from "svelte/store";
import { fetchGPX } from "./trail_store";
export const summitLog: Writable<SummitLog> = writable(new SummitLog(new Date().toISOString().substring(0, 10))); export const summitLog: Writable<SummitLog> = writable(new SummitLog(new Date().toISOString().substring(0, 10)));
export const summitLogs: Writable<SummitLog[]> = writable([]); export const summitLogs: Writable<SummitLog[]> = writable([]);
export async function summit_logs_index(f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) { export async function summit_logs_index(filter?: SummitLogFilter, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f('/api/v1/summit-log?', { const filterText = filter ? buildFilterText(filter) : "";
const r = await f('/api/v1/summit-log?' + new URLSearchParams({
filter: filterText,
}), {
method: 'GET', method: 'GET',
}) })
@@ -17,6 +22,18 @@ export async function summit_logs_index(f: (url: RequestInfo | URL, config?: Req
const fetchedSummitLogs: SummitLog[] = await r.json(); const fetchedSummitLogs: SummitLog[] = await r.json();
for (const log of fetchedSummitLogs) {
if (!log.gpx) {
continue
}
const gpxData: string = await fetchGPX(log as any, f);
if (!log.expand) {
log.expand = {};
}
log.expand.gpx_data = gpxData;
}
summitLogs.set(fetchedSummitLogs); summitLogs.set(fetchedSummitLogs);
return fetchedSummitLogs; return fetchedSummitLogs;
@@ -95,3 +112,22 @@ export async function summit_logs_delete(summitLog: SummitLog) {
throw new ClientResponseError(await r.json()) throw new ClientResponseError(await r.json())
} }
} }
function buildFilterText(filter: SummitLogFilter,): string {
let filterText: string = "";
if (filter.category.length > 0) {
filterText += `trails_via_summit_logs.category != null && '${filter.category.join(",")}' ~ trails_via_summit_logs.category`;
}
if (filter.startDate) {
filterText += `${filter.category.length ? ' && ' : ''}date >= '${filter.startDate}'`
}
if (filter.endDate) {
filterText += `${filter.category.length || filter.startDate ? ' && ' : ''} date <= '${filter.endDate}'`
}
return filterText;
}

View File

@@ -50,6 +50,22 @@ export function formatElevation(meters?: number) {
} }
} }
export function formatSpeed(speed?: number) {
if (speed === undefined) {
return "-";
}
const unit = get(page).data.settings?.unit ?? "metric";
if (unit == "metric") {
return `${Math.round(speed)} km/h`
} else {
const mph = speed * 0.621371;
return `${Math.round(mph)} mp/h`;
}
}
export function formatTimeSince(date: Date) { export function formatTimeSince(date: Date) {
var seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000); var seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000);

View File

@@ -3,10 +3,13 @@ import { pb } from '$lib/pocketbase';
import { error, json, type RequestEvent } from '@sveltejs/kit'; import { error, json, type RequestEvent } from '@sveltejs/kit';
export async function GET(event: RequestEvent) { export async function GET(event: RequestEvent) {
const filter = event.url.searchParams.get('filter') ?? ""
try { try {
const r: SummitLog[] = await pb.collection('summit_logs').getFullList<SummitLog>({ const r: SummitLog[] = await pb.collection('summit_logs').getFullList<SummitLog>({
expand: "trails_via_summit_logs.category", expand: "trails_via_summit_logs.category",
sort: "+date" sort: "+date",
filter: filter
}) })
return json(r) return json(r)
} catch (e: any) { } catch (e: any) {

View File

@@ -1,15 +1,23 @@
<script lang="ts"> <script lang="ts">
import { page } from "$app/stores";
import Calendar from "$lib/components/base/calendar.svelte"; import Calendar from "$lib/components/base/calendar.svelte";
import Datepicker from "$lib/components/base/datepicker.svelte";
import MultiSelect from "$lib/components/base/multi_select.svelte";
import Select, { import Select, {
type SelectItem, type SelectItem,
} from "$lib/components/base/select.svelte"; } from "$lib/components/base/select.svelte";
import SummitLogTable from "$lib/components/summit_log/summit_log_table.svelte"; import SummitLogTable from "$lib/components/summit_log/summit_log_table.svelte";
import { summitLogs } from "$lib/stores/summit_log_store"; import { categories } from "$lib/stores/category_store.js";
import {
summit_logs_index,
summitLogs,
} from "$lib/stores/summit_log_store";
import { currentUser } from "$lib/stores/user_store"; import { currentUser } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util"; import { getFileURL } from "$lib/util/file_util";
import { import {
formatDistance, formatDistance,
formatElevation, formatElevation,
formatSpeed,
formatTimeHHMM, formatTimeHHMM,
} from "$lib/util/format_util"; } from "$lib/util/format_util";
import { import {
@@ -25,6 +33,8 @@
import { Bar, Pie } from "svelte-chartjs"; import { Bar, Pie } from "svelte-chartjs";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
export let data;
ChartJS.register( ChartJS.register(
Title, Title,
Tooltip, Tooltip,
@@ -35,6 +45,13 @@
BarElement, BarElement,
); );
const filter = data.filter;
const categorySelectItems: SelectItem[] = $categories.map((c) => ({
value: c.id,
text: c.name,
}));
const barChartSelectItems: SelectItem[] = [ const barChartSelectItems: SelectItem[] = [
{ {
text: $_("distance"), text: $_("distance"),
@@ -65,7 +82,13 @@
"#ffafcc", "#ffafcc",
]; ];
$: categories = $summitLogs.reduce( const conversionFactors = {
distance: 0.621371,
elevation_gain: 3.28084,
elevation_loss: 3.28084,
};
$: logCategories = $summitLogs.reduce(
(acc, log) => { (acc, log) => {
const cat = const cat =
log.expand.trails_via_summit_logs?.at(0)?.expand.category log.expand.trails_via_summit_logs?.at(0)?.expand.category
@@ -76,8 +99,8 @@
{} as Record<string, number>, {} as Record<string, number>,
); );
$: categoryLabels = Object.keys(categories).sort(); $: categoryLabels = Object.keys(logCategories).sort();
$: categoryValues = Object.values(categories); $: categoryValues = Object.values(logCategories);
$: categoryColorMap = Object.fromEntries( $: categoryColorMap = Object.fromEntries(
categoryLabels.map((label, index) => [ categoryLabels.map((label, index) => [
label, label,
@@ -95,12 +118,19 @@
], ],
}; };
$: barChartUnit = function barChartUnit() {
barChartSelectedValue == "duration" const unit = $page.data.settings?.unit ?? "metric";
? "min"
: barChartSelectedValue == "distance" switch (barChartSelectedValue) {
? "km" case "duration":
: "m"; return "min";
case "elevation_gain":
case "elevation_loss":
return unit == "metric" ? "m" : "ft";
case "distance":
return unit == "metric" ? "km" : "mi";
}
}
$: barChartDataByDate = $summitLogs.reduce( $: barChartDataByDate = $summitLogs.reduce(
(acc, log) => { (acc, log) => {
@@ -115,6 +145,11 @@
if (barChartSelectedValue === "distance") { if (barChartSelectedValue === "distance") {
acc[date] = acc[date] / 1000; acc[date] = acc[date] / 1000;
} }
if ($page.data.settings?.unit !== "metric") {
acc[date] =
acc[date] *
(conversionFactors as any)[barChartSelectedValue];
}
return acc; return acc;
}, },
{} as Record<string, number>, {} as Record<string, number>,
@@ -156,11 +191,60 @@
(sum, log) => sum + (log.elevation_loss ?? 0), (sum, log) => sum + (log.elevation_loss ?? 0),
0, 0,
); );
$: averageSpeed =
totalDuration > 0 ? totalDistance / totalDuration : undefined;
function updateFilterCategory(categories: SelectItem[]) {
filter.category = categories.map((c) => c.value);
loadSummitLogs();
}
function handleDateClick(date: Date) {
const datePlusN = new Date();
datePlusN.setDate(date.getDate() + 1);
filter.startDate = datePlusN.toISOString().slice(0, 10);
datePlusN.setDate(date.getDate() + 2);
filter.endDate = datePlusN.toISOString().slice(0, 10);
loadSummitLogs();
}
async function loadSummitLogs() {
const logs = await summit_logs_index(filter);
summitLogs.set(logs);
}
</script> </script>
<div class="grid grid-cols-5 gap-4 items-start max-w-6xl mx-auto"> <svelte:head>
<title>{$_("profile")} | wanderer</title>
</svelte:head>
<div <div
class="border border-input-border rounded-xl p-6 col-span-2 row-span-2 space-y-6" class="grid grid-cols-1 md:grid-cols-[356px_minmax(0,_1fr)] gap-y-4 items-start max-w-6xl mx-auto"
>
<div
class="flex flex-wrap md:flex-nowrap col-start-1 md:col-start-2 gap-x-4 justify-end"
>
<MultiSelect
on:change={(e) => updateFilterCategory(e.detail)}
label={$_("categories")}
items={categorySelectItems}
placeholder={`${$_("filter-categories")}...`}
></MultiSelect>
<Datepicker
on:change={loadSummitLogs}
bind:value={filter.startDate}
label={$_("after")}
></Datepicker>
<Datepicker
on:change={loadSummitLogs}
bind:value={filter.endDate}
label={$_("before")}
></Datepicker>
</div>
<div
class="border border-input-border rounded-xl p-6 lg:row-span-3 space-y-6 grow-0 md:mr-4"
> >
{#if $currentUser} {#if $currentUser}
<div class="flex items-center gap-x-6"> <div class="flex items-center gap-x-6">
@@ -188,8 +272,13 @@
</div> </div>
</div> </div>
{/if} {/if}
<Calendar logs={$summitLogs} colorMap={categoryColorMap}></Calendar> <Calendar
on:click={(e) => handleDateClick(e.detail)}
logs={$summitLogs}
colorMap={categoryColorMap}
></Calendar>
</div> </div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div <div
class="flex flex-col items-center gap-6 border border-input-border rounded-xl p-6" class="flex flex-col items-center gap-6 border border-input-border rounded-xl p-6"
> >
@@ -225,7 +314,9 @@
"elevation-gain", "elevation-gain",
)}</span )}</span
> >
<p class="text-4xl font-bold">{formatElevation(totalElevationGain)}</p> <p class="text-4xl font-bold">
{formatElevation(totalElevationGain)}
</p>
</div> </div>
<div <div
class="flex flex-col items-center gap-6 border border-input-border rounded-xl p-6" class="flex flex-col items-center gap-6 border border-input-border rounded-xl p-6"
@@ -235,13 +326,27 @@
"elevation-loss", "elevation-loss",
)}</span )}</span
> >
<p class="text-4xl font-bold">{formatElevation(totalElevationLoss)}</p> <p class="text-4xl font-bold">
{formatElevation(totalElevationLoss)}
</p>
</div>
<div
class="flex flex-col items-center gap-6 border border-input-border rounded-xl p-6"
>
<span class="text-gray-500 font-semibold text-lg self-start"
><i class="fa fa-arrow-trend-down mr-3"></i>{$_(
"average-speed",
)}</span
>
<p class="text-4xl font-bold">{formatSpeed(averageSpeed)}</p>
</div> </div>
<div <div
class="col-start-1 col-span-1 border border-input-border rounded-xl p-6 space-y-4" class="col-start-1 col-span-1 border border-input-border rounded-xl p-6 space-y-4"
> >
<span class="text-gray-500 font-semibold text-lg" <span class="text-gray-500 font-semibold text-lg"
><i class="fa fa-person-hiking mr-3"></i>{$_("categories")}</span ><i class="fa fa-person-hiking mr-3"></i>{$_(
"categories",
)}</span
> >
<Pie <Pie
data={categoryChartData} data={categoryChartData}
@@ -256,7 +361,7 @@
/> />
</div> </div>
<div <div
class="h-full col-span-3 space-y-2 border border-input-border rounded-xl p-6" class="h-full md:col-span-2 space-y-2 border border-input-border rounded-xl p-6"
> >
<div class="flex justify-between"> <div class="flex justify-between">
<span class="text-gray-500 font-semibold text-lg" <span class="text-gray-500 font-semibold text-lg"
@@ -280,7 +385,7 @@
tooltip: { tooltip: {
callbacks: { callbacks: {
label: (item) => label: (item) =>
`${item.dataset.label}: ${item.formattedValue} ${barChartUnit}`, `${item.dataset.label}: ${item.formattedValue} ${barChartUnit()}`,
}, },
}, },
}, },
@@ -288,7 +393,7 @@
y: { y: {
ticks: { ticks: {
callback: function (value, index, ticks) { callback: function (value, index, ticks) {
return value + " " + barChartUnit; return value + " " + barChartUnit();
}, },
}, },
}, },
@@ -296,11 +401,17 @@
}} }}
></Bar> ></Bar>
</div> </div>
</div>
<div class="col-span-5 border border-input-border rounded-xl p-6 space-y-6"> <div
class="col-span-1 md:col-span-2 border border-input-border rounded-xl p-6 space-y-6"
>
<span class="text-gray-500 font-semibold text-lg" <span class="text-gray-500 font-semibold text-lg"
><i class="fa fa-table mr-3"></i>{$_("all-activities")}</span ><i class="fa fa-table mr-3"></i>{$_("all-activities")}</span
> >
<SummitLogTable summitLogs={$summitLogs} showCategory></SummitLogTable> <div class=" overflow-x-scroll">
<SummitLogTable summitLogs={$summitLogs} showCategory showTrail
></SummitLogTable>
</div>
</div> </div>
</div> </div>

View File

@@ -1,23 +1,23 @@
import { summit_logs_index, summitLogs } from "$lib/stores/summit_log_store"; import type { SummitLogFilter } from "$lib/models/summit_log";
import { categories_index } from "$lib/stores/category_store";
import { summit_logs_index } from "$lib/stores/summit_log_store";
import { fetchGPX } from "$lib/stores/trail_store"; import { fetchGPX } from "$lib/stores/trail_store";
import { type ServerLoad } from "@sveltejs/kit"; import { type ServerLoad } from "@sveltejs/kit";
import { get } from "svelte/store";
export const load: ServerLoad = async ({ params, locals, fetch }) => { export const load: ServerLoad = async ({ params, locals, fetch }) => {
const logs = await summit_logs_index(fetch);
for (const log of logs) { const date = new Date(), y = date.getFullYear(), m = date.getMonth();
if (!log.gpx) { const firstDay = new Date(y, m, 1);
continue const lastDay = new Date(y, m + 1, 0);
const categories = await categories_index(fetch)
const filter: SummitLogFilter = {
startDate: firstDay.toISOString().slice(0, 10),
endDate: lastDay.toISOString().slice(0, 10),
category: []
} }
const gpxData: string = await fetchGPX(log as any, fetch); const logs = await summit_logs_index(filter, fetch);
if (!log.expand) {
log.expand = {};
}
log.expand.gpx_data = gpxData;
}
console.log(logs);
return {filter}
}; };