feat: translate all pages
This commit is contained in:
117
messages/de.json
117
messages/de.json
@ -5,5 +5,122 @@
|
|||||||
"school": "Schule",
|
"school": "Schule",
|
||||||
"work": "Arbeit",
|
"work": "Arbeit",
|
||||||
"no-location": "Kein {name} Speicherort gespeichert."
|
"no-location": "Kein {name} Speicherort gespeichert."
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"unlock": "Standort entsperren",
|
||||||
|
"lock": "Standort sperren",
|
||||||
|
"code": "Standortcode",
|
||||||
|
"start": "Standort teilen",
|
||||||
|
"join": "Remote-Standort beitreten"
|
||||||
|
},
|
||||||
|
"vehicles": {
|
||||||
|
"selector": {
|
||||||
|
"title": "Fahrzeugauswahl",
|
||||||
|
"description": "Wählen Sie Ihr Fahrzeug aus, um die Route individuell auf Sie abzustimmen.",
|
||||||
|
"add": "Fahrzeug hinzufügen"
|
||||||
|
},
|
||||||
|
"types": {
|
||||||
|
"car": "Auto",
|
||||||
|
"moped": "Moped"
|
||||||
|
},
|
||||||
|
"add": {
|
||||||
|
"name": "Fahrzeugname",
|
||||||
|
"legal-speed": "Legale Geschwindigkeit",
|
||||||
|
"actual-speed": "Tatsächliche Geschwindigkeit",
|
||||||
|
"fuel": "Kraftstoffart",
|
||||||
|
"preferred-fuel": "Bevorzugter Kraftstoff",
|
||||||
|
"diesel": "Diesel",
|
||||||
|
"petrol": "Benzin",
|
||||||
|
"electric": "Elektrisch",
|
||||||
|
"errors": {
|
||||||
|
"enter-name": "Bitte geben Sie einen Fahrzeugnamen ein.",
|
||||||
|
"enter-speeds": "Bitte geben Sie gültige Geschwindigkeiten ein.",
|
||||||
|
"select-fuel": "Bitte wählen Sie eine gültige Kraftstoffart und den bevorzugten Kraftstoff aus."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": "Standardfahrzeug"
|
||||||
|
},
|
||||||
|
"save": "Speichern",
|
||||||
|
"cancel": "Abbrechen",
|
||||||
|
"loading": "Laden...",
|
||||||
|
"more": "Mehr",
|
||||||
|
"error": "Fehler",
|
||||||
|
"sidebar": {
|
||||||
|
"about": {
|
||||||
|
"header": "Über",
|
||||||
|
"powered-by": "Angetrieben von",
|
||||||
|
"contributors": "Mitwirkende"
|
||||||
|
},
|
||||||
|
"developer": {
|
||||||
|
"header": "Entwicklereinstellungen"
|
||||||
|
},
|
||||||
|
"offline-maps": {
|
||||||
|
"header": "Offline-Karten",
|
||||||
|
"not-available": "Keine Offline-Karten verfügbar.",
|
||||||
|
"only-mobile": "Offline-Karten sind nur auf Mobilgeräten verfügbar.",
|
||||||
|
"downloaded": "{name} wurde heruntergeladen"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"header": "Sprache"
|
||||||
|
},
|
||||||
|
"map-style": {
|
||||||
|
"header": "Kartenstil"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"header": "Einstellungen",
|
||||||
|
"general": "Allgemein",
|
||||||
|
"map": "Karte"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"dropped": "Pin",
|
||||||
|
"route": "Route",
|
||||||
|
"email": "E-Mail",
|
||||||
|
"website": "Webseite",
|
||||||
|
"call": "Anrufen",
|
||||||
|
"set-as": "Speichern als {name}",
|
||||||
|
"payment-methods": "Zahlungsarten",
|
||||||
|
"fuel-types": "Kraftstoffarten",
|
||||||
|
"prices": "Kraftstoffpreise",
|
||||||
|
"no-prices": "Keine Kraftstoffpreise verfügbar.",
|
||||||
|
"error-loading-prices": "Fehler beim Laden der Kraftstoffpreise",
|
||||||
|
"internet-access": "Internetzugang",
|
||||||
|
"fee": "Gebühr",
|
||||||
|
"opening-hours": "Öffnungszeiten",
|
||||||
|
"open": "Offen",
|
||||||
|
"closed": "Geschlossen",
|
||||||
|
"restaurant": "Restaurant",
|
||||||
|
"reviews": "Bewertungen",
|
||||||
|
"no-reviews": "Keine Bewertungen.",
|
||||||
|
"write-review": "Eigene Bewertung schreiben"
|
||||||
|
},
|
||||||
|
"mapai": {
|
||||||
|
"ask-question": "Stellen Sie eine Frage zu diesem Ort ..."
|
||||||
|
},
|
||||||
|
"in-route": {
|
||||||
|
"left": "links",
|
||||||
|
"end-trip": "Route beenden",
|
||||||
|
"share-code": "Code teilen",
|
||||||
|
"stop-sharing": "Standortfreigabe beenden",
|
||||||
|
"share-location": "Routenstatus und Standort teilen"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"header": "Route",
|
||||||
|
"driving-with": "Fahren mit",
|
||||||
|
"help": "Sie können <strong>aktuell</strong> für Ihren aktuellen Standort und <strong>home</strong>, <strong>school</strong> oder <strong>work</strong> für gespeicherte Standorte verwenden.",
|
||||||
|
"calculate": "Berechnen"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"header": "Suchergebnisse für"
|
||||||
|
},
|
||||||
|
"trip": {
|
||||||
|
"header": "Routendetails",
|
||||||
|
"start": "Start",
|
||||||
|
"save": "Speichern",
|
||||||
|
"send": "Senden"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"header": "Benutzer",
|
||||||
|
"login": "Login"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
117
messages/en.json
117
messages/en.json
@ -1,9 +1,126 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://inlang.com/schema/inlang-message-format",
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"save": "Save",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"loading": "Loading...",
|
||||||
|
"more": "More",
|
||||||
|
"error": "Error",
|
||||||
"saved": {
|
"saved": {
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
"school": "School",
|
"school": "School",
|
||||||
"work": "Work",
|
"work": "Work",
|
||||||
"no-location": "No {name} location saved."
|
"no-location": "No {name} location saved."
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"unlock": "Unlock Location",
|
||||||
|
"lock": "Lock Location",
|
||||||
|
"code": "Advertise code",
|
||||||
|
"start": "Advertise Location",
|
||||||
|
"join": "Join Remote Location"
|
||||||
|
},
|
||||||
|
"vehicles": {
|
||||||
|
"default": "Default Vehicle",
|
||||||
|
"selector": {
|
||||||
|
"title": "Vehicle Selector",
|
||||||
|
"description": "Select your vehicle to customize routing just for you.",
|
||||||
|
"add": "Add Vehicle"
|
||||||
|
},
|
||||||
|
"types": {
|
||||||
|
"car": "Car",
|
||||||
|
"moped": "Moped"
|
||||||
|
},
|
||||||
|
"add": {
|
||||||
|
"name": "Vehicle Name",
|
||||||
|
"legal-speed": "Legal Speed",
|
||||||
|
"actual-speed": "Actual Speed",
|
||||||
|
"fuel": "Fuel Type",
|
||||||
|
"preferred-fuel": "Preferred Fuel",
|
||||||
|
"diesel": "Diesel",
|
||||||
|
"petrol": "Petrol",
|
||||||
|
"electric": "Electric",
|
||||||
|
"errors": {
|
||||||
|
"enter-name": "Please enter a vehicle name.",
|
||||||
|
"enter-speeds": "Please enter valid speeds.",
|
||||||
|
"select-fuel": "Please select a valid fuel type and preferred fuel."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"about": {
|
||||||
|
"header": "About",
|
||||||
|
"powered-by": "Powered by",
|
||||||
|
"contributors": "contributors"
|
||||||
|
},
|
||||||
|
"developer": {
|
||||||
|
"header": "Developer Settings"
|
||||||
|
},
|
||||||
|
"offline-maps": {
|
||||||
|
"header": "Offline Maps",
|
||||||
|
"not-available": "No offline maps available.",
|
||||||
|
"only-mobile": "Offline maps are only available on mobile.",
|
||||||
|
"downloaded": "Downloaded {name}"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"header": "Language"
|
||||||
|
},
|
||||||
|
"map-style": {
|
||||||
|
"header": "Map Style"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"header": "Settings",
|
||||||
|
"general": "General",
|
||||||
|
"map": "Map"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"dropped": "Dropped Pin",
|
||||||
|
"route": "Route",
|
||||||
|
"email": "Email",
|
||||||
|
"website": "Website",
|
||||||
|
"call": "Call",
|
||||||
|
"set-as": "Set as {name}",
|
||||||
|
"payment-methods": "Payment Methods",
|
||||||
|
"fuel-types": "Fuel Types",
|
||||||
|
"prices": "Fuel Prices",
|
||||||
|
"no-prices": "No fuel prices available.",
|
||||||
|
"error-loading-prices": "Error loading fuel prices",
|
||||||
|
"internet-access": "Internet Access",
|
||||||
|
"fee": "Fee",
|
||||||
|
"opening-hours": "Opening Hours",
|
||||||
|
"open": "Open",
|
||||||
|
"closed": "Closed",
|
||||||
|
"restaurant": "Restaurant",
|
||||||
|
"reviews": "Reviews",
|
||||||
|
"no-reviews": "No reviews.",
|
||||||
|
"write-review": "Write a review"
|
||||||
|
},
|
||||||
|
"mapai": {
|
||||||
|
"ask-question": "Ask a question about this place..."
|
||||||
|
},
|
||||||
|
"in-route": {
|
||||||
|
"left": "left",
|
||||||
|
"end-trip": "End Trip",
|
||||||
|
"share-code": "Share Code",
|
||||||
|
"stop-sharing": "Stop Sharing Location",
|
||||||
|
"share-location": "Share Trip Status & Location"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"header": "Route",
|
||||||
|
"driving-with": "Driving with",
|
||||||
|
"help": "You can use <strong>current</strong> for your current location, <strong>home</strong>, <strong>school</strong> or <strong>work</strong> for saved locations.",
|
||||||
|
"calculate": "Calculate"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"header": "Search Results for"
|
||||||
|
},
|
||||||
|
"trip": {
|
||||||
|
"header": "Trip Details",
|
||||||
|
"start": "Start Navigation",
|
||||||
|
"save": "Save",
|
||||||
|
"send": "Send"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"header": "User",
|
||||||
|
"login": "Login"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,6 +21,7 @@
|
|||||||
import * as Select from "../ui/select";
|
import * as Select from "../ui/select";
|
||||||
import Input from "../ui/input/input.svelte";
|
import Input from "../ui/input/input.svelte";
|
||||||
import EvConnectorSelect from "./EVConnectorSelect.svelte";
|
import EvConnectorSelect from "./EVConnectorSelect.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
let open = $state(false);
|
let open = $state(false);
|
||||||
|
|
||||||
@ -62,7 +63,7 @@
|
|||||||
</Drawer.Trigger>
|
</Drawer.Trigger>
|
||||||
<Drawer.Content>
|
<Drawer.Content>
|
||||||
<Drawer.Header>
|
<Drawer.Header>
|
||||||
<Drawer.Title>Add Vehicle</Drawer.Title>
|
<Drawer.Title>{m["vehicles.selector.add"]()}</Drawer.Title>
|
||||||
</Drawer.Header>
|
</Drawer.Header>
|
||||||
<div class="p-4 pt-0 flex flex-col gap-2">
|
<div class="p-4 pt-0 flex flex-col gap-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
@ -71,75 +72,75 @@
|
|||||||
{@const Icon = getVehicleIcon(vehicle.type)}
|
{@const Icon = getVehicleIcon(vehicle.type)}
|
||||||
<Icon />
|
<Icon />
|
||||||
{vehicle.type === "car"
|
{vehicle.type === "car"
|
||||||
? "Car"
|
? m["vehicles.types.car"]()
|
||||||
: vehicle.type === "motor_scooter"
|
: vehicle.type === "motor_scooter"
|
||||||
? "Moped"
|
? m["vehicles.types.moped"]()
|
||||||
: "?"}
|
: "?"}
|
||||||
</Select.Trigger>
|
</Select.Trigger>
|
||||||
<Select.Content>
|
<Select.Content>
|
||||||
<Select.Item value="car">
|
<Select.Item value="car">
|
||||||
<CarIcon />
|
<CarIcon />
|
||||||
Car
|
{m["vehicles.types.car"]()}
|
||||||
</Select.Item>
|
</Select.Item>
|
||||||
<Select.Item value="motor_scooter">
|
<Select.Item value="motor_scooter">
|
||||||
<TractorIcon />
|
<TractorIcon />
|
||||||
Moped
|
{m["vehicles.types.moped"]()}
|
||||||
</Select.Item>
|
</Select.Item>
|
||||||
</Select.Content>
|
</Select.Content>
|
||||||
</Select.Root>
|
</Select.Root>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Vehicle Name"
|
placeholder={m["vehicles.add.name"]()}
|
||||||
bind:value={vehicle.name}
|
bind:value={vehicle.name}
|
||||||
class="w-full"
|
class="w-full"
|
||||||
aria-label="Vehicle Name"
|
aria-label={m["vehicles.add.name"]()}
|
||||||
aria-required="true"
|
aria-required="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-around mt-4">
|
<div class="flex justify-around mt-4">
|
||||||
<span>Legal Speed</span>
|
<span>{m["vehicles.add.legal-speed"]()}</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span>Actual Speed</span>
|
<span>{m["vehicles.add.actual-speed"]()}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="Legal Speed"
|
placeholder={m["vehicles.add.legal-speed"]()}
|
||||||
bind:value={vehicle.legalMaxSpeed}
|
bind:value={vehicle.legalMaxSpeed}
|
||||||
class="w-full text-center"
|
class="w-full text-center"
|
||||||
aria-label="Legal Max Speed"
|
aria-label={m["vehicles.add.legal-speed"]()}
|
||||||
aria-required="true"
|
aria-required="true"
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="Actual Speed"
|
placeholder={m["vehicles.add.actual-speed"]()}
|
||||||
bind:value={vehicle.actualMaxSpeed}
|
bind:value={vehicle.actualMaxSpeed}
|
||||||
class="w-full text-center"
|
class="w-full text-center"
|
||||||
aria-label="Actual Max Speed"
|
aria-label={m["vehicles.add.actual-speed"]()}
|
||||||
aria-required="true"
|
aria-required="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-around mt-4">
|
<div class="flex justify-around mt-4">
|
||||||
<span>Fuel Type</span>
|
<span>{m["vehicles.add.fuel"]()}</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span>Preferred Fuel</span>
|
<span>{m["vehicles.add.preferred-fuel"]()}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<Select.Root type="single" bind:value={vehicle.fuelType}>
|
<Select.Root type="single" bind:value={vehicle.fuelType}>
|
||||||
<Select.Trigger class="w-full">
|
<Select.Trigger class="w-full">
|
||||||
{vehicle.fuelType === "diesel"
|
{vehicle.fuelType === "diesel"
|
||||||
? "Diesel"
|
? m["vehicles.add.diesel"]()
|
||||||
: vehicle.fuelType === "petrol"
|
: vehicle.fuelType === "petrol"
|
||||||
? "Petrol"
|
? m["vehicles.add.petrol"]()
|
||||||
: "Electric"}
|
: m["vehicles.add.electric"]()}
|
||||||
</Select.Trigger>
|
</Select.Trigger>
|
||||||
<Select.Content>
|
<Select.Content>
|
||||||
<Select.Item value="diesel">Diesel</Select.Item>
|
<Select.Item value="diesel">{m["vehicles.add.diesel"]()}</Select.Item>
|
||||||
<Select.Item value="petrol">Petrol</Select.Item>
|
<Select.Item value="petrol">{m["vehicles.add.petrol"]()}</Select.Item>
|
||||||
<Select.Item value="electric">Electric</Select.Item>
|
<Select.Item value="electric">{m["vehicles.add.electric"]()}</Select.Item>
|
||||||
</Select.Content>
|
</Select.Content>
|
||||||
</Select.Root>
|
</Select.Root>
|
||||||
|
|
||||||
@ -165,15 +166,15 @@
|
|||||||
onclick={() => {
|
onclick={() => {
|
||||||
open = false;
|
open = false;
|
||||||
if (vehicle.name.trim() === "") {
|
if (vehicle.name.trim() === "") {
|
||||||
alert("Please enter a vehicle name.");
|
alert(m["vehicles.add.errors.enter-name"]());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (vehicle.legalMaxSpeed <= 0 || vehicle.actualMaxSpeed <= 0) {
|
if (vehicle.legalMaxSpeed <= 0 || vehicle.actualMaxSpeed <= 0) {
|
||||||
alert("Please enter valid speeds.");
|
alert(m["vehicles.add.errors.enter-speeds"]());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isValidFuel(vehicle)) {
|
if (!isValidFuel(vehicle)) {
|
||||||
alert("Please select a valid fuel type and preferred fuel.");
|
alert(m["vehicles.add.errors.select-fuel"]());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setVehicles([...vehicles, vehicle]);
|
setVehicles([...vehicles, vehicle]);
|
||||||
@ -182,7 +183,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SaveIcon />
|
<SaveIcon />
|
||||||
Save
|
{m.save()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@ -191,7 +192,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<XIcon />
|
<XIcon />
|
||||||
Cancel
|
{m.cancel()}
|
||||||
</Button>
|
</Button>
|
||||||
</Drawer.Footer>
|
</Drawer.Footer>
|
||||||
</Drawer.Content>
|
</Drawer.Content>
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
import AboutSidebar from "./sidebar/settings/AboutSidebar.svelte";
|
import AboutSidebar from "./sidebar/settings/AboutSidebar.svelte";
|
||||||
import OfflineMapsSidebar from "./sidebar/settings/OfflineMapsSidebar.svelte";
|
import OfflineMapsSidebar from "./sidebar/settings/OfflineMapsSidebar.svelte";
|
||||||
import DeveloperSidebar from "./sidebar/settings/DeveloperSidebar.svelte";
|
import DeveloperSidebar from "./sidebar/settings/DeveloperSidebar.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const views: Record<string, Component<any>> = {
|
const views: Record<string, Component<any>> = {
|
||||||
@ -188,10 +189,10 @@
|
|||||||
location.toggleLock();
|
location.toggleLock();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{location.locked ? "Unlock Location" : "Lock Location"}
|
{location.locked ? m["location.unlock"]() : m["location.unlock"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{#if location.code}
|
{#if location.code}
|
||||||
<span>Advertise code: {location.code}</span>
|
<span>{m["location.code"]()}: {location.code}</span>
|
||||||
{/if}
|
{/if}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@ -199,7 +200,7 @@
|
|||||||
advertiseRemoteLocation();
|
advertiseRemoteLocation();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Advertise Location
|
{m["location.start"]()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@ -207,7 +208,7 @@
|
|||||||
remoteLocation(prompt("Code?") || "");
|
remoteLocation(prompt("Code?") || "");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Join Remote Location
|
{m["location.join"]()}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Popover.Content>
|
</Popover.Content>
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
type VehicleType,
|
type VehicleType,
|
||||||
} from "$lib/vehicles/vehicles.svelte";
|
} from "$lib/vehicles/vehicles.svelte";
|
||||||
import AddVehicleDrawer from "./AddVehicleDrawer.svelte";
|
import AddVehicleDrawer from "./AddVehicleDrawer.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
let open = $state(false);
|
let open = $state(false);
|
||||||
|
|
||||||
@ -48,9 +49,9 @@
|
|||||||
</Drawer.Trigger>
|
</Drawer.Trigger>
|
||||||
<Drawer.Content>
|
<Drawer.Content>
|
||||||
<Drawer.Header>
|
<Drawer.Header>
|
||||||
<Drawer.Title>Vehicle Selector</Drawer.Title>
|
<Drawer.Title>{m["vehicles.selector.title"]()}</Drawer.Title>
|
||||||
<Drawer.Description
|
<Drawer.Description
|
||||||
>Select your vehicle to customize routing just for you.</Drawer.Description
|
>{m["vehicles.selector.description"]()}</Drawer.Description
|
||||||
>
|
>
|
||||||
</Drawer.Header>
|
</Drawer.Header>
|
||||||
<div class="p-4 pt-0 flex flex-col gap-2">
|
<div class="p-4 pt-0 flex flex-col gap-2">
|
||||||
@ -72,7 +73,7 @@
|
|||||||
<AddVehicleDrawer>
|
<AddVehicleDrawer>
|
||||||
<Button variant="secondary" class="w-full p-5">
|
<Button variant="secondary" class="w-full p-5">
|
||||||
<PlusCircleIcon />
|
<PlusCircleIcon />
|
||||||
Add Vehicle
|
{m["vehicles.selector.add"]()}
|
||||||
</Button>
|
</Button>
|
||||||
</AddVehicleDrawer>
|
</AddVehicleDrawer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import Badge from "$lib/components/ui/badge/badge.svelte";
|
import Badge from "$lib/components/ui/badge/badge.svelte";
|
||||||
import { getStations } from "$lib/services/MTSK";
|
import { getStations } from "$lib/services/MTSK";
|
||||||
import RequiresCapability from "../RequiresCapability.svelte";
|
import RequiresCapability from "../RequiresCapability.svelte";
|
||||||
@ -6,7 +7,7 @@
|
|||||||
let { tags, lat, lng } = $props();
|
let { tags, lat, lng } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h3 class="text-lg font-bold mt-2">Fuel Types</h3>
|
<h3 class="text-lg font-bold mt-2">{m["sidebar.info.fuel-types"]()}</h3>
|
||||||
<ul class="flex gap-2 flex-wrap">
|
<ul class="flex gap-2 flex-wrap">
|
||||||
{#each Object.entries(tags).filter( ([key]) => key.startsWith("fuel:"), ) as [key, tag] (key)}
|
{#each Object.entries(tags).filter( ([key]) => key.startsWith("fuel:"), ) as [key, tag] (key)}
|
||||||
<!-- <li>{key.replace("fuel:", "")}: {tag}</li> -->
|
<!-- <li>{key.replace("fuel:", "")}: {tag}</li> -->
|
||||||
@ -19,9 +20,9 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<RequiresCapability capability="fuel">
|
<RequiresCapability capability="fuel">
|
||||||
<h3 class="text-lg font-bold mt-2">Prices</h3>
|
<h3 class="text-lg font-bold mt-2">{m["sidebar.info.prices"]()}</h3>
|
||||||
{#await getStations(lat, lng)}
|
{#await getStations(lat, lng)}
|
||||||
<p>Loading fuel prices...</p>
|
<p>{m.loading()}</p>
|
||||||
{:then stations}
|
{:then stations}
|
||||||
{#if stations.stations.length > 0}
|
{#if stations.stations.length > 0}
|
||||||
{@const station = stations.stations[0]}
|
{@const station = stations.stations[0]}
|
||||||
@ -35,9 +36,9 @@
|
|||||||
<p>E5: {station.e5}</p>
|
<p>E5: {station.e5}</p>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<p>No fuel prices available.</p>
|
<p>{m["sidebar.info.no-prices"]()}</p>
|
||||||
{/if}
|
{/if}
|
||||||
{:catch err}
|
{:catch err}
|
||||||
<p>Error loading fuel prices: {err.message}</p>
|
<p>{m["sidebar.info.error-loading-prices"]()}: {err.message}</p>
|
||||||
{/await}
|
{/await}
|
||||||
</RequiresCapability>
|
</RequiresCapability>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import Badge from "$lib/components/ui/badge/badge.svelte";
|
import Badge from "$lib/components/ui/badge/badge.svelte";
|
||||||
|
|
||||||
let { tags } = $props();
|
let { tags } = $props();
|
||||||
@ -8,12 +9,12 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if tag != "no"}
|
{#if tag != "no"}
|
||||||
<h3 class="text-lg font-bold mt-2">Internet Access</h3>
|
<h3 class="text-lg font-bold mt-2">{m["sidebar.info.internet-access"]()}</h3>
|
||||||
{#each splitter as value, _index (value)}
|
{#each splitter as value, _index (value)}
|
||||||
<Badge>{value}</Badge>
|
<Badge>{value}</Badge>
|
||||||
{/each}
|
{/each}
|
||||||
{#if tags["internet_access:fee"] && tags["internet_access:fee"] != "no"}
|
{#if tags["internet_access:fee"] && tags["internet_access:fee"] != "no"}
|
||||||
<Badge>Fee: {tags["internet_access:fee"]}</Badge>
|
<Badge>{m["sidebar.info.fee"]()}: {tags["internet_access:fee"]}</Badge>
|
||||||
{/if}
|
{/if}
|
||||||
{#if tags["internet_access:ssid"]}
|
{#if tags["internet_access:ssid"]}
|
||||||
<Badge>{tags["internet_access:ssid"]}</Badge>
|
<Badge>{tags["internet_access:ssid"]}</Badge>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import Input from "$lib/components/ui/input/input.svelte";
|
import Input from "$lib/components/ui/input/input.svelte";
|
||||||
import { ai } from "$lib/services/lnv";
|
import { ai } from "$lib/services/lnv";
|
||||||
import { SparklesIcon } from "@lucide/svelte";
|
import { SparklesIcon } from "@lucide/svelte";
|
||||||
@ -23,17 +24,17 @@
|
|||||||
<SparklesIcon />
|
<SparklesIcon />
|
||||||
<div class="flex gap-2 flex-col w-full">
|
<div class="flex gap-2 flex-col w-full">
|
||||||
{#await ai(question, { lat, lon })}
|
{#await ai(question, { lat, lon })}
|
||||||
<p>Loading...</p>
|
<p>{m.loading()}</p>
|
||||||
{:then data}
|
{:then data}
|
||||||
{@const text = getText(data)}
|
{@const text = getText(data)}
|
||||||
<p>{text}</p>
|
<p>{text}</p>
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<p>Error: {error.message}</p>
|
<p>{m.error()}: {error.message}</p>
|
||||||
{/await}
|
{/await}
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
value=""
|
value=""
|
||||||
placeholder="Ask a question about this place..."
|
placeholder={m["sidebar.mapai.ask-question"]()}
|
||||||
onchange={(e) => {
|
onchange={(e) => {
|
||||||
question = (e.target! as HTMLInputElement).value;
|
question = (e.target! as HTMLInputElement).value;
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import Badge from "$lib/components/ui/badge/badge.svelte";
|
import Badge from "$lib/components/ui/badge/badge.svelte";
|
||||||
import opening_hours from "opening_hours";
|
import opening_hours from "opening_hours";
|
||||||
|
|
||||||
@ -18,11 +19,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h3 class="text-lg font-bold mt-2">
|
<h3 class="text-lg font-bold mt-2">
|
||||||
Opening Hours
|
{m["sidebar.info.opening-hours"]()}
|
||||||
{#if oh.getState()}
|
{#if oh.getState()}
|
||||||
<Badge>Open</Badge>
|
<Badge>{m["sidebar.info.open"]()}</Badge>
|
||||||
{:else}
|
{:else}
|
||||||
<Badge variant="destructive">Closed</Badge>
|
<Badge variant="destructive">{m["sidebar.info.closed"]()}</Badge>
|
||||||
{/if}
|
{/if}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import Badge from "$lib/components/ui/badge/badge.svelte";
|
import Badge from "$lib/components/ui/badge/badge.svelte";
|
||||||
|
|
||||||
let { tags } = $props();
|
let { tags } = $props();
|
||||||
@ -15,7 +16,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if matchingTags.length > 0}
|
{#if matchingTags.length > 0}
|
||||||
<h3 class="text-lg font-bold mt-2">Restaurant</h3>
|
<h3 class="text-lg font-bold mt-2">{m["sidebar.info.restaurant"]()}</h3>
|
||||||
<ul class="flex gap-2 flex-wrap">
|
<ul class="flex gap-2 flex-wrap">
|
||||||
{#each matchingTags as tag, _index (tag)}
|
{#each matchingTags as tag, _index (tag)}
|
||||||
{#if tag != "no"}
|
{#if tag != "no"}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import * as Avatar from "$lib/components/ui/avatar";
|
import * as Avatar from "$lib/components/ui/avatar";
|
||||||
import { Button } from "$lib/components/ui/button";
|
import { Button } from "$lib/components/ui/button";
|
||||||
import { getReviews, postReview } from "$lib/services/lnv";
|
import { getReviews, postReview } from "$lib/services/lnv";
|
||||||
@ -7,7 +8,7 @@
|
|||||||
let { lat, lng }: { lat: number; lng: number } = $props();
|
let { lat, lng }: { lat: number; lng: number } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h3 class="text-lg font-bold mt-2">Reviews</h3>
|
<h3 class="text-lg font-bold mt-2">{m["sidebar.info.reviews"]()}</h3>
|
||||||
{#await getReviews({ lat, lon: lng }) then reviews}
|
{#await getReviews({ lat, lon: lng }) then reviews}
|
||||||
{#if reviews.length > 0}
|
{#if reviews.length > 0}
|
||||||
<ul class="list-disc pl-5">
|
<ul class="list-disc pl-5">
|
||||||
@ -25,7 +26,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
{:else}
|
{:else}
|
||||||
<p>No reviews available.</p>
|
<p>{m["sidebar.info.no-reviews"]()}</p>
|
||||||
{/if}
|
{/if}
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@ -46,8 +47,8 @@
|
|||||||
alert("Review submission cancelled.");
|
alert("Review submission cancelled.");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled>Write a review</Button
|
disabled>{m["sidebar.info.write-review"]()}</Button
|
||||||
><br />
|
><br />
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<p>Error loading reviews: {error.message}</p>
|
<p>{m.error()}: {error.message}</p>
|
||||||
{/await}
|
{/await}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import { Button } from "$lib/components/ui/button";
|
import { Button } from "$lib/components/ui/button";
|
||||||
import {
|
import {
|
||||||
decodePolyline,
|
decodePolyline,
|
||||||
@ -122,7 +123,7 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{fullDistanceText} left
|
{fullDistanceText} {m["sidebar.in-route.left"]()}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
@ -133,12 +134,12 @@
|
|||||||
<Button
|
<Button
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
stopNavigation();
|
stopNavigation();
|
||||||
}}>End Trip</Button
|
}}>{m["sidebar.in-route.end-trip"]()}</Button
|
||||||
>
|
>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2 mt-5">
|
<div class="flex flex-col gap-2 mt-5">
|
||||||
{#if location.code}
|
{#if location.code}
|
||||||
<span>Share Code: {location.code}</span>
|
<span>{m["sidebar.in-route.share-code"]()}: {location.code}</span>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
@ -147,7 +148,7 @@
|
|||||||
location.code = null;
|
location.code = null;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Stop Sharing Location
|
{m["sidebar.in-route.stop-sharing"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{:else}
|
{:else}
|
||||||
<Button
|
<Button
|
||||||
@ -156,7 +157,7 @@
|
|||||||
advertiseRemoteLocation();
|
advertiseRemoteLocation();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Share Trip Status & Location
|
{m["sidebar.in-route.share-location"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
import { getDeveloperToggle } from "./settings/developer.svelte";
|
import { getDeveloperToggle } from "./settings/developer.svelte";
|
||||||
import InternetAccess from "../info/InternetAccess.svelte";
|
import InternetAccess from "../info/InternetAccess.svelte";
|
||||||
import RestaurantInfo from "../info/RestaurantInfo.svelte";
|
import RestaurantInfo from "../info/RestaurantInfo.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
// let { feature }: { feature: Feature } = $props();
|
// let { feature }: { feature: Feature } = $props();
|
||||||
|
|
||||||
@ -88,9 +89,9 @@
|
|||||||
pin.liftPin();
|
pin.liftPin();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Dropped Pin
|
{m["sidebar.info.dropped"]()}
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<p>Loading...</p>
|
<p>{m.loading()}</p>
|
||||||
{:then res}
|
{:then res}
|
||||||
{#if res.elements.length === 0}
|
{#if res.elements.length === 0}
|
||||||
<SidebarHeader
|
<SidebarHeader
|
||||||
@ -98,7 +99,7 @@
|
|||||||
pin.liftPin();
|
pin.liftPin();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Dropped Pin
|
{m["sidebar.info.dropped"]()}
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<span style="color: #acacac;">© OpenStreetMap</span>
|
<span style="color: #acacac;">© OpenStreetMap</span>
|
||||||
<pre>{JSON.stringify(res, null, 2)}</pre>
|
<pre>{JSON.stringify(res, null, 2)}</pre>
|
||||||
@ -132,7 +133,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RouteIcon />
|
<RouteIcon />
|
||||||
Route
|
{m["sidebar.info.route"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{#if tags.email || tags["contact:email"]}
|
{#if tags.email || tags["contact:email"]}
|
||||||
<Button
|
<Button
|
||||||
@ -141,7 +142,7 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<MailIcon />
|
<MailIcon />
|
||||||
Email
|
{m["sidebar.info.email"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if tags.website || tags["contact:website"]}
|
{#if tags.website || tags["contact:website"]}
|
||||||
@ -151,7 +152,7 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<GlobeIcon />
|
<GlobeIcon />
|
||||||
Website
|
{m["sidebar.info.website"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if tags.phone || tags["contact:phone"]}
|
{#if tags.phone || tags["contact:phone"]}
|
||||||
@ -161,14 +162,14 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<PhoneIcon />
|
<PhoneIcon />
|
||||||
Call
|
{m["sidebar.info.call"]()}
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
<Popover.Root>
|
<Popover.Root>
|
||||||
<Popover.Trigger>
|
<Popover.Trigger>
|
||||||
<Button variant="secondary">
|
<Button variant="secondary">
|
||||||
<EllipsisIcon />
|
<EllipsisIcon />
|
||||||
More
|
{m.more()}
|
||||||
</Button>
|
</Button>
|
||||||
</Popover.Trigger>
|
</Popover.Trigger>
|
||||||
<Popover.Content>
|
<Popover.Content>
|
||||||
@ -185,7 +186,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<HomeIcon />
|
<HomeIcon />
|
||||||
Set as Home
|
{m["sidebar.info.set-as"]({ name: m["saved.home"]() })}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@ -195,7 +196,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SchoolIcon />
|
<SchoolIcon />
|
||||||
Set as School
|
{m["sidebar.info.set-as"]({ name: m["saved.school"]() })}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@ -209,7 +210,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BriefcaseIcon />
|
<BriefcaseIcon />
|
||||||
Set as Work
|
{m["sidebar.info.set-as"]({ name: m["saved.work"]() })}
|
||||||
</Button>
|
</Button>
|
||||||
{#if dev.current}
|
{#if dev.current}
|
||||||
<Button
|
<Button
|
||||||
@ -255,7 +256,7 @@
|
|||||||
|
|
||||||
<!-- any payment:* tag -->
|
<!-- any payment:* tag -->
|
||||||
{#if Object.keys(tags).some((key) => key.startsWith("payment:"))}
|
{#if Object.keys(tags).some((key) => key.startsWith("payment:"))}
|
||||||
<h3 class="text-lg font-bold mt-2">Payment Methods</h3>
|
<h3 class="text-lg font-bold mt-2">{m["sidebar.info.payment-methods"]()}</h3>
|
||||||
<ul style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
|
<ul style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
|
||||||
{#each Object.entries(tags).filter( ([key]) => key.startsWith("payment:"), ) as [key, value] (key)}
|
{#each Object.entries(tags).filter( ([key]) => key.startsWith("payment:"), ) as [key, value] (key)}
|
||||||
<Badge
|
<Badge
|
||||||
|
|||||||
@ -22,12 +22,12 @@
|
|||||||
onclick={() => {
|
onclick={() => {
|
||||||
const loc = saved.home;
|
const loc = saved.home;
|
||||||
if (!loc) {
|
if (!loc) {
|
||||||
alert(m["saved.no-location"](m["saved.home"]));
|
alert(m["saved.no-location"]({ name: m["saved.home"]() }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { lat, lon } = loc;
|
const { lat, lon } = loc;
|
||||||
if (!lat || !lon) {
|
if (!lat || !lon) {
|
||||||
alert(m["saved.no-location"](m["saved.home"]));
|
alert(m["saved.no-location"]({ name: m["saved.home"]() }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pin.dropPin(lat, lon);
|
pin.dropPin(lat, lon);
|
||||||
@ -48,12 +48,12 @@
|
|||||||
console.log(saved);
|
console.log(saved);
|
||||||
const loc = saved.school;
|
const loc = saved.school;
|
||||||
if (!loc) {
|
if (!loc) {
|
||||||
alert(m["saved.no-location"](m["saved.school"]));
|
alert(m["saved.no-location"]({ name: m["saved.school"]() }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { lat, lon } = loc;
|
const { lat, lon } = loc;
|
||||||
if (!lat || !lon) {
|
if (!lat || !lon) {
|
||||||
alert(m["saved.no-location"](m["saved.school"]));
|
alert(m["saved.no-location"]({ name: m["saved.school"]() }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pin.dropPin(lat, lon);
|
pin.dropPin(lat, lon);
|
||||||
@ -73,12 +73,12 @@
|
|||||||
onclick={() => {
|
onclick={() => {
|
||||||
const loc = saved.work;
|
const loc = saved.work;
|
||||||
if (!loc) {
|
if (!loc) {
|
||||||
alert(m["saved.no-location"](m["saved.work"]));
|
alert(m["saved.no-location"]({ name: m["saved.work"]() }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { lat, lon } = loc;
|
const { lat, lon } = loc;
|
||||||
if (!lat || !lon) {
|
if (!lat || !lon) {
|
||||||
alert(m["saved.no-location"](m["saved.work"]));
|
alert(m["saved.no-location"]({ name: m["saved.work"]() }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pin.dropPin(lat, lon);
|
pin.dropPin(lat, lon);
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
} from "$lib/vehicles/vehicles.svelte";
|
} from "$lib/vehicles/vehicles.svelte";
|
||||||
import { location } from "../location.svelte";
|
import { location } from "../location.svelte";
|
||||||
import { saved } from "$lib/saved.svelte";
|
import { saved } from "$lib/saved.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
from,
|
from,
|
||||||
@ -46,11 +47,11 @@
|
|||||||
removeAllRoutes();
|
removeAllRoutes();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Route
|
{m["sidebar.route.header"]()}
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
>Driving with <strong>{(selectedVehicle() ?? DefaultVehicle).name}</strong
|
>{m["sidebar.route.driving-with"]()} <strong>{(selectedVehicle() ?? DefaultVehicle).name}</strong
|
||||||
></span
|
></span
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-2 w-full mb-2">
|
<div class="flex flex-col gap-2 w-full mb-2">
|
||||||
@ -66,9 +67,7 @@
|
|||||||
<Input bind:value={toLocation} />
|
<Input bind:value={toLocation} />
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
You can use <strong>current</strong> for your current location,
|
{@html m["sidebar.route.help"]()}
|
||||||
<strong>home</strong>
|
|
||||||
or <strong>work</strong> for saved locations.
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@ -110,7 +109,7 @@
|
|||||||
}
|
}
|
||||||
drawAllRoutes(routes);
|
drawAllRoutes(routes);
|
||||||
zoomToPoints(FROM, TO, map.value!);
|
zoomToPoints(FROM, TO, map.value!);
|
||||||
}}>Calculate</Button
|
}}>{m["sidebar.route.calculate"]()}</Button
|
||||||
>
|
>
|
||||||
|
|
||||||
{#if routes}
|
{#if routes}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
import type { Feature } from "$lib/services/Search";
|
import type { Feature } from "$lib/services/Search";
|
||||||
import SidebarHeader from "./SidebarHeader.svelte";
|
import SidebarHeader from "./SidebarHeader.svelte";
|
||||||
import { searchbar } from "../view.svelte";
|
import { searchbar } from "../view.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
results,
|
results,
|
||||||
@ -21,7 +22,7 @@
|
|||||||
searchbar.text = "";
|
searchbar.text = "";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Search Results for "{query}"
|
{m["sidebar.search.header"]()} "{query}"
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<div
|
<div
|
||||||
id="results"
|
id="results"
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
import { Button } from "$lib/components/ui/button";
|
import { Button } from "$lib/components/ui/button";
|
||||||
import { RouteIcon, SaveIcon, SendIcon } from "@lucide/svelte";
|
import { RouteIcon, SaveIcon, SendIcon } from "@lucide/svelte";
|
||||||
import { map } from "../map.svelte";
|
import { map } from "../map.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
route,
|
route,
|
||||||
@ -27,7 +28,7 @@
|
|||||||
removeAllRoutes();
|
removeAllRoutes();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Trip Details
|
{m["sidebar.trip.header"]()}
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
|
|
||||||
<div id="actions" class="flex gap-2">
|
<div id="actions" class="flex gap-2">
|
||||||
@ -40,15 +41,15 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RouteIcon />
|
<RouteIcon />
|
||||||
Start Navigation
|
{m["sidebar.trip.start"]()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="secondary" disabled>
|
<Button variant="secondary" disabled>
|
||||||
<SaveIcon />
|
<SaveIcon />
|
||||||
Save
|
{m["sidebar.trip.save"]()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="secondary" disabled>
|
<Button variant="secondary" disabled>
|
||||||
<SendIcon />
|
<SendIcon />
|
||||||
Send
|
{m["sidebar.trip.send"]()}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
import Button from "$lib/components/ui/button/button.svelte";
|
import Button from "$lib/components/ui/button/button.svelte";
|
||||||
import { getAuthURL, getOIDCUser } from "$lib/services/oidc";
|
import { getAuthURL, getOIDCUser } from "$lib/services/oidc";
|
||||||
import * as Avatar from "$lib/components/ui/avatar";
|
import * as Avatar from "$lib/components/ui/avatar";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
interface OIDCUser {
|
interface OIDCUser {
|
||||||
sub: string;
|
sub: string;
|
||||||
@ -26,7 +27,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !user}
|
{#if !user}
|
||||||
<SidebarHeader>User</SidebarHeader>
|
<SidebarHeader>{m["sidebar.user.header"]()}</SidebarHeader>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
@ -57,7 +58,7 @@
|
|||||||
atob((localStorage.getItem("lnv-id") || "").split(".")[1]),
|
atob((localStorage.getItem("lnv-id") || "").split(".")[1]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}}>Login</Button
|
}}>{m["sidebar.user.login"]()}</Button
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<SidebarHeader>
|
<SidebarHeader>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { m } from "$lang/messages";
|
||||||
import SidebarHeader from "../SidebarHeader.svelte";
|
import SidebarHeader from "../SidebarHeader.svelte";
|
||||||
import { getDeveloperToggle } from "./developer.svelte";
|
import { getDeveloperToggle } from "./developer.svelte";
|
||||||
|
|
||||||
@ -6,7 +7,7 @@
|
|||||||
const dev = getDeveloperToggle();
|
const dev = getDeveloperToggle();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SidebarHeader>About</SidebarHeader>
|
<SidebarHeader>{m["sidebar.about.header"]()}</SidebarHeader>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
@ -21,9 +22,9 @@
|
|||||||
>
|
>
|
||||||
TrafficCue
|
TrafficCue
|
||||||
</h1>
|
</h1>
|
||||||
<span>Powered by:</span>
|
<span>{m["sidebar.about.powered-by"]()}:</span>
|
||||||
<ul>
|
<ul>
|
||||||
<li>© OpenStreetMap contributors</li>
|
<li>© OpenStreetMap {m["sidebar.about.contributors"]()}</li>
|
||||||
<li>Natural Earth</li>
|
<li>Natural Earth</li>
|
||||||
<li>MapLibre</li>
|
<li>MapLibre</li>
|
||||||
<li>OpenMapTiles</li>
|
<li>OpenMapTiles</li>
|
||||||
|
|||||||
@ -6,11 +6,12 @@
|
|||||||
import { downloadPMTiles } from "$lib/services/OfflineTiles";
|
import { downloadPMTiles } from "$lib/services/OfflineTiles";
|
||||||
import { getDeveloperToggle } from "./developer.svelte";
|
import { getDeveloperToggle } from "./developer.svelte";
|
||||||
import { view } from "../../view.svelte";
|
import { view } from "../../view.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
const dev = getDeveloperToggle();
|
const dev = getDeveloperToggle();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SidebarHeader>Developer Settings</SidebarHeader>
|
<SidebarHeader>{m["sidebar.developer.header"]()}</SidebarHeader>
|
||||||
|
|
||||||
<div id="sections">
|
<div id="sections">
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@ -3,22 +3,23 @@
|
|||||||
import { DownloadCloudIcon } from "@lucide/svelte";
|
import { DownloadCloudIcon } from "@lucide/svelte";
|
||||||
import SettingsButton from "./SettingsButton.svelte";
|
import SettingsButton from "./SettingsButton.svelte";
|
||||||
import SidebarHeader from "../SidebarHeader.svelte";
|
import SidebarHeader from "../SidebarHeader.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
let progresses: Record<string, number> = $state({});
|
let progresses: Record<string, number> = $state({});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SidebarHeader>Offline Maps</SidebarHeader>
|
<SidebarHeader>{m["sidebar.offline-maps.header"]()}</SidebarHeader>
|
||||||
|
|
||||||
{#await getRemoteList()}
|
{#await getRemoteList()}
|
||||||
<p>Loading...</p>
|
<p>{m.loading()}</p>
|
||||||
{:then list}
|
{:then list}
|
||||||
<div style="display: flex; flex-direction: column; gap: 0.5rem;">
|
<div style="display: flex; flex-direction: column; gap: 0.5rem;">
|
||||||
{#if list.length === 0}
|
{#if list.length === 0}
|
||||||
<p>No offline maps available.</p>
|
<p>{m["sidebar.offline-maps.not-available"]()}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !window.__TAURI__}
|
{#if !window.__TAURI__}
|
||||||
<p>Offline maps are only available on mobile.</p>
|
<p>{m["sidebar.offline-maps.only-mobile"]()}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#each list as item, _index (item.file)}
|
{#each list as item, _index (item.file)}
|
||||||
@ -35,7 +36,7 @@
|
|||||||
progresses[item.file] = (progress / total) * 100;
|
progresses[item.file] = (progress / total) * 100;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
alert(`Downloaded ${item.name}`);
|
alert(m["sidebar.offline-maps.downloaded"]({ name: item.name }));
|
||||||
location.reload();
|
location.reload();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9,34 +9,35 @@
|
|||||||
import SidebarHeader from "../SidebarHeader.svelte";
|
import SidebarHeader from "../SidebarHeader.svelte";
|
||||||
import SettingsButton from "./SettingsButton.svelte";
|
import SettingsButton from "./SettingsButton.svelte";
|
||||||
import { getDeveloperToggle } from "./developer.svelte";
|
import { getDeveloperToggle } from "./developer.svelte";
|
||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
const dev = getDeveloperToggle();
|
const dev = getDeveloperToggle();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SidebarHeader>Settings</SidebarHeader>
|
<SidebarHeader>{m["sidebar.settings.header"]()}</SidebarHeader>
|
||||||
|
|
||||||
<div id="sections">
|
<div id="sections">
|
||||||
<section>
|
<section>
|
||||||
<h2>General</h2>
|
<h2>{m["sidebar.settings.general"]()}</h2>
|
||||||
<SettingsButton icon={LanguagesIcon} text="Language" disabled />
|
<SettingsButton icon={LanguagesIcon} text={m["sidebar.language.header"]()} disabled />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Map</h2>
|
<h2>{m["sidebar.settings.map"]()}</h2>
|
||||||
<SettingsButton icon={MapIcon} text="Offline Maps" view="offline-maps" />
|
<SettingsButton icon={MapIcon} text={m["sidebar.offline-maps.header"]()} view="offline-maps" />
|
||||||
<SettingsButton icon={PaintbrushIcon} text="Map Style" disabled />
|
<SettingsButton icon={PaintbrushIcon} text={m["sidebar.map-style.header"]()} disabled />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>About</h2>
|
<h2>{m["sidebar.about.header"]()}</h2>
|
||||||
{#if dev.current == "true"}
|
{#if dev.current == "true"}
|
||||||
<SettingsButton
|
<SettingsButton
|
||||||
icon={CodeIcon}
|
icon={CodeIcon}
|
||||||
text="Developer Settings"
|
text={m["sidebar.developer.header"]()}
|
||||||
view="dev-options"
|
view="dev-options"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<SettingsButton icon={InfoIcon} text="About" view="about" />
|
<SettingsButton icon={InfoIcon} text={m["sidebar.about.header"]()} view="about" />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { m } from "$lang/messages";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Valhalla costing:
|
Valhalla costing:
|
||||||
auto, prioritizes motorways = car, (truck), motorcycle
|
auto, prioritizes motorways = car, (truck), motorcycle
|
||||||
@ -57,7 +59,7 @@ export interface Vehicle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultVehicle: Vehicle = {
|
export const DefaultVehicle: Vehicle = {
|
||||||
name: "Default Vehicle",
|
name: m["vehicles.default"](),
|
||||||
legalMaxSpeed: 45,
|
legalMaxSpeed: 45,
|
||||||
actualMaxSpeed: 45,
|
actualMaxSpeed: 45,
|
||||||
type: "motor_scooter",
|
type: "motor_scooter",
|
||||||
|
|||||||
Reference in New Issue
Block a user