cleanup, improve date formatting, move date filtering to client side, make statuses more 'airport-y'
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^16.2.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"date-fns-tz": "^3.2.0",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
|
|||||||
45
src/App.js
45
src/App.js
@@ -1,44 +1,32 @@
|
|||||||
import { useState, useEffect, useMemo } from 'react';
|
import { useState, useEffect, useMemo } from 'react';
|
||||||
|
import { format, formatDistanceToNow, startOfDay } from 'date-fns';
|
||||||
|
import { formatInTimeZone } from 'date-fns-tz';
|
||||||
|
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import '@fontsource/roboto-mono';
|
import '@fontsource/roboto-mono';
|
||||||
|
|
||||||
import Schedule from './components/schedule/Schedule';
|
import Schedule from './components/schedule/Schedule';
|
||||||
import Radar from './components/Radar';
|
import Radar from './components/Radar';
|
||||||
import { format, formatDistanceToNow } from 'date-fns';
|
|
||||||
import Metar from './components/metar/Metar';
|
import Metar from './components/metar/Metar';
|
||||||
|
|
||||||
const statuses = {
|
const statuses = {
|
||||||
OPEN: 'ON TIME',
|
OPEN: 'ON TIME',
|
||||||
|
COMPLETED: 'LANDED',
|
||||||
|
'IN PROGRESS': 'ENROUTE',
|
||||||
};
|
};
|
||||||
const days = [
|
|
||||||
'Sunday',
|
|
||||||
'Monday',
|
|
||||||
'Tuesday',
|
|
||||||
'Wednesday',
|
|
||||||
'Thursday',
|
|
||||||
'Friday',
|
|
||||||
'Saturday',
|
|
||||||
];
|
|
||||||
const pad = n => String(n).padStart(2, '0');
|
|
||||||
|
|
||||||
function formatUtcDate(date) {
|
|
||||||
return (
|
|
||||||
`${days[date.getUTCDay()]} ${pad(date.getUTCDate())}/${pad(date.getUTCMonth() + 1)}/${date.getUTCFullYear()} ` +
|
|
||||||
`${pad(date.getUTCHours())}:${pad(date.getUTCMinutes())}:${pad(date.getUTCSeconds())}Z`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const normaliseData = data => {
|
const normaliseData = data => {
|
||||||
return data.map(d => {
|
return data.map(d => {
|
||||||
const date = format(d.start, 'dd/MM');
|
const date = format(d.start, 'dd/MM');
|
||||||
const start = format(d.start, 'HH:mm');
|
const startTime = format(d.start, 'HH:mm');
|
||||||
const end = format(d.end, 'HH:mm');
|
const endTime = format(d.end, 'HH:mm');
|
||||||
const status = statuses[d.status] ?? d.status;
|
const status = statuses[d.status.toUpperCase()] ?? d.status;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...d,
|
...d,
|
||||||
date,
|
date,
|
||||||
start,
|
startTime,
|
||||||
end,
|
endTime,
|
||||||
status,
|
status,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -58,10 +46,17 @@ function App() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
const today = startOfDay(new Date());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch('https://mattfidd.rocks/veroDashboard.json');
|
const res = await fetch('https://mattfidd.rocks/veroDashboard.json');
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
setData(normaliseData(json.slice(1)));
|
|
||||||
|
const normalisedData = normaliseData(json.slice(1)).filter(
|
||||||
|
d => new Date(d.end) >= today,
|
||||||
|
);
|
||||||
|
|
||||||
|
setData(normalisedData);
|
||||||
setDataUpdated(json[0].updatedAt);
|
setDataUpdated(json[0].updatedAt);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching data:', err);
|
console.error('Error fetching data:', err);
|
||||||
@@ -79,7 +74,7 @@ function App() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const formattedTime = useMemo(() => {
|
const formattedTime = useMemo(() => {
|
||||||
return formatUtcDate(time);
|
return formatInTimeZone(time, 'UTC', 'EEEE dd/MM HH:mm:ss') + 'Z';
|
||||||
}, [time]);
|
}, [time]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import ScheduleRow from './ScheduleRow';
|
|||||||
import ScheduleCell from './ScheduleCell';
|
import ScheduleCell from './ScheduleCell';
|
||||||
|
|
||||||
const widths = [85, 85, 85, 85, 400, 150];
|
const widths = [85, 85, 85, 85, 400, 150];
|
||||||
|
const colours = {
|
||||||
|
LANDED: '#6FB165',
|
||||||
|
ENROUTE: '#3197E5',
|
||||||
|
CANCELLED: '#E54331',
|
||||||
|
};
|
||||||
|
|
||||||
const Schedule = ({ data }) => {
|
const Schedule = ({ data }) => {
|
||||||
return (
|
return (
|
||||||
@@ -56,8 +61,8 @@ const Schedule = ({ data }) => {
|
|||||||
<ScheduleRow bg={i % 2 === 1} key={row.id}>
|
<ScheduleRow bg={i % 2 === 1} key={row.id}>
|
||||||
<ScheduleCell width={widths[0]}>{row.name}</ScheduleCell>
|
<ScheduleCell width={widths[0]}>{row.name}</ScheduleCell>
|
||||||
<ScheduleCell width={widths[1]}>{row.date}</ScheduleCell>
|
<ScheduleCell width={widths[1]}>{row.date}</ScheduleCell>
|
||||||
<ScheduleCell width={widths[2]}>{row.start}</ScheduleCell>
|
<ScheduleCell width={widths[2]}>{row.startTime}</ScheduleCell>
|
||||||
<ScheduleCell width={widths[3]}>{row.end}</ScheduleCell>
|
<ScheduleCell width={widths[3]}>{row.endTime}</ScheduleCell>
|
||||||
<ScheduleCell width={widths[4]}>
|
<ScheduleCell width={widths[4]}>
|
||||||
{row.description?.length
|
{row.description?.length
|
||||||
? row.description
|
? row.description
|
||||||
@@ -69,15 +74,7 @@ const Schedule = ({ data }) => {
|
|||||||
<ScheduleCell width={widths[5]}>{row.location}</ScheduleCell>
|
<ScheduleCell width={widths[5]}>{row.location}</ScheduleCell>
|
||||||
<ScheduleCell
|
<ScheduleCell
|
||||||
end="true"
|
end="true"
|
||||||
color={
|
color={colours[row.status.toUpperCase()]}
|
||||||
row.status.toUpperCase() === 'COMPLETED'
|
|
||||||
? '#6FB165'
|
|
||||||
: row.status.toUpperCase() === 'IN PROGRESS'
|
|
||||||
? '#3197E5'
|
|
||||||
: row.status.toUpperCase() === 'CANCELLED'
|
|
||||||
? '#E54331'
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{row.status}
|
{row.status}
|
||||||
</ScheduleCell>
|
</ScheduleCell>
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@@ -5008,6 +5008,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"date-fns-tz@npm:^3.2.0":
|
||||||
|
version: 3.2.0
|
||||||
|
resolution: "date-fns-tz@npm:3.2.0"
|
||||||
|
peerDependencies:
|
||||||
|
date-fns: ^3.0.0 || ^4.0.0
|
||||||
|
checksum: 10c0/3f43300a4335d59f3515dc5196c66b4b56ef2af129eb82e4445ce0983e8ef31a5d038bc0406d669946bbbcf52ed953527527aa28b4a810995d6631a54655abcc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"date-fns@npm:^4.1.0":
|
"date-fns@npm:^4.1.0":
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
resolution: "date-fns@npm:4.1.0"
|
resolution: "date-fns@npm:4.1.0"
|
||||||
@@ -12920,6 +12929,7 @@ __metadata:
|
|||||||
"@testing-library/react": "npm:^16.2.0"
|
"@testing-library/react": "npm:^16.2.0"
|
||||||
"@testing-library/user-event": "npm:^13.5.0"
|
"@testing-library/user-event": "npm:^13.5.0"
|
||||||
date-fns: "npm:^4.1.0"
|
date-fns: "npm:^4.1.0"
|
||||||
|
date-fns-tz: "npm:^3.2.0"
|
||||||
prettier: "npm:^3.5.3"
|
prettier: "npm:^3.5.3"
|
||||||
react: "npm:^19.1.0"
|
react: "npm:^19.1.0"
|
||||||
react-dom: "npm:^19.1.0"
|
react-dom: "npm:^19.1.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user