diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 9b68301..66fa369 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,47 +1,14 @@
import React, { useState } from "react";
-import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
-import "leaflet/dist/leaflet.css";
-import MarkerClusterGroup from "react-leaflet-markercluster";
-import L, { Icon } from "leaflet";
-
-import "leaflet.markercluster/dist/MarkerCluster.css";
-import "leaflet.markercluster/dist/MarkerCluster.Default.css";
-
-// Icons
-import trainStationIconURL from "../src/assets/icons/train-station.png";
-import trainIconURL from "../src/assets/icons/train.png";
-
-// Fix marker icon issue with Leaflet
-delete L.Icon.Default.prototype._getIconUrl;
-L.Icon.Default.mergeOptions({
- iconUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png",
- iconRetinaUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png",
- shadowUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png",
-});
-
-const icons = new Map();
-icons.set(
- "IrishRailStation",
- new Icon({
- iconUrl: trainStationIconURL,
- iconSize: [24, 24],
- })
-);
-
-icons.set(
- "IrishRailTrain",
- new Icon({
- iconUrl: trainIconURL,
- iconSize: [24, 24],
- })
-);
+import Sidebar from "./components/Sidebar";
+import MapComponent from "./components/MapComponent";
+import LoadingOverlay from "./components/LoadingOverlay";
const TRANSIENT_DATA_API = "https://281bc6mcm5.execute-api.us-east-1.amazonaws.com/transient_data";
const PERMANENT_DATA_API = "https://a6y312dpuj.execute-api.us-east-1.amazonaws.com/permanent_data";
const dataSources = [
- { id: "IrishRailTrains", name: "Irish Rail Trains", url: TRANSIENT_DATA_API + "?objectType=IrishRailTrain" },
- { id: "IrishRailStations", name: "Irish Rail Stations", url: PERMANENT_DATA_API + "?objectType=IrishRailStation" },
+ { id: "IrishRailTrains", name: "Irish Rail Trains", url: `${TRANSIENT_DATA_API}?objectType=IrishRailTrain` },
+ { id: "IrishRailStations", name: "Irish Rail Stations", url: `${PERMANENT_DATA_API}?objectType=IrishRailStation` },
];
function App() {
@@ -50,95 +17,37 @@ function App() {
const [loading, setLoading] = useState(false);
const [clusteringEnabled, setClusteringEnabled] = useState(true);
- const handleCheckboxChange = (id) => {
- setSelectedSources((prev) =>
- prev.includes(id) ? prev.filter((source) => source !== id) : [...prev, id]
- );
- };
-
const fetchData = async () => {
setLoading(true);
- const newMarkers = [];
- for (const source of dataSources) {
- if (selectedSources.includes(source.id)) {
- try {
- const response = await fetch(source.url);
- const data = await response.json();
- data.forEach((item) => {
- newMarkers.push({
- coords: [item.latitude, item.longitude],
- popup: item.objectType,
- icon: item.objectType,
- });
- });
- } catch (error) {
- console.error(`Error fetching data from ${source.name}:`, error);
- }
- }
+ try {
+ const newMarkers = (await Promise.all(
+ dataSources
+ .filter(({ id }) => selectedSources.includes(id))
+ .map(({ url }) => fetch(url).then((res) => res.json()))
+ )).flat().map(({ latitude, longitude, objectType }) => ({
+ coords: [latitude, longitude],
+ popup: objectType,
+ icon: objectType,
+ }));
+ setMarkers(newMarkers);
+ } catch (error) {
+ console.error("Error fetching data:", error);
}
- setMarkers(newMarkers);
setLoading(false);
};
return (
- {loading && (
-
- Loading data...
-
- )}
-
-
Select Data Sources
- {dataSources.map((source) => (
-
- handleCheckboxChange(source.id)}
- />
-
-
- ))}
-
- setClusteringEnabled(!clusteringEnabled)}
- />
-
-
-
-
+ {loading &&
}
+
-
-
- {clusteringEnabled ? (
-
- {markers.map((marker, index) => (
-
- {marker.popup}
-
- ))}
-
- ) : (
- markers.map((marker, index) => (
-
- {marker.popup}
-
- ))
- )}
-
+
);
diff --git a/frontend/src/components/LoadingOverlay.jsx b/frontend/src/components/LoadingOverlay.jsx
new file mode 100644
index 0000000..76ac3d4
--- /dev/null
+++ b/frontend/src/components/LoadingOverlay.jsx
@@ -0,0 +1,15 @@
+import React from "react";
+
+const LoadingOverlay = () => (
+
+ Loading data...
+
+);
+
+export default LoadingOverlay;
diff --git a/frontend/src/components/MapComponent.jsx b/frontend/src/components/MapComponent.jsx
new file mode 100644
index 0000000..f3b21b4
--- /dev/null
+++ b/frontend/src/components/MapComponent.jsx
@@ -0,0 +1,51 @@
+import React from "react";
+import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
+import MarkerClusterGroup from "react-leaflet-markercluster";
+import L, { Icon } from "leaflet";
+import "leaflet/dist/leaflet.css";
+import "leaflet.markercluster/dist/MarkerCluster.css";
+import "leaflet.markercluster/dist/MarkerCluster.Default.css";
+
+import trainStationIconURL from "../assets/icons/train-station.png";
+import trainIconURL from "../assets/icons/train.png";
+
+// Fix Leaflet marker icon issue
+delete L.Icon.Default.prototype._getIconUrl;
+L.Icon.Default.mergeOptions({
+ iconUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png",
+ iconRetinaUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png",
+ shadowUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png",
+});
+
+const icons = new Map([
+ ["IrishRailStation", new Icon({ iconUrl: trainStationIconURL, iconSize: [24, 24] })],
+ ["IrishRailTrain", new Icon({ iconUrl: trainIconURL, iconSize: [24, 24] })],
+]);
+
+const MapComponent = ({ markers, clusteringEnabled }) => {
+ return (
+
+
+ {clusteringEnabled ? (
+
+ {markers.map(({ coords, popup, icon }, index) => (
+
+ {popup}
+
+ ))}
+
+ ) : (
+ markers.map(({ coords, popup, icon }, index) => (
+
+ {popup}
+
+ ))
+ )}
+
+ );
+};
+
+export default MapComponent;
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
new file mode 100644
index 0000000..0db7211
--- /dev/null
+++ b/frontend/src/components/Sidebar.jsx
@@ -0,0 +1,59 @@
+import React, { useState } from "react";
+
+const Sidebar = ({ selectedSources, setSelectedSources, clusteringEnabled, setClusteringEnabled, fetchData }) => {
+ const [isOpen, setIsOpen] = useState(true);
+ const dataSources = [
+ { id: "IrishRailTrains", name: "Irish Rail Trains" },
+ { id: "IrishRailStations", name: "Irish Rail Stations" },
+ ];
+
+ return (
+
+
+ {isOpen && (
+
+
Select Data Sources
+ {dataSources.map(({ id, name }) => (
+
+
+ setSelectedSources((prev) => prev.includes(id) ? prev.filter((s) => s !== id) : [...prev, id])
+ }
+ />
+
+
+ ))}
+
+ setClusteringEnabled(!clusteringEnabled)}
+ />
+
+
+
+
+ )}
+
+ );
+};
+
+export default Sidebar;
\ No newline at end of file