♻️ Replace methods called to render Component with small Components
This commit is contained in:
@@ -1,14 +1,56 @@
|
||||
import { Component } from 'solid-js';
|
||||
import { Component, createEffect, createResource, createSignal, useContext } from 'solid-js';
|
||||
import { createDateNow, getTime } from '@solid-primitives/date';
|
||||
import { Motion } from "@motionone/solid";
|
||||
|
||||
import { TrafficStatus } from './types';
|
||||
import { renderLineTransportMode, renderLinePicto } from './utils';
|
||||
|
||||
import { BusinessDataContext } from "./businessData";
|
||||
|
||||
import styles from "./passagesPanel.module.css";
|
||||
|
||||
|
||||
export const PassagesPanel: Component = (props) => {
|
||||
const TtwPassage: Component = (props) => {
|
||||
|
||||
const [dateNow] = createDateNow(5000);
|
||||
|
||||
const refTs = props.passage.expectedDepartTs !== null ? props.passage.expectedDepartTs : props.passage.expectedArrivalTs;
|
||||
const ttwSec = refTs - (getTime(dateNow()) / 1000);
|
||||
const isApproaching = ttwSec <= 60;
|
||||
|
||||
return (
|
||||
<div class={props.style}>
|
||||
<svg viewBox={`0 0 215 ${props.fontSize}`}>
|
||||
<Motion.text
|
||||
x="100%" y="55%"
|
||||
dominant-baseline="middle" text-anchor="end"
|
||||
font-size={props.fontSize} style={{ fill: "#000000" }}
|
||||
initial={isApproaching}
|
||||
animate={{ opacity: [1, 0, 1] }}
|
||||
transition={{ duration: 3, repeat: Infinity }}>
|
||||
{Math.floor(ttwSec / 60)} min
|
||||
</Motion.text>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const UnavailablePassage: Component = (props) => {
|
||||
const textStyle = { fill: "#000000" };
|
||||
|
||||
return (
|
||||
<div class={props.style}>
|
||||
<svg viewbox="0 0 230 110">
|
||||
<text x="100%" y="26" font-size="25" text-anchor="end" style={textStyle}>Information</text>
|
||||
<text x="100%" y="63" font-size="25" text-anchor="end" style={textStyle}>non</text>
|
||||
<text x="100%" y="100" font-size="25" text-anchor="end" style={textStyle}>disponible</text>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/* TODO: Manage end of service */
|
||||
const Passages: Component = (props) => {
|
||||
|
||||
/* TODO: Find where to get data to compute traffic status. */
|
||||
const trafficStatusColor = new Map<TrafficStatus, string>([
|
||||
@@ -19,102 +61,71 @@ export const PassagesPanel: Component = (props) => {
|
||||
[TrafficStatus.BYPASSED, "#ffffff"]
|
||||
]);
|
||||
|
||||
const [dateNow] = createDateNow(5000);
|
||||
const passagesLength = props.passages.length;
|
||||
const firstPassage = passagesLength > 0 ? props.passages[0] : undefined;
|
||||
const secondPassage = passagesLength > 1 ? props.passages[1] : undefined;
|
||||
const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
|
||||
|
||||
function _computeTtwPassage(class_, passage, fontSize) {
|
||||
const refTs = passage.expectedDepartTs !== null ? passage.expectedDepartTs : passage.expectedArrivalTs;
|
||||
const ttwSec = refTs - (getTime(dateNow()) / 1000);
|
||||
const isApproaching = ttwSec <= 60;
|
||||
return (
|
||||
<div class={class_}>
|
||||
<svg viewBox={`0 0 215 ${fontSize}`}>
|
||||
<Motion.text
|
||||
x="100%" y="55%"
|
||||
dominant-baseline="middle" text-anchor="end"
|
||||
font-size={fontSize} style={{ fill: "#000000" }}
|
||||
initial={isApproaching}
|
||||
animate={{ opacity: [1, 0, 1] }}
|
||||
transition={{ duration: 3, repeat: Infinity }}>
|
||||
{Math.floor(ttwSec / 60)} min
|
||||
</Motion.text>
|
||||
return (
|
||||
<div class={styles.line}>
|
||||
<div class={styles.transportMode}>
|
||||
{renderLineTransportMode(props.line)}
|
||||
</div>
|
||||
{renderLinePicto(props.line, styles)}
|
||||
<div class={styles.destination}>
|
||||
<svg viewbox="0 0 600 40">
|
||||
<text x="0" y="50%" dominant-baseline="middle" font-size="40" style={{ fill: "#000000" }}>
|
||||
{props.destination}
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function _computeUnavailablePassage(class_) {
|
||||
const textStyle = { fill: "#000000" };
|
||||
return (
|
||||
<div class={class_}>
|
||||
<svg viewbox="0 0 230 110">
|
||||
<text x="100%" y="26" font-size="25" text-anchor="end" style={textStyle}>Information</text>
|
||||
<text x="100%" y="63" font-size="25" text-anchor="end" style={textStyle}>non</text>
|
||||
<text x="100%" y="100" font-size="25" text-anchor="end" style={textStyle}>disponible</text>
|
||||
<div class={styles.trafficStatus}>
|
||||
<svg viewBox="0 0 51 51">
|
||||
<circle cx="50%" cy="50%" r="24" stroke="#231f20" stroke-width="3" style={trafficStatusStyle} />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function _computeSecondPassage(passage): JSX.Element {
|
||||
return (
|
||||
<Show when={passage !== undefined} fallback={_computeUnavailablePassage(styles.unavailableSecondPassage)}>
|
||||
{_computeTtwPassage(styles.secondPassage, passage, 45)}
|
||||
<Show when={firstPassage !== undefined} fallback=<UnavailablePassage style={styles.unavailableFirstPassage} />>
|
||||
<TtwPassage style={styles.firstPassage} passage={firstPassage} fontSize="50" />
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
||||
function _computeFirstPassage(passage): JSX.Element {
|
||||
return (
|
||||
<Show when={passage !== undefined} fallback={_computeUnavailablePassage(styles.unavailableFirstPassage)}>
|
||||
{_computeTtwPassage(styles.firstPassage, passage, 50)}
|
||||
<Show when={secondPassage !== undefined} fallback=<UnavailablePassage style={styles.unavailableSecondPassage} />>
|
||||
<TtwPassage style={styles.secondPassage} passage={secondPassage} fontSize="45" />
|
||||
</Show>
|
||||
);
|
||||
</div >
|
||||
);
|
||||
}
|
||||
|
||||
export const PassagesPanel: Component = (props) => {
|
||||
|
||||
const { getLine } = useContext(BusinessDataContext);
|
||||
|
||||
const getLines = async (lineIds: Array<number>) => {
|
||||
const lines = await Promise.all(lineIds.map((lineId) => getLine(lineId)));
|
||||
return lines;
|
||||
}
|
||||
|
||||
/* TODO: Manage end of service */
|
||||
function _genPassages(passages, line, destination) {
|
||||
const passagesLength = passages.length;
|
||||
const firstPassage = passagesLength > 0 ? passages[0] : undefined;
|
||||
const secondPassage = passagesLength > 1 ? passages[1] : undefined;
|
||||
const trafficStatusStyle = { fill: trafficStatusColor.get(line.trafficStatus) };
|
||||
return (
|
||||
<div class={styles.line}>
|
||||
<div class={styles.transportMode}>
|
||||
{renderLineTransportMode(line)}
|
||||
</div>
|
||||
{renderLinePicto(line, styles)}
|
||||
<div class={styles.destination}>
|
||||
<svg viewbox="0 0 600 40">
|
||||
<text x="0" y="50%" dominant-baseline="middle" font-size="40" style={{ fill: "#000000" }}>
|
||||
{destination}
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class={styles.trafficStatus}>
|
||||
<svg viewBox="0 0 51 51">
|
||||
<circle cx="50%" cy="50%" r="24" stroke="#231f20" stroke-width="3" style={trafficStatusStyle} />
|
||||
</svg>
|
||||
</div>
|
||||
{firstPassage ? _computeFirstPassage(firstPassage) : null}
|
||||
{secondPassage ? _computeSecondPassage(secondPassage) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const [lineIds, setLinesIds] = createSignal([]);
|
||||
const [lines] = createResource(lineIds, getLines);
|
||||
|
||||
createEffect(async () => {
|
||||
setLinesIds(Object.keys(props.passages));
|
||||
});
|
||||
|
||||
return (
|
||||
<div classList={{ [styles.passagesContainer]: true, [styles.displayed]: props.show }} style={{ "top": `${100 * props.position}%` }}>
|
||||
{() => {
|
||||
const ret = [];
|
||||
for (const lineId of Object.keys(props.passages)) {
|
||||
const line = props.lines.get(lineId);
|
||||
const byLinePassages = props.passages[lineId];
|
||||
for (const destination of Object.keys(byLinePassages)) {
|
||||
const passages = byLinePassages[destination];
|
||||
ret.push(_genPassages(passages, line, destination));
|
||||
<Show when={lines() !== undefined} >
|
||||
{() => {
|
||||
const ret = [];
|
||||
for (const line of lines()) {
|
||||
const byLinePassages = props.passages[line.id];
|
||||
if (byLinePassages !== undefined) {
|
||||
for (const destination of Object.keys(byLinePassages)) {
|
||||
ret.push(<Passages passages={byLinePassages[destination]} line={line} destination={destination} />);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}}
|
||||
</div>
|
||||
return ret;
|
||||
}}
|
||||
</Show>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user