DVB Container
This commit is contained in:
parent
0ac2eb2125
commit
f3f01f9717
73
src/components/DVB.tsx
Normal file
73
src/components/DVB.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import type { Departure } from "../lib/interfaces";
|
||||||
|
import { minuteDiff } from "../lib/utils";
|
||||||
|
import * as styles from "../styles/containers/DVB.module.css";
|
||||||
|
|
||||||
|
const DVB_REFRESH_INTERVAL = 30 * 1000
|
||||||
|
|
||||||
|
const DVB = ({ stopId }: { stopId: number }) => {
|
||||||
|
const [departuresHead, setDeparturesHead] = React.useState("")
|
||||||
|
const [departuresTable, setDeparturesTable] = React.useState([])
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
//pullDepartures();
|
||||||
|
// TODO
|
||||||
|
//const dvbInterval = setInterval(pullDepartures, DVB_REFRESH_INTERVAL);
|
||||||
|
|
||||||
|
//return () => clearInterval(dvbInterval);
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const processDepatures = (departures: Departure[]) => {
|
||||||
|
const depTable = [];
|
||||||
|
|
||||||
|
departures.forEach((departure, index) => {
|
||||||
|
const realTime = departure.RealTime ? new Date(parseInt(departure.RealTime.replace(/\/Date\(/g, "").replace(/\-.*$/g, ""))) : undefined;
|
||||||
|
const scheduledTime = new Date(parseInt(departure.ScheduledTime.replace(/\/Date\(/g, "").replace(/\-.*$/g, "")));
|
||||||
|
const timeToDisplay = realTime || scheduledTime;
|
||||||
|
const timeDelay = realTime ? minuteDiff(realTime, scheduledTime) : 0;
|
||||||
|
|
||||||
|
depTable.push(
|
||||||
|
<tr className={styles.departure} key={index}>
|
||||||
|
<td>{departure.LineName}</td>
|
||||||
|
<td>{departure.Direction}</td>
|
||||||
|
<td>{timeToDisplay.getHours()}:{timeToDisplay.getMinutes().toString().padStart(2, "0")}</td>
|
||||||
|
<td>{minuteDiff(timeToDisplay, new Date())}</td>
|
||||||
|
<td className={timeDelay < 0 ? styles.beforeTime : styles.delay}>{timeDelay > 0 ? "+" : ""}{timeDelay !== 0 ? timeDelay : false}</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
setDeparturesTable(depTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pullDepartures = async () => {
|
||||||
|
const time = new Date();
|
||||||
|
time.setMinutes(time.getMinutes() + 5)
|
||||||
|
const response = await fetch("https://webapi.vvo-online.de/dm", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
stopid: stopId,
|
||||||
|
limit: 5,
|
||||||
|
time: time.toUTCString()
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.Name !== departuresHead) setDeparturesHead(data.Name);
|
||||||
|
console.log(data)
|
||||||
|
processDepatures(data.Departures);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<div className={`container ${styles.container}`}>
|
||||||
|
<table>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{departuresTable}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DVB;
|
@ -1,6 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { XMLParser } from "fast-xml-parser";
|
import { XMLParser } from "fast-xml-parser";
|
||||||
import * as styles from "../styles/containers/News.module.css"
|
import * as styles from "../styles/containers/News.module.css"
|
||||||
|
import type { News as NewsType, PostillonNews } from "../lib/interfaces";
|
||||||
|
|
||||||
const NEWS_REFRESH_INTERVAL = 15 * 60 * 1000;
|
const NEWS_REFRESH_INTERVAL = 15 * 60 * 1000;
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ const News = () => {
|
|||||||
return () => clearInterval(newsInterval);
|
return () => clearInterval(newsInterval);
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const processNews = (news: {title: string; updated: string;}[], postillon: {title: string; pubDate: string; categories: string[]}[]) => {
|
const processNews = (news: NewsType[], postillon: PostillonNews[]) => {
|
||||||
const newsTable = []
|
const newsTable = []
|
||||||
|
|
||||||
for (const n of news) {
|
for (const n of news) {
|
||||||
|
@ -31,3 +31,23 @@ export interface Event {
|
|||||||
start: { dateTime: string; date?: string; };
|
start: { dateTime: string; date?: string; };
|
||||||
summary: string;
|
summary: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface News {
|
||||||
|
title: string;
|
||||||
|
updated: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PostillonNews {
|
||||||
|
title: string;
|
||||||
|
pubDate: string;
|
||||||
|
categories: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Departure {
|
||||||
|
Direction: string;
|
||||||
|
LineName: string;
|
||||||
|
RealTime?: string;
|
||||||
|
ScheduledTime: string;
|
||||||
|
State?: "Delayed" | "InTime" | "Canceled";
|
||||||
|
CancelReasons?: string[];
|
||||||
|
}
|
@ -28,3 +28,7 @@ export function monthToString(month: number) {
|
|||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function minuteDiff(later: Date, before: Date) {
|
||||||
|
return Math.floor((later.getTime() - before.getTime()) / 60000);
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import secrets from "../../secrets.json"
|
import secrets from "../../secrets.json"
|
||||||
import Calendar from "../components/Calendar";
|
import Calendar from "../components/Calendar";
|
||||||
|
import DVB from "../components/DVB";
|
||||||
import News from "../components/News";
|
import News from "../components/News";
|
||||||
import WeatherAndTimeContainer from "../components/WeatherAndTime"
|
import WeatherAndTimeContainer from "../components/WeatherAndTime"
|
||||||
import WeatherRadar from "../components/WeatherRadar";
|
import WeatherRadar from "../components/WeatherRadar";
|
||||||
@ -36,6 +37,7 @@ const IndexPage = () => {
|
|||||||
<Calendar secrets={secrets.calendar} />
|
<Calendar secrets={secrets.calendar} />
|
||||||
<WeatherRadar />
|
<WeatherRadar />
|
||||||
<News />
|
<News />
|
||||||
|
<DVB stopId={secrets.dvb.stopId} />
|
||||||
</main>)
|
</main>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
50
src/styles/containers/DVB.module.css
Normal file
50
src/styles/containers/DVB.module.css
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
.container {
|
||||||
|
grid-area: dvb;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container table {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.departureHeader {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 110%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.departure {
|
||||||
|
font-size: 150%;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.departure td {
|
||||||
|
padding: 2px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.departure td:nth-child(1) {
|
||||||
|
padding-left: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.departure td:nth-child(2) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.departure td:nth-child(3), .departure td:nth-child(4) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delay, .beforeTime {
|
||||||
|
padding-left: 0 !important;
|
||||||
|
font-size: 70%;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delay {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beforeTime {
|
||||||
|
color: #0000ff;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user