Compare commits
2 Commits
v3.0.0-dev
...
v3.0.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 91cb119b7d | |||
| 26e40c5bf6 |
1806
package-lock.json
generated
1806
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,7 @@
|
|||||||
"vitest-browser-svelte": "^2.0.2"
|
"vitest-browser-svelte": "^2.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@owlboard/owlboard-ts": "^3.0.0-dev.20260428T2753",
|
"@owlboard/owlboard-ts": "^3.0.0-dev.20260503T0051",
|
||||||
"@tabler/icons-svelte": "^3.40.0"
|
"@tabler/icons-svelte": "^3.40.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
src/lib/components/ui/Loading.svelte
Normal file
59
src/lib/components/ui/Loading.svelte
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
let {
|
||||||
|
message = "Loading..."
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="loading-state">
|
||||||
|
<div class="track">
|
||||||
|
<div class="shuttle"></div>
|
||||||
|
</div>
|
||||||
|
<p>{message}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.loading-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
width: 75%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track {
|
||||||
|
width: 160px;
|
||||||
|
height: 3px;
|
||||||
|
background-color: var(--color-title);
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shuttle {
|
||||||
|
position: absolute;
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: linear-gradient(90deg, #1abc9c 0%, #3498db 100%);
|
||||||
|
animation: data-travel 1.6s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-family: 'URW Gothic', sans-serif;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: var(--color-title);
|
||||||
|
animation: pulse 2s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes data-travel {
|
||||||
|
0% { left: -50%; }
|
||||||
|
100% { left: 100%; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {opacity: 1;}
|
||||||
|
50% {opacity: 0.4;}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -22,8 +22,22 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
|
font-size: 1.1rem;
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
font-family:'Courier New', Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AW {
|
||||||
|
/* Transport for Wales */
|
||||||
|
background: red;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LM {
|
||||||
|
/* West Midlands Trains */
|
||||||
|
background: rgb(176, 115, 1);
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.GW {
|
.GW {
|
||||||
@@ -44,6 +58,12 @@
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.GN {
|
||||||
|
/* Great Northern */
|
||||||
|
background-color: fuchsia;
|
||||||
|
color: rgb(229, 229, 229);
|
||||||
|
}
|
||||||
|
|
||||||
.SW {
|
.SW {
|
||||||
/* South Western Railway */
|
/* South Western Railway */
|
||||||
background-color: #2a3389;
|
background-color: #2a3389;
|
||||||
|
|||||||
@@ -1,15 +1,51 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ApiTrainsTrainByHeadcode } from '@owlboard/owlboard-ts';
|
import type { ApiTrainsTrainByHeadcode } from '@owlboard/owlboard-ts';
|
||||||
import { slide } from 'svelte/transition';
|
import { OwlClient, ApiError, ValidationError } from '$lib/owlClient';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
import { quintOut} from 'svelte/easing';
|
||||||
import { formatUkTime } from '$lib/utils/time';
|
import { formatUkTime } from '$lib/utils/time';
|
||||||
import TocStyle from '$lib/components/ui/TocStyle.svelte';
|
import TocStyle from '$lib/components/ui/TocStyle.svelte';
|
||||||
|
|
||||||
let { service }: { service: ApiTrainsTrainByHeadcode.TrainByHeadcodeResponse} = $props();
|
let { service }: { service: ApiTrainsTrainByHeadcode.TrainByHeadcodeResponse} = $props();
|
||||||
let isExpanded = $state(false);
|
let isExpanded = $state(false);
|
||||||
|
let loadingDetails = $state(false)
|
||||||
|
let details = $state(null);
|
||||||
|
|
||||||
|
const toggleExpand = async (rid: string) => {
|
||||||
|
if (isExpanded) {
|
||||||
|
isExpanded = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details) {
|
||||||
|
isExpanded = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadingDetails = true;
|
||||||
|
try {
|
||||||
|
const result = await OwlClient.trains.getByRid(service.r)
|
||||||
|
details = result.data;
|
||||||
|
isExpanded = true;
|
||||||
|
} catch (e) {
|
||||||
|
console.Error("Failde to load train details")
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const toggleExpand = () => isExpanded = !isExpanded;
|
|
||||||
|
|
||||||
let OriginDepartureSummary = $derived(formatUkTime(service.od));
|
let OriginDepartureSummary = $derived(formatUkTime(service.od));
|
||||||
|
|
||||||
|
async function loadDetails(rid: string) {
|
||||||
|
if (details) return;
|
||||||
|
loadingDetails = true;
|
||||||
|
|
||||||
|
const result = await OwlClient.trains.getByRid(service.r)
|
||||||
|
details = result.data;
|
||||||
|
loadingDetails = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="train-service">
|
<div class="train-service">
|
||||||
@@ -30,8 +66,16 @@ import { formatUkTime } from '$lib/utils/time';
|
|||||||
<div class="location-summary">
|
<div class="location-summary">
|
||||||
{service.dt}
|
{service.dt}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Add arrow icon to signify drop-down -->
|
||||||
|
<!-- ADD LOADING STATE -->
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
{#if isExpanded && details}
|
||||||
|
<div transition:slide={{duration: 800, easing: quintOut}} class="detauls-content">
|
||||||
|
<!-- Here goes the data formatting! -->
|
||||||
|
{JSON.stringify(details)}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -42,6 +86,12 @@ import { formatUkTime } from '$lib/utils/time';
|
|||||||
box-shadow: var(--shadow-std);
|
box-shadow: var(--shadow-std);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: 'URW Gothic', sans-serif;
|
font-family: 'URW Gothic', sans-serif;
|
||||||
|
transition: 0.2s all;
|
||||||
|
filter: brightness(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.train-service:hover {
|
||||||
|
filter:brightness(1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary {
|
.summary {
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { slide, fade } from 'svelte/transition';
|
import { slide, fade } from 'svelte/transition';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { navigating } from '$app/state';
|
||||||
import { LOCATIONS } from '$lib/locations-object.svelte';
|
import { LOCATIONS } from '$lib/locations-object.svelte';
|
||||||
import { nearestStationsState } from '$lib/geohash.svelte';
|
import { nearestStationsState } from '$lib/geohash.svelte';
|
||||||
|
|
||||||
|
import Loading from '$lib/components/ui/Loading.svelte';
|
||||||
import TimezoneWarning from '$lib/components/ui/TimezoneWarning.svelte';
|
import TimezoneWarning from '$lib/components/ui/TimezoneWarning.svelte';
|
||||||
|
|
||||||
import '$lib/global.css';
|
import '$lib/global.css';
|
||||||
@@ -81,7 +82,12 @@
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<TimezoneWarning />
|
<TimezoneWarning />
|
||||||
{@render children()}
|
|
||||||
|
{#if navigating && navigating.to}
|
||||||
|
<Loading />
|
||||||
|
{:else}
|
||||||
|
{@render children()}
|
||||||
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<nav bind:clientWidth={navWidth}>
|
<nav bind:clientWidth={navWidth}>
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
import NoResults from '$lib/components/ui/NoResults.svelte';
|
import NoResults from '$lib/components/ui/NoResults.svelte';
|
||||||
import TrainService from '$lib/components/ui/TrainService.svelte';
|
import TrainService from '$lib/components/ui/TrainService.svelte';
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{#if data.results.length === 0}
|
{#if data.results.length === 0}
|
||||||
<NoResults
|
<NoResults
|
||||||
message={"No trains found on this date with this headcode."}
|
message={"No trains found on this date with this headcode."}
|
||||||
@@ -21,6 +24,7 @@
|
|||||||
width: 95%;
|
width: 95%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
|
padding-bottom: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user