Add station modal logic and station data for part of route 0210
This commit is contained in:
@@ -57,7 +57,12 @@
|
||||
<div class="list-container">
|
||||
<a href="https://owlboard.info" class="button-link">Go to OwlBoard Live Departures & PIS</a>
|
||||
|
||||
<input type="text" bind:value={searchTerm} placeholder="Search Station/Jn" class="search-input" />
|
||||
<input
|
||||
type="text"
|
||||
bind:value={searchTerm}
|
||||
placeholder="Search Station/Jn"
|
||||
class="search-input"
|
||||
/>
|
||||
{#each filteredMaps as map (map.routeId)}
|
||||
<a
|
||||
href={resolve(`/map/${map.routeId.toString().padStart(4, '0')}`)}
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
<script lang="ts">
|
||||
import RouteRow from '$lib/components/RouteRow.svelte';
|
||||
import RouteEndLink from '$lib/components/mapIcons/RouteEndLink.svelte';
|
||||
import StationInfo from '$lib/components/StationInfo.svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { resolve } from '$app/paths';
|
||||
|
||||
import logo from '$lib/assets/round-logo.svg';
|
||||
import { IconArrowsExchange, IconSettings } from '@tabler/icons-svelte';
|
||||
import { IconArrowsExchange, IconSettings } from '@tabler/icons-svelte';
|
||||
|
||||
// data.route contains: routeStart, routeEnd, routeId, elecStart, elecEnd, routeDetail[]
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
let reversed = false; // Reverses Array, and passes value down to children
|
||||
let activeCrs = $state<string | null>(null);
|
||||
let isModalOpen = $derived(activeCrs !== null);
|
||||
|
||||
let visibleTypes = {
|
||||
function openStationModal(crs: string) {
|
||||
activeCrs = crs;
|
||||
}
|
||||
|
||||
function closeStationModal() {
|
||||
activeCrs = null;
|
||||
}
|
||||
|
||||
let reversed = $state(false); // Reverses Array, and passes value down to children
|
||||
|
||||
let visibleTypes = $state({
|
||||
station: true,
|
||||
minorBridge: false,
|
||||
bridge: true,
|
||||
@@ -23,10 +35,10 @@
|
||||
siteof: true,
|
||||
junction: true,
|
||||
tunnel: true,
|
||||
crossing: true,
|
||||
};
|
||||
crossing: true
|
||||
});
|
||||
|
||||
let showFilters = false;
|
||||
let showFilters = $state(false);
|
||||
|
||||
// Toggle feature types
|
||||
const toggleFilter = (type: string) => {
|
||||
@@ -38,31 +50,29 @@
|
||||
const formatLabel = (str: string) =>
|
||||
str.replace(/([A-Z])/g, ' $1').replace(/^./, (s) => s.toUpperCase());
|
||||
|
||||
$: processedFeatures = (() => {
|
||||
const processedFeatures = $derived.by(() => {
|
||||
const list = reversed ? [...data.route.routeDetail].reverse() : [...data.route.routeDetail];
|
||||
|
||||
// Seed currentElec from the YAML header boundary
|
||||
let currentElec = reversed ? data.route.elecEnd.elec : data.route.elecStart.elec;
|
||||
|
||||
return list.map((f) => {
|
||||
if (f.type === 'electrificationChange') {
|
||||
// Transition state: this tile and everything after it
|
||||
// adopts the new electrification.
|
||||
currentElec = reversed ? f.from.elec : f.to.elec;
|
||||
}
|
||||
|
||||
return {
|
||||
...f,
|
||||
activeElec: currentElec
|
||||
};
|
||||
});
|
||||
})();
|
||||
|
||||
$: filteredFeatures = processedFeatures.filter((f) => {
|
||||
return visibleTypes[f.type] ?? true;
|
||||
});
|
||||
|
||||
const filteredFeatures = $derived(processedFeatures.filter((f) => visibleTypes[f.type] ?? true));
|
||||
</script>
|
||||
|
||||
{#if isModalOpen && activeCrs}
|
||||
<StationInfo crs={activeCrs} onclose={closeStationModal} />
|
||||
{/if}
|
||||
|
||||
<div class="map-layout">
|
||||
<header class="top-nav">
|
||||
<div class="nav-cluster">
|
||||
@@ -76,8 +86,8 @@
|
||||
{reversed ? data.route.routeEnd : data.route.routeStart}
|
||||
</h1>
|
||||
<span class="secondary-station">
|
||||
<span class="route-stack-to">
|
||||
to</span> {reversed ? data.route.routeStart : data.route.routeEnd}
|
||||
<span class="route-stack-to"> to</span>
|
||||
{reversed ? data.route.routeStart : data.route.routeEnd}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -87,7 +97,9 @@
|
||||
<button class="icon-btn" onclick={() => (reversed = !reversed)}>
|
||||
<IconArrowsExchange />
|
||||
</button>
|
||||
<button class="icon-btn" onclick={() => (showFilters = !showFilters)}> <IconSettings /> </button>
|
||||
<button class="icon-btn" onclick={() => (showFilters = !showFilters)}>
|
||||
<IconSettings />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -139,7 +151,12 @@
|
||||
{#if f.type === 'continues'}
|
||||
<RouteEndLink feature={f} />
|
||||
{:else}
|
||||
<RouteRow feature={f} activeElec={f.activeElec} {reversed} />
|
||||
<RouteRow
|
||||
feature={f}
|
||||
activeElec={f.activeElec}
|
||||
{reversed}
|
||||
onShowInfo={openStationModal}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
@@ -212,7 +229,7 @@
|
||||
|
||||
.route-stack {
|
||||
display: flex;
|
||||
font-family: "urwgothic";
|
||||
font-family: 'urwgothic';
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
margin-left: 0;
|
||||
@@ -250,7 +267,7 @@
|
||||
}
|
||||
|
||||
@media (min-width: 536px) {
|
||||
.primary-station {
|
||||
.primary-station {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.secondary-station {
|
||||
|
||||
@@ -20,9 +20,8 @@ export const load: PageLoad = async ({ params }) => {
|
||||
|
||||
return {
|
||||
route: rawData,
|
||||
slug: slug,
|
||||
slug: slug
|
||||
};
|
||||
|
||||
} catch (err) {
|
||||
console.error(`Error loading map ${slug}: `, err);
|
||||
throw error(500, {
|
||||
|
||||
Reference in New Issue
Block a user