adds komoot integration

This commit is contained in:
Christian Beutel
2025-02-04 21:23:54 +01:00
parent a0b6480854
commit 4d1d07922a
32 changed files with 1373 additions and 189 deletions

View File

@@ -72,7 +72,7 @@
</div>
{#if activity.photos.length}
<div
class="grid {activity.photos.length > 1
class="grid gap-[1px] {activity.photos.length > 1
? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'}"
>

View File

@@ -0,0 +1,39 @@
<script lang="ts">
import Toggle from "$lib/components/base/toggle.svelte";
import { _ } from "svelte-i18n";
interface Props {
onclick: () => void;
ontoggle: (value: boolean) => void;
active: boolean;
disabled: boolean;
img: string;
title: string;
description: string;
}
let {
onclick,
ontoggle,
active = $bindable(),
disabled,
img,
title,
description,
}: Props = $props();
</script>
<div class="border border-input-border rounded-lg p-4 space-y-4">
<img class="h-20" src={img} alt="integration logo"/>
<div>
<h5 class="text-xl font-semibold">{title}</h5>
<p class="text-sm text-gray-500">
{description}
</p>
</div>
<div class="flex items-center justify-between">
<button class="btn-secondary" {onclick}
><i class="fa fa-cogs mr-2"></i>{$_("settings")}</button
>
<Toggle bind:value={active} onchange={ontoggle} {disabled}></Toggle>
</div>
</div>

View File

@@ -0,0 +1,82 @@
<script lang="ts">
import Modal from "$lib/components/base/modal.svelte";
import TextField from "$lib/components/base/text_field.svelte";
import { KomootSchema } from "$lib/models/api/integration_schema";
import type {
Integration,
KomootIntegration,
} from "$lib/models/integration";
import { validator } from "@felte/validator-zod";
import { createForm } from "felte";
import { _ } from "svelte-i18n";
interface Props {
integration?: Integration;
onsave?: (komootIntegration: KomootIntegration) => void;
}
let { integration, onsave }: Props = $props();
let modal: Modal;
export function openModal() {
errors.set({})
modal.openModal();
}
const {
form,
errors,
data: d,
} = createForm({
initialValues: {
email: integration?.komoot?.email ?? "",
password: integration?.komoot?.password ?? "",
active: integration?.komoot?.active ?? false,
},
extend: validator({
schema: KomootSchema,
}),
onSubmit: async (form) => {
onsave?.(form);
modal.closeModal();
},
});
</script>
<Modal
id="komoot-settings-modal"
size="max-w-lg"
title={"komoot " + $_("settings")}
bind:this={modal}
>
{#snippet content()}
<form id="komoot-settings-form" class="space-y-2" use:form>
<TextField
label={$_("email")}
placeholder="user@example.com"
name="email"
error={$errors.email}
></TextField>
<TextField
label={$_("password")}
name="password"
type="password"
error={$errors.password}
></TextField>
</form>
{/snippet}
{#snippet footer()}
<div class="flex items-center gap-4">
<button class="btn-secondary" onclick={() => modal.closeModal()}
>{$_("cancel")}</button
>
<button
class="btn-primary"
form="komoot-settings-form"
type="submit"
name="save">{$_("save")}</button
>
</div>
{/snippet}</Modal
>

View File

@@ -0,0 +1,93 @@
<script lang="ts">
import Modal from "$lib/components/base/modal.svelte";
import TextField from "$lib/components/base/text_field.svelte";
import Toggle from "$lib/components/base/toggle.svelte";
import { StravaSchema } from "$lib/models/api/integration_schema";
import type {
Integration,
StravaIntegration,
} from "$lib/models/integration";
import { validator } from "@felte/validator-zod";
import { createForm } from "felte";
import { _ } from "svelte-i18n";
interface Props {
integration?: Integration;
onsave?: (stravaIntegration: StravaIntegration) => void;
}
let { integration, onsave }: Props = $props();
let modal: Modal;
export function openModal() {
errors.set({})
modal.openModal();
}
const {
form,
errors,
} = createForm({
initialValues: {
clientId: integration?.strava?.clientId ?? "",
clientSecret: integration?.strava?.clientSecret ?? "",
routes: integration?.strava?.routes ?? true,
activities: integration?.strava?.activities ?? true,
active: integration?.strava?.active ?? false,
},
extend: validator({
schema: StravaSchema,
}),
onSubmit: async (form) => {
onsave?.(form);
modal.closeModal();
},
});
</script>
<Modal
id="strava-settings-modal"
size="max-w-lg"
title={"strava " + $_("settings")}
bind:this={modal}
>
{#snippet content()}
<form id="strava-settings-form" class="space-y-2" use:form>
<TextField
label="Client-ID"
placeholder="000000"
name="clientId"
error={$errors.clientId}
></TextField>
<TextField
label="Client Secret"
placeholder="de8b3789bd7116d..."
name="clientSecret"
type="password"
error={$errors.clientSecret}
></TextField>
<div class="flex gap-x-4">
<Toggle name="routes" label={$_("route", { values: { n: 2 } })}
></Toggle>
<Toggle
name="activities"
label={$_("activity", { values: { n: 2 } })}
></Toggle>
</div>
</form>
{/snippet}
{#snippet footer()}
<div class="flex items-center gap-4">
<button class="btn-secondary" onclick={() => modal.closeModal()}
>{$_("cancel")}</button
>
<button
class="btn-primary"
form="strava-settings-form"
type="submit"
name="save">{$_("save")}</button
>
</div>
{/snippet}</Modal
>

View File

@@ -55,7 +55,7 @@
<div
class="relative w-full min-h-40 max-h-48 overflow-hidden rounded-t-2xl"
>
<img width="100%" id="header-img" src={thumbnail} alt="" />
<img class="min-h-40" id="header-img" src={thumbnail} alt="" />
</div>
{#if (trail.public || trailIsShared) && pb.authStore.model}
<div

View File

@@ -44,13 +44,20 @@
import TrailTimeline from "./trail_timeline.svelte";
interface Props {
trail: Trail;
initTrail: Trail;
mode?: "overview" | "map" | "list";
markers?: M.Marker[];
activeTab?: number;
}
let { trail, mode = "map", markers = [], activeTab = 0 }: Props = $props();
let {
initTrail,
mode = "map",
markers = [],
activeTab = 0,
}: Props = $props();
let trail = $state(initTrail);
const tabs = [
$_("summit-book"),
@@ -362,7 +369,9 @@
{:else}
<EmptyStateDescription></EmptyStateDescription>
{/if}
<h4 class="text-2xl font-semibold mb-6 mt-12">{$_("route", { values: { n: 2 } })}</h4>
<h4 class="text-2xl font-semibold mb-6 mt-12">
{$_("route", { values: { n: 2 } })}
</h4>
{#if mode === "overview"}
<div
class="relative border border-input-border rounded-xl p-2 mb-6 text-xs"

View File

@@ -42,23 +42,26 @@
<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
photos={wp.photos.map((p) => getFileURL(wp, p))}
bind:this={gallery[i]}
></PhotoGallery>
<div
class="grid {wp.photos.length > 1
class="grid gap-[1px] {wp.photos.length > 1
? 'grid-cols-[8fr_5fr]'
: 'grid-cols-1'} cursor-pointer"
>
{#each wp.photos as photo, j}
<button onclick={() => gallery[i].openGallery(j)}>
<img
class="object-cover h-full max-h-80 w-full"
class:row-span-2={i == 0 &&
wp.photos.length > 2}
src={getFileURL(wp, photo)}
alt=""
/>
</button>
<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=""
/>
{/each}
</div>
{/if}

View File

@@ -45,7 +45,7 @@
</script>
<div
class="flex gap-4 p-4 outline outline-1 outline-input-border rounded-md my-2 hover:outline-2"
class="flex gap-4 p-4 outline outline-1 outline-input-border rounded-md my-2 hover:outline-2 items-start"
>
{#if imgSrc.length}
{#if mode == "show"}
@@ -61,7 +61,7 @@
>
{#each imgSrc as img, i}
<img
class="absolute h-full rounded-xl object-cover"
class="absolute h-full rounded-xl object-cover aspect-square"
style="top: {6 * i}px; right: {6 *
i}px; transform: rotate(-{i * 5}deg)"
src={img}

View File

@@ -100,6 +100,7 @@
"error-during-login": "Fehler beim Login",
"error-during-password-reset": "Email zum Zurücksetzen des Passworts konnte nicht versandt werden",
"error-exporting-trail": "Fehler beim Exportieren des Trails",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Fehler beim Posten des Kommentars",
"error-printing-map": "Fehler beim Drucken der Karte",
"error-reading-file": "Fehler beim Lesen der Datei",
@@ -107,6 +108,7 @@
"error-saving-trail": "Fehler beim Speichern der Route",
"error-setting-up-strava-integration": "",
"error-updating-password": "Fehler beim Aktualisieren des Passworts",
"error-updating-strava-integration": "",
"est-duration": "Gesch. Dauer",
"explore": "Erkunden",
"explore-some-trails": "Erkunde einige Routen",
@@ -143,6 +145,8 @@
"import": "Importieren",
"import-hint": "GPX, FIT, KML oder TCX Dateien auswählen oder hierher ziehen...",
"include-description": "Beschreibung übernehmen",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Ungültiges Datum",
"invalid-username": "Ungültiger Nutzername",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Deine Listen sind standardmäßig öffentlich. \nJeder kann sie sehen. \nDu kannst diese Einstellung jederzeit für einzelne Listen ändern.",
"settings-privacy-trails-private": "Deine Routen sind standardmäßig privat. \nNiemand außer Ihnen kann sie sehen. \nDu kannst diese Einstellung jederzeit für einzelne Routen ändern.",
"settings-privacy-trails-public": "Deine Trails sind standardmäßig öffentlich. \nJeder kann sie sehen. \nDu kannst diese Einstellung jederzeit für einzelne Routen ändern.",
"settings-saved": "",
"share": "Teilen",
"share-profile": "Profil teilen",
"share-this-list": "Diese Liste teilen",
@@ -295,4 +300,4 @@
"welcome_to": "Willkommen bei",
"wrong-username-or-password": "Falscher Nutzername oder falsches Passwort",
"you-can": "Du kannst"
}
}

View File

@@ -100,6 +100,7 @@
"error-during-login": "Error during login",
"error-during-password-reset": "Unable to send password reset email",
"error-exporting-trail": "Error exporting trail",
"error-logging-in-to-komoot": "Error logging in to komoot",
"error-posting-comment": "Error posting comment",
"error-printing-map": "Error printing map",
"error-reading-file": "Error reading file",
@@ -107,6 +108,7 @@
"error-saving-trail": "Error saving trail",
"error-setting-up-strava-integration": "Error setting up strava integration",
"error-updating-password": "Error updating password",
"error-updating-strava-integration": "Error updating komoot integration",
"est-duration": "Est. duration",
"explore": "Explore",
"explore-some-trails": "Explore some trails",
@@ -143,6 +145,8 @@
"import": "Import",
"import-hint": "Select or drag GPX, FIT, KML or TCX files here...",
"include-description": "Include description",
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integrations": "Integrations",
"invalid-date": "Invalid Date",
"invalid-username": "Invalid username",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Your lists are public by default. Everyone will be able to see them. You can change this setting at any point for individual lists.",
"settings-privacy-trails-private": "Your trails are private by default. No one except you will be able to see them. You can change this setting at any point for individual trails.",
"settings-privacy-trails-public": "Your trails are public by default. Everyone will be able to see them. You can change this setting at any point for individual trails.",
"settings-saved": "Settings saved",
"share": "Share",
"share-profile": "Share profile",
"share-this-list": "Share this list",
@@ -295,4 +300,4 @@
"welcome_to": "Welcome to",
"wrong-username-or-password": "Wrong username or password",
"you-can": "You can"
}
}

View File

@@ -100,6 +100,7 @@
"error-during-login": "Error durante el acceso",
"error-during-password-reset": "Imposible enviar la contraseña de restablecimiento al correo electrónico",
"error-exporting-trail": "Error exportando la ruta",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error publicando el comentario",
"error-printing-map": "Error durante la impresión del mapa",
"error-reading-file": "Error leyendo el archivo",
@@ -107,6 +108,7 @@
"error-saving-trail": "Error guardando la ruta",
"error-setting-up-strava-integration": "",
"error-updating-password": "Error actualizando la contraseña",
"error-updating-strava-integration": "",
"est-duration": "Duración estimada",
"explore": "Explora",
"explore-some-trails": "Explora alguna ruta",
@@ -143,6 +145,8 @@
"import": "Importar",
"import-hint": "Selecciona o arrastra aquí archivos GPX, FIT, KML o TCX...",
"include-description": "Incluir descripción",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Fecha no válida",
"invalid-username": "Usuario no válido",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Tus listas son públicas por defecto. Todos podrán verlas. Puedes cambiar esta configuración en cualquier momento para listas específicas.",
"settings-privacy-trails-private": "Tus rutas son privadas por defecto. Nadie excepto tú podrás verlas. Puedes cambiar esta configuración en cualquier momento para rutas específicas.",
"settings-privacy-trails-public": "Tus rutas son públicas por defecto. Todos podrán verlas. Puedes cambiar esta configuración en cualquier momento para rutas específicas.",
"settings-saved": "",
"share": "Compartir",
"share-profile": "Compartir perfil",
"share-this-list": "Compartir esta lista",

View File

@@ -100,6 +100,7 @@
"error-during-login": "Erreur durant la connexion",
"error-during-password-reset": "Unable to send password reset email",
"error-exporting-trail": "Erreur lors de l'export de l'itinéraire",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error posting comment",
"error-printing-map": "Erreur d'impression de la carte",
"error-reading-file": "Erreur de lecture du fichier",
@@ -107,6 +108,7 @@
"error-saving-trail": "Erreur lors de l'enregistrement de l'itinéraire",
"error-setting-up-strava-integration": "",
"error-updating-password": "Erreur lors de la mise à jour du mot de passe",
"error-updating-strava-integration": "",
"est-duration": "Temps estimé",
"explore": "Explorer",
"explore-some-trails": "Explorer les itinéraires",
@@ -143,6 +145,8 @@
"import": "Importer",
"import-hint": "Sélectionnez ou glissez des fichiers GPX, FIT, KML ou TCX ici...",
"include-description": "Inclure la description",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Date invalide",
"invalid-username": "Nom d'utilisateur invalide",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Your lists are public by default. Everyone will be able to see them. You can change this setting at any point for individual lists.",
"settings-privacy-trails-private": "Your trails are private by default. No one except you will be able to see them. You can change this setting at any point for individual trails.",
"settings-privacy-trails-public": "Your trails are public by default. Everyone will be able to see them. You can change this setting at any point for individual trails.",
"settings-saved": "",
"share": "Partager",
"share-profile": "Share profile",
"share-this-list": "Partager cette liste",

View File

@@ -100,6 +100,7 @@
"error-during-login": "Hiba bejelentkezés közben",
"error-during-password-reset": "Unable to send password reset email",
"error-exporting-trail": "Error exporting trail",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error posting comment",
"error-printing-map": "Error printing map",
"error-reading-file": "Hiba a fájl olvasása közben",
@@ -107,6 +108,7 @@
"error-saving-trail": "Error saving trail",
"error-setting-up-strava-integration": "",
"error-updating-password": "Error updating password",
"error-updating-strava-integration": "",
"est-duration": "Becsült időtartam",
"explore": "Felfedezés",
"explore-some-trails": "Fedezzen fel néhány ösvényt",
@@ -143,6 +145,8 @@
"import": "Import",
"import-hint": "Select or drag GPX, FIT, KML or TCX files here...",
"include-description": "Include description",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Érvénytelen dátum",
"invalid-username": "Érvénytelen felhasználó",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Your lists are public by default. Everyone will be able to see them. You can change this setting at any point for individual lists.",
"settings-privacy-trails-private": "Your trails are private by default. No one except you will be able to see them. You can change this setting at any point for individual trails.",
"settings-privacy-trails-public": "Your trails are public by default. Everyone will be able to see them. You can change this setting at any point for individual trails.",
"settings-saved": "",
"share": "Share",
"share-profile": "Share profile",
"share-this-list": "Share this list",

View File

@@ -100,6 +100,7 @@
"error-during-login": "Errore durante il login",
"error-during-password-reset": "Impossibile inviare email per ripristinare la password",
"error-exporting-trail": "Errore durante l'esportazione del percorso",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Errore pubblicando il commento",
"error-printing-map": "Errore durante la stampa della mappa",
"error-reading-file": "Errore durante la lettura del file",
@@ -107,6 +108,7 @@
"error-saving-trail": "Errore nel salvataggio del percorso",
"error-setting-up-strava-integration": "",
"error-updating-password": "Errore nell'aggiornamento della password",
"error-updating-strava-integration": "",
"est-duration": "Durata stimata",
"explore": "Esplora",
"explore-some-trails": "Esplora alcuni percorsi",
@@ -143,6 +145,8 @@
"import": "Importa",
"import-hint": "Seleziona o trascina qui i file GPX, FIT, KML o TCX...",
"include-description": "Adotta descrizione",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Data non valida",
"invalid-username": "Nome utente non valido",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Le tue liste sono pubbliche per impostazione predefinita. Tutto potrànno vederle. Puoi cambiare queste impostazione in qualsiasi momento per liste specifiche.",
"settings-privacy-trails-private": "Le tuoi percorsi sono privati per impostazione predefinita. Nessuno tranne tu potrà vederli. Puoi cambiare queste impostazione in qualsiasi momento per percorsi specifici.",
"settings-privacy-trails-public": "Le tuoi percorsi sono pubblici per impostazione predefinita. Tutti potranno vederli. Puoi cambiare queste impostazione in qualsiasi momento per percorsi specifici.",
"settings-saved": "",
"share": "Condividi",
"share-profile": "Condividere profilo",
"share-this-list": "Condividi questa lista",

View File

@@ -100,6 +100,7 @@
"error-during-login": "Het inloggen is mislukt",
"error-during-password-reset": "Unable to send password reset email",
"error-exporting-trail": "Error exporting trail",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error posting comment",
"error-printing-map": "Fout bij afdrukken van kaart",
"error-reading-file": "Het bestand kan niet worden ingelezen",
@@ -107,6 +108,7 @@
"error-saving-trail": "Error saving trail",
"error-setting-up-strava-integration": "",
"error-updating-password": "Error updating password",
"error-updating-strava-integration": "",
"est-duration": "Geschatte duur",
"explore": "Verkennen",
"explore-some-trails": "Verken enkele wandelroutes",
@@ -143,6 +145,8 @@
"import": "Import",
"import-hint": "Select or drag GPX, FIT, KML or TCX files here...",
"include-description": "Inclusief beschrijving",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Ongeldige datum",
"invalid-username": "Ongeldige gebruikersnaam",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Your lists are public by default. Everyone will be able to see them. You can change this setting at any point for individual lists.",
"settings-privacy-trails-private": "Your trails are private by default. No one except you will be able to see them. You can change this setting at any point for individual trails.",
"settings-privacy-trails-public": "Your trails are public by default. Everyone will be able to see them. You can change this setting at any point for individual trails.",
"settings-saved": "",
"share": "Share",
"share-profile": "Share profile",
"share-this-list": "Share this list",

View File

@@ -100,6 +100,7 @@
"error-during-login": "Błąd podczas logowania",
"error-during-password-reset": "Nie udało się wysłać e-maila z resetowaniem hasła",
"error-exporting-trail": "Błąd podczas eksportowania szlaku",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error posting comment",
"error-printing-map": "Błąd podczas drukowania mapy",
"error-reading-file": "Błąd wczytywania pliku",
@@ -107,6 +108,7 @@
"error-saving-trail": "Błąd podczas zapisywania szlaku",
"error-setting-up-strava-integration": "",
"error-updating-password": "Błąd podczas aktualizacji hasła",
"error-updating-strava-integration": "",
"est-duration": "Szacowany czas",
"explore": "Eksploruj",
"explore-some-trails": "Eksploruj różne szlaki",
@@ -143,6 +145,8 @@
"import": "Importuj",
"import-hint": "Wybierz lub przeciągnij tutaj plik GPX, FIT, KML lub TCX...",
"include-description": "Dołącz opis",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Nieprawidłowa data",
"invalid-username": "Błędna nazwa użytkownika",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Domyślnie, twoje listy są publiczne. Każdy będzie mógł je zobaczyć. Zawsze możesz zmieniać to ustawienie, osobno dla każdej listy.",
"settings-privacy-trails-private": "Domyślnie, twoje szlaki są prywatne. Nikt poza tobą nie będzie mógł ich zobaczyć. Zawsze możesz zmieniać to ustawienie, osobno dla każdego szlaku.",
"settings-privacy-trails-public": "Domyślnie, twoje szlaki są publiczne. Każdy będzie mógł je zobaczyć. Zawsze możesz zmieniać to ustawienie, osobno dla każdego szlaku.",
"settings-saved": "",
"share": "Udostępnij",
"share-profile": "Udostępnij profil",
"share-this-list": "Udostępnij tę listę",

View File

@@ -100,6 +100,7 @@
"error-during-login": "Erro durante o ‘login’",
"error-during-password-reset": "Unable to send password reset email",
"error-exporting-trail": "Erro na exportação do percurso",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error posting comment",
"error-printing-map": "Erro na impressão do mapa",
"error-reading-file": "Erro ao ler o arquivo",
@@ -107,6 +108,7 @@
"error-saving-trail": "Erro ao gravar percurso",
"error-setting-up-strava-integration": "",
"error-updating-password": "Erro ao atualizar password",
"error-updating-strava-integration": "",
"est-duration": "Duração prevista",
"explore": "Explorar",
"explore-some-trails": "Explore algumas trilhas",
@@ -143,6 +145,8 @@
"import": "Importar",
"import-hint": "Selecionar ou arrastar ficheiros GPX, FIT, KML ou TCX para aqui...",
"include-description": "Incluir descrição",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "Data inválida",
"invalid-username": "Nome de usuário inválido",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Your lists are public by default. Everyone will be able to see them. You can change this setting at any point for individual lists.",
"settings-privacy-trails-private": "Your trails are private by default. No one except you will be able to see them. You can change this setting at any point for individual trails.",
"settings-privacy-trails-public": "Your trails are public by default. Everyone will be able to see them. You can change this setting at any point for individual trails.",
"settings-saved": "",
"share": "Partilhar",
"share-profile": "Share profile",
"share-this-list": "Partilhar esta lista",

View File

@@ -100,6 +100,7 @@
"error-during-login": "登录错误",
"error-during-password-reset": "Unable to send password reset email",
"error-exporting-trail": "导出路线失败",
"error-logging-in-to-komoot": "",
"error-posting-comment": "Error posting comment",
"error-printing-map": "打印地图失败",
"error-reading-file": "读取文件错误",
@@ -107,6 +108,7 @@
"error-saving-trail": "保存路线失败",
"error-setting-up-strava-integration": "",
"error-updating-password": "更新密码失败",
"error-updating-strava-integration": "",
"est-duration": "预计时长",
"explore": "探索",
"explore-some-trails": "探索行程",
@@ -143,6 +145,8 @@
"import": "导入",
"import-hint": "在此选择或拖拽GPX、FIT、KML或TCX文件...",
"include-description": "包含描述",
"integration-description-komoot": "",
"integration-description-strava": "",
"integrations": "",
"invalid-date": "无效日期",
"invalid-username": "无效用户名",
@@ -257,6 +261,7 @@
"settings-privacy-lists-public": "Your lists are public by default. Everyone will be able to see them. You can change this setting at any point for individual lists.",
"settings-privacy-trails-private": "Your trails are private by default. No one except you will be able to see them. You can change this setting at any point for individual trails.",
"settings-privacy-trails-public": "Your trails are public by default. Everyone will be able to see them. You can change this setting at any point for individual trails.",
"settings-saved": "",
"share": "分享",
"share-profile": "Share profile",
"share-this-list": "分享此列表",

View File

@@ -12,14 +12,22 @@ const StravaSchema = z.object({
active: z.boolean()
})
const KomootSchema = z.object({
email: z.string().email(),
password: z.string(),
active: z.boolean()
})
const IntegrationCreateSchema = z.object({
user: z.string().length(15),
strava: StravaSchema,
strava: StravaSchema.optional(),
komoot: KomootSchema.optional()
}) satisfies ZodType<Integration>
const IntegrationUpdateSchema = z.object({
strava: StravaSchema.optional(),
strava: StravaSchema.optional().nullable(),
komoot: KomootSchema.optional().nullable()
}) satisfies ZodType<Partial<Integration>>
export { StravaSchema, IntegrationCreateSchema, IntegrationUpdateSchema }
export { StravaSchema, IntegrationCreateSchema, IntegrationUpdateSchema, KomootSchema };

View File

@@ -1,9 +1,9 @@
interface BaseIntegration {
export interface BaseIntegration {
active: boolean
}
interface StravaIntegration extends BaseIntegration {
export interface StravaIntegration extends BaseIntegration {
clientId: string | number;
clientSecret: string;
routes: boolean;
@@ -13,13 +13,21 @@ interface StravaIntegration extends BaseIntegration {
expiresAt?: number;
}
export interface KomootIntegration extends BaseIntegration {
email: string,
password: string,
}
export class Integration {
id?: string;
user: string;
strava?: StravaIntegration;
strava?: StravaIntegration | null;
komoot?: KomootIntegration | null
constructor(user: string, strava?: StravaIntegration) {
constructor(user: string, strava?: StravaIntegration, komoot?: KomootIntegration) {
this.user = user;
this.strava = strava;
this.komoot = komoot;
}
}