[frontend]: Fix TrainStationPopup from going offscreen on data fetch
This commit is contained in:
@ -1,20 +1,29 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useRef } from "react";
|
||||||
|
import { useMap } from "react-leaflet";
|
||||||
|
|
||||||
const TrainStationPopup = ({ item, objectTitle }) => {
|
const TrainStationPopup = ({ item, objectTitle }) => {
|
||||||
const [trainInfo, setTrainInfo] = useState("");
|
const [trainInfo, setTrainInfo] = useState("");
|
||||||
|
const map = useMap(); // Access the Leaflet map instance
|
||||||
|
|
||||||
const fetchTrainData = async () => {
|
const fetchTrainData = async () => {
|
||||||
|
let trainInfoHtml = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`https://kkz92ft0ad.execute-api.us-east-1.amazonaws.com/return_station_data?stationCode=${item.trainStationCode}`);
|
const response = await fetch(
|
||||||
|
`https://kkz92ft0ad.execute-api.us-east-1.amazonaws.com/return_station_data?stationCode=${item.trainStationCode}`
|
||||||
|
);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
// Ensure objStationData is always an array
|
|
||||||
let trainDataArray = Array.isArray(data.ArrayOfObjStationData.objStationData)
|
let trainDataArray = Array.isArray(data.ArrayOfObjStationData.objStationData)
|
||||||
? data.ArrayOfObjStationData.objStationData
|
? data.ArrayOfObjStationData.objStationData
|
||||||
: [data.ArrayOfObjStationData.objStationData];
|
: [data.ArrayOfObjStationData.objStationData];
|
||||||
|
|
||||||
trainDataArray = trainDataArray.slice(0, 3); // Only show the first 3 trains
|
trainDataArray = trainDataArray.slice(0, 3); // Only show the first 3 trains
|
||||||
|
|
||||||
|
if (trainDataArray.length === 0) {
|
||||||
|
throw new Error("No train data available");
|
||||||
|
}
|
||||||
|
|
||||||
const trainData = trainDataArray.map(train => ({
|
const trainData = trainDataArray.map(train => ({
|
||||||
trainCode: train.Traincode,
|
trainCode: train.Traincode,
|
||||||
origin: train.Origin,
|
origin: train.Origin,
|
||||||
@ -25,21 +34,30 @@ const TrainStationPopup = ({ item, objectTitle }) => {
|
|||||||
lastLocation: train.Lastlocation,
|
lastLocation: train.Lastlocation,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const trainInfoHtml = "<b>Trains due in next 90 minutes:</b><br>"
|
trainInfoHtml =
|
||||||
+ trainData.map(train => `
|
"<b>Trains due in next 90 minutes:</b><br>" +
|
||||||
Train Code: ${train.trainCode}<br>
|
trainData
|
||||||
Origin: ${train.origin}<br>
|
.map(train => `
|
||||||
Destination: ${train.destination}<br>
|
Train Code: ${train.trainCode}<br>
|
||||||
Due In: ${train.dueIn} minutes<br>
|
Origin: ${train.origin}<br>
|
||||||
Punctuality: ${train.late > 0 ? `${train.late} minute${train.late === 1 ? "" : "s"} late` : train.late < 0 ? `${Math.abs(train.late)} minute${Math.abs(train.late) === 1 ? "" : "s"} early` : "On time"}<br>
|
Destination: ${train.destination}<br>
|
||||||
Status: ${train.status}<br>
|
Due In: ${train.dueIn} minutes<br>
|
||||||
Last Location: ${train.lastLocation || "N/A"}<br><br>
|
Punctuality: ${train.late > 0 ? `${train.late} minute${train.late === 1 ? "" : "s"} late` : train.late < 0 ? `${Math.abs(train.late)} minute${Math.abs(train.late) === 1 ? "" : "s"} early` : "On time"}<br>
|
||||||
`).join("");
|
Status: ${train.status}<br>
|
||||||
|
Last Location: ${train.lastLocation || "N/A"}<br><br>
|
||||||
|
`)
|
||||||
|
.join("");
|
||||||
|
|
||||||
setTrainInfo(trainInfoHtml);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setTrainInfo("No trains due in the next 90 minutes");
|
trainInfoHtml = "No trains due in the next 90 minutes.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTrainInfo(trainInfoHtml);
|
||||||
|
|
||||||
|
// Ensure the map pans to keep the popup in view even if an error occurs
|
||||||
|
setTimeout(() => {
|
||||||
|
map.panTo([item.latitude, item.longitude], { animate: true });
|
||||||
|
}, 300);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -50,12 +68,30 @@ const TrainStationPopup = ({ item, objectTitle }) => {
|
|||||||
<li><b>Train Station ID:</b> {item.trainStationID}</li>
|
<li><b>Train Station ID:</b> {item.trainStationID}</li>
|
||||||
<li><b>Train Station Code:</b> {item.trainStationCode}</li>
|
<li><b>Train Station Code:</b> {item.trainStationCode}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button onClick={fetchTrainData} style={{ padding: "5px", marginTop: "5px", cursor: "pointer", color: "white" }}>
|
<button
|
||||||
|
onClick={fetchTrainData}
|
||||||
|
style={{
|
||||||
|
padding: "5px",
|
||||||
|
marginTop: "5px",
|
||||||
|
cursor: "pointer",
|
||||||
|
color: "white",
|
||||||
|
background: "black",
|
||||||
|
border: "none",
|
||||||
|
borderRadius: "4px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
Load incoming trains
|
Load incoming trains
|
||||||
</button>
|
</button>
|
||||||
<div dangerouslySetInnerHTML={{ __html: trainInfo }} style={{ marginTop: "10px" }}></div>
|
<div
|
||||||
|
dangerouslySetInnerHTML={{ __html: trainInfo }}
|
||||||
|
style={{
|
||||||
|
marginTop: "10px",
|
||||||
|
maxHeight: "200px", // limit popup height
|
||||||
|
overflowY: "auto" // enable scrolling
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TrainStationPopup;
|
export default TrainStationPopup;
|
||||||
|
Reference in New Issue
Block a user