This repository has been archived on 2025-11-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
trafficcue-client/src/lib/components/lnv/sidebar/RouteSidebar.svelte
Cfp 03b129f947
Some checks failed
TrafficCue CI / check (push) Failing after 47s
TrafficCue CI / build (push) Failing after 41s
feat: location selector in route UI
2025-08-21 15:45:16 +02:00

129 lines
3.3 KiB
Svelte

<script lang="ts">
import { CircleArrowDown, CircleDotIcon, StarIcon } from "@lucide/svelte";
import Input from "$lib/components/ui/input/input.svelte";
import SidebarHeader from "./SidebarHeader.svelte";
import { Button } from "$lib/components/ui/button";
import { createValhallaRequest } from "$lib/vehicles/ValhallaVehicles";
import {
drawAllRoutes,
fetchRoute,
removeAllRoutes,
zoomToPoints,
} from "$lib/services/navigation/routing.svelte";
import { ROUTING_SERVER } from "$lib/services/hosts";
import { map } from "../map.svelte";
import { view } from "../view.svelte";
import {
DefaultVehicle,
selectedVehicle,
} from "$lib/vehicles/vehicles.svelte";
import { location } from "../location.svelte";
import { saved } from "$lib/saved.svelte";
import { m } from "$lang/messages";
import LocationSelect from "../LocationSelect.svelte";
let {
from,
to,
}: {
from?: string;
to?: string;
} = $props();
let fromLocation = $state(from || "current");
let toLocation = $state(to || "");
let routes: Trip[] | null = $state(null);
function formatTime(seconds: number) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
// const secs = seconds % 60;
return `${hours != 0 ? hours + "h " : ""}${minutes}min`;
}
</script>
<SidebarHeader
onback={() => {
removeAllRoutes();
}}
>
{m["sidebar.route.header"]()}
</SidebarHeader>
<span
>{m["sidebar.route.driving-with"]()}
<strong>{(selectedVehicle() ?? DefaultVehicle).name}</strong></span
>
<div class="flex flex-col gap-2 w-full mb-2">
<div class="flex gap-2 items-center w-full">
<CircleDotIcon />
<LocationSelect bind:value={fromLocation} />
</div>
<div class="flex items-center justify-center w-full">
<CircleArrowDown />
</div>
<div class="flex gap-2 items-center w-full">
<CircleDotIcon />
<LocationSelect bind:value={toLocation} />
</div>
</div>
<Button
onclick={async () => {
console.log(fromLocation, toLocation);
const FROM: WorldLocation =
fromLocation == "current"
? { lat: location.lat, lon: location.lng }
: saved[fromLocation]
? saved[fromLocation]
: {
lat: parseFloat(fromLocation.split(",")[0]),
lon: parseFloat(fromLocation.split(",")[1]),
};
const TO: WorldLocation =
toLocation == "current"
? { lat: location.lat, lon: location.lng }
: saved[toLocation]
? saved[toLocation]
: {
lat: parseFloat(toLocation.split(",")[0]),
lon: parseFloat(toLocation.split(",")[1]),
};
const req = createValhallaRequest(selectedVehicle() ?? DefaultVehicle, [
FROM,
TO,
]);
const res = await fetchRoute(ROUTING_SERVER, req);
routes = [res.trip];
if (res.alternates) {
for (const alternate of res.alternates) {
if (alternate.trip) {
routes.push(alternate.trip);
}
}
}
drawAllRoutes(routes);
zoomToPoints(FROM, TO, map.value!);
}}>{m["sidebar.route.calculate"]()}</Button
>
{#if routes}
<div class="mt-2 flex gap-2 flex-col">
{#each routes as route, i (route?.summary?.length)}
<Button
variant="secondary"
onclick={() => {
view.switch("trip", { route });
}}
>
{#if i == 0}
<StarIcon />
{/if}
{Math.round(route.summary.length)}km - {formatTime(
Math.round(route.summary.time),
)}
</Button>
{/each}
</div>
{/if}