Adjust display logic
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ApiStationsBoard } from '@owlboard/owlboard-ts';
|
import type { ApiStationsBoard } from '@owlboard/owlboard-ts';
|
||||||
import { formatUkTime, estClass, delayClassFromTimePair } from '$lib/utils/time';
|
import { formatUkTime, estClass, delayClassFromTimePair, isRightTime } from '$lib/utils/time';
|
||||||
import { fade, slide, fly } from 'svelte/transition';
|
import { fade, slide, fly } from 'svelte/transition';
|
||||||
import { flip } from 'svelte/animate';
|
import { flip } from 'svelte/animate';
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="departure-board">
|
<section class="departure-board">
|
||||||
<div class="header">
|
<div class="header container">
|
||||||
<div class="header row">
|
<div class="header row">
|
||||||
<div class="upper-header-blank"></div>
|
<div class="upper-header-blank"></div>
|
||||||
<div class="upper-header-text">Arr</div>
|
<div class="upper-header-text">Arr</div>
|
||||||
@@ -36,9 +36,14 @@
|
|||||||
<div
|
<div
|
||||||
class="service-block"
|
class="service-block"
|
||||||
animate:flip={{ duration: 400 }}
|
animate:flip={{ duration: 400 }}
|
||||||
transition:slide={{duration:300}}
|
transition:slide={{ duration: 300 }}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="service row"
|
||||||
|
class:passing={service.wtp}
|
||||||
|
class:nonPax={!service.ip}
|
||||||
|
class:cancelled={service.c}
|
||||||
>
|
>
|
||||||
<div class="service row">
|
|
||||||
<div class="cell id">{service.h}</div>
|
<div class="cell id">{service.h}</div>
|
||||||
<div class="cell orig">
|
<div class="cell orig">
|
||||||
{#key service.og.t}
|
{#key service.og.t}
|
||||||
@@ -50,7 +55,7 @@
|
|||||||
<div class="cell dest">
|
<div class="cell dest">
|
||||||
{#key service.dt.t}<div transition:fade={{ duration: 300 }}>{service.dt.t}</div>{/key}
|
{#key service.dt.t}<div transition:fade={{ duration: 300 }}>{service.dt.t}</div>{/key}
|
||||||
</div>
|
</div>
|
||||||
<div class="cell plt">
|
<div class="cell plt" class:platsup={service.ps} class:platchange={service.pc}>
|
||||||
{#key service.p}<div transition:fade={{ duration: 300 }}>{service.p || '-'}</div>{/key}
|
{#key service.p}<div transition:fade={{ duration: 300 }}>{service.p || '-'}</div>{/key}
|
||||||
</div>
|
</div>
|
||||||
{#if service.wtp}
|
{#if service.wtp}
|
||||||
@@ -58,35 +63,47 @@
|
|||||||
<div class="cell sch">
|
<div class="cell sch">
|
||||||
{formatUkTime(service.wtp)}
|
{formatUkTime(service.wtp)}
|
||||||
</div>
|
</div>
|
||||||
<div class="cell act">
|
<div
|
||||||
{#key realPass}
|
class="cell act {estClass(service.atp, service.etp)} {delayClassFromTimePair(service.wtp, service.atp || service.etp)}"
|
||||||
<div transition:fade={{ duration: 300 }}>
|
>
|
||||||
|
{#if isRightTime(service.wtp, service.atp || service.etp)}
|
||||||
|
RT
|
||||||
|
{:else if service.c}
|
||||||
|
CANC
|
||||||
|
{:else}
|
||||||
{realPass}
|
{realPass}
|
||||||
</div>
|
{/if}
|
||||||
{/key}
|
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="cell sch">{formatUkTime(service.sta)}</div>
|
<div class="cell sch">{formatUkTime(service.sta)}</div>
|
||||||
<div class="cell act">
|
<div
|
||||||
{#key realArrival}
|
class="cell act {estClass(service.ata, service.eta)} {delayClassFromTimePair(service.sta, service.ata || service.eta)}"
|
||||||
<div transition:fade={{ duration: 300 }}>
|
>
|
||||||
|
{#if isRightTime(service.sta, service.ata || service.eta)}
|
||||||
|
RT
|
||||||
|
{:else if service.sta && service.c} CAN {:else}
|
||||||
{realArrival}
|
{realArrival}
|
||||||
</div>
|
{/if}
|
||||||
{/key}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="cell sch">{formatUkTime(service.std)}</div>
|
<div class="cell sch">{formatUkTime(service.std)}</div>
|
||||||
<div class="cell act">
|
<div class="cell act {estClass(service.atd, service.etd)} {delayClassFromTimePair(service.std, service.atd || service.etd)}">
|
||||||
{#key realDeparture}
|
{#if isRightTime(service.std, service.atd || service.etd)}
|
||||||
<div transition:fade={{ duration: 300 }}>
|
RT
|
||||||
|
{:else if service.std && service.c} CANC {:else}
|
||||||
{realDeparture}
|
{realDeparture}
|
||||||
</div>
|
{/if}
|
||||||
{/key}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="operator row">{service.o}</div>
|
<div class="operator row">{service.o}</div>
|
||||||
{#if service?.cr?.r}
|
{#if service?.cr?.r}
|
||||||
|
{#if service.c}
|
||||||
<div class="cancel-reason row" transition:slide={{ duration: 300 }}>{service.cr.r}</div>
|
<div class="cancel-reason row" transition:slide={{ duration: 300 }}>{service.cr.r}</div>
|
||||||
|
{:else}
|
||||||
|
<div class="cancel-reason row" transition:slide={{ duration: 300 }}>
|
||||||
|
Part of this service has been cancelled
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{:else if service?.dr?.r}
|
{:else if service?.dr?.r}
|
||||||
<div class="delay-reason row" transition:slide={{ duration: 300 }}>{service.dr.r}</div>
|
<div class="delay-reason row" transition:slide={{ duration: 300 }}>{service.dr.r}</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -104,6 +121,13 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header.container {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 2;
|
||||||
|
background: var(--color-bg-dark);
|
||||||
|
}
|
||||||
|
|
||||||
.row.header {
|
.row.header {
|
||||||
font-weight: 875;
|
font-weight: 875;
|
||||||
}
|
}
|
||||||
@@ -131,6 +155,17 @@
|
|||||||
font-variant-ligatures: additional-ligatures;
|
font-variant-ligatures: additional-ligatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.service.row.passing {
|
||||||
|
font-style: italic;
|
||||||
|
opacity: 0.25;
|
||||||
|
font-weight: 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service.row.nonPax {
|
||||||
|
opacity: 0.25;
|
||||||
|
font-weight: 200;
|
||||||
|
}
|
||||||
|
|
||||||
.service-block {
|
.service-block {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -142,52 +177,11 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.departure-board td {
|
|
||||||
font-family: 'Inconsolata Variable', monospace;
|
|
||||||
font-size: clamp(1rem, 0.475rem + 2.8vw, 1.35rem);
|
|
||||||
font-variant-ligatures: additional-ligatures;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead,
|
|
||||||
.cancel-row td,
|
|
||||||
.delay-row td {
|
|
||||||
letter-spacing: -0.15ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 2;
|
|
||||||
background: var(--color-bg-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
abbr {
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: none;
|
|
||||||
cursor: help;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:first-child td {
|
|
||||||
border-top: 5px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Row Logic */
|
/* Row Logic */
|
||||||
.serviceCancelled {
|
.service.cancelled {
|
||||||
color: rgb(255, 131, 131);
|
color: rgb(255, 131, 131);
|
||||||
}
|
}
|
||||||
|
|
||||||
.servicePass td {
|
|
||||||
opacity: 0.75;
|
|
||||||
font-weight: 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
.serviceNonPassenger td {
|
|
||||||
opacity: 0.5;
|
|
||||||
font-weight: 290;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Special Row Styles */
|
/* Special Row Styles */
|
||||||
.operator.row,
|
.operator.row,
|
||||||
.delay-reason.row,
|
.delay-reason.row,
|
||||||
@@ -200,11 +194,13 @@
|
|||||||
.cancel-reason.row {
|
.cancel-reason.row {
|
||||||
color: rgb(255, 131, 131);
|
color: rgb(255, 131, 131);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
letter-spacing: -0.1ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delay-reason.row {
|
.delay-reason.row {
|
||||||
color: var(--delay-orange);
|
color: var(--delay-orange);
|
||||||
font-style: italic;
|
font-weight: 400;
|
||||||
|
letter-spacing: -0.1ch;
|
||||||
}
|
}
|
||||||
@media (min-width: 375px) {
|
@media (min-width: 375px) {
|
||||||
.operator.row,
|
.operator.row,
|
||||||
@@ -314,16 +310,12 @@
|
|||||||
font-stretch: 110%;
|
font-stretch: 110%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cell.plt.platSup {
|
.cell.plt.platsup {
|
||||||
font-weight: 200;
|
font-weight: 150;
|
||||||
opacity: 0.3;
|
|
||||||
}
|
}
|
||||||
.cell.plt.platChange {
|
.cell.plt.platchange {
|
||||||
animation: fast-pulse 2s ease-out infinite;
|
animation: fast-pulse 2s ease-out infinite;
|
||||||
}
|
}
|
||||||
.service-row.serviceCancelled .plt-cell {
|
|
||||||
text-decoration: line-through;
|
|
||||||
}
|
|
||||||
.pass-cell {
|
.pass-cell {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-stretch: 100%;
|
font-stretch: 100%;
|
||||||
@@ -343,6 +335,12 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
font-stretch: 72%;
|
font-stretch: 72%;
|
||||||
}
|
}
|
||||||
|
.cell.act.delay-late {
|
||||||
|
color: var(--delay-orange);
|
||||||
|
}
|
||||||
|
.cell.act.delay-early {
|
||||||
|
color: var(--early-blue);
|
||||||
|
}
|
||||||
@media (min-width: 350px) {
|
@media (min-width: 350px) {
|
||||||
.cell.sch,
|
.cell.sch,
|
||||||
.cell.act {
|
.cell.act {
|
||||||
@@ -367,21 +365,10 @@
|
|||||||
font-stretch: 100%;
|
font-stretch: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.cell.act.est {
|
||||||
/* RT Logic */
|
font-style: italic;
|
||||||
.time-cell.delay-rt span {
|
font-weight: 300;
|
||||||
display: none;
|
opacity: 0.5;
|
||||||
}
|
|
||||||
.time-cell.delay-rt::after {
|
|
||||||
content: 'RT';
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-cell.delay-early {
|
|
||||||
color: var(--early-blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-cell.delay-late {
|
|
||||||
color: var(--delay-orange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Time Types */
|
/* Time Types */
|
||||||
@@ -390,7 +377,7 @@
|
|||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
font-weight: 350;
|
font-weight: 350;
|
||||||
}
|
}
|
||||||
.cell.act {
|
.cell.act.actual {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { ApiTrainsTrainDetails } from '@owlboard/owlboard-ts';
|
import type { ApiTrainsTrainDetails } from '@owlboard/owlboard-ts';
|
||||||
|
|
||||||
export const estClass = (act: any, est: any) => (act ? 'act' : 'est');
|
export const estClass = (act: any, est: any) => (act ? 'actual' : 'estimate');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts ISO/JSON time to UK-formatted HH:MM string, with optional (default off) seconds
|
* Converts ISO/JSON time to UK-formatted HH:MM string, with optional (default off) seconds
|
||||||
@@ -132,3 +132,23 @@ export function delayClassFromTimePair(sched: any, act: any): string {
|
|||||||
|
|
||||||
return diff > 0 ? 'delay-late' : 'delay-early';
|
return diff > 0 ? 'delay-late' : 'delay-early';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a pair of times (string or Date) and returns true if service considered 'on-time'
|
||||||
|
* @param sched Scheduled Time (string, Date)
|
||||||
|
* @param act Actual Time (string, Date)
|
||||||
|
*/
|
||||||
|
export function isRightTime(
|
||||||
|
sched: string | Date | undefined,
|
||||||
|
act: string | Date | undefined
|
||||||
|
): boolean {
|
||||||
|
console.log(`Checking [sched: ${sched}, act: ${act}]`);
|
||||||
|
if (!sched || !act) return false;
|
||||||
|
|
||||||
|
const s = new Date(sched).getTime();
|
||||||
|
const a = new Date(act).getTime();
|
||||||
|
|
||||||
|
if (isNaN(s) || isNaN(a)) return false;
|
||||||
|
|
||||||
|
return Math.abs(a - s) < 60000;
|
||||||
|
}
|
||||||
|
|||||||
@@ -130,6 +130,10 @@
|
|||||||
<div class="service-list-wrapper">
|
<div class="service-list-wrapper">
|
||||||
<StaffServicesGrid services={data.boardData.data.s} />
|
<StaffServicesGrid services={data.boardData.data.s} />
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="no-service">
|
||||||
|
No services at this location in the next three hours
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -145,6 +149,13 @@
|
|||||||
gap: 0;
|
gap: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-service {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
max-width: 75%;
|
||||||
|
font-family: 'URW Gothic', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
.time-data {
|
.time-data {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user