From 4bec4459a9536da29550a936d23eef8b4fe4ad7f Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 14 Mar 2025 21:11:15 +0000 Subject: [PATCH] [frontend]: Add 'Favourite' functionality --- diary.md | 1 + frontend/src/App.jsx | 43 +++++++++--------- frontend/src/components/Sidebar.jsx | 69 +++++++++++++++++------------ 3 files changed, 62 insertions(+), 51 deletions(-) diff --git a/diary.md b/diary.md index 933e59f..6ade3b9 100644 --- a/diary.md +++ b/diary.md @@ -3,6 +3,7 @@ - Add 'favourite' button to train station pop-up. - Create `IrishRailTrainPopup` with favourite button. - Create `BusPopup` with favourite button. +- Create `BusStopPopup` with favourite button. ## Wed 12 Mar 2025 - Fix search input freezing when there's a large number of data. diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 714487b..a35e043 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -13,6 +13,7 @@ import LuasPopup from "./components/LuasPopup"; import TrainStationPopup from "./components/TrainStationPopup"; import IrishRailTrainPopup from "./components/IrishRailTrainPopup"; import BusPopup from "./components/BusPopup.jsx"; +import BusStopPopup from "./components/BusStopPopup.jsx"; 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"; @@ -35,6 +36,7 @@ const defaultFavourites = { function App() { const [favourites, setFavourites] = useState(defaultFavourites); + const [showFaovouritesOnly, setShowFavouritesOnly] = useState(false); useEffect(() => { try { @@ -270,7 +272,8 @@ function App() { ((showRunning && trainStatus == "Running") || (showNotYetRunning && trainStatus == "Not yet running") || (showTerminated && trainStatus == "Terminated")) && ((trainStatus == "Running" && showEarly && punctualityStr == "early") || (trainStatus == "Running" && showOnTime && punctualityStr == "On time") || (trainStatus == "Running" && showLate && punctualityStr == "late") || (trainStatus == "Not yet running" && showNotYetRunning) || (trainStatus == "Terminated" && showTerminated))) && - (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true); + (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true) && + (showFaovouritesOnly ? favourites.IrishRailTrain.includes(item.trainCode) : true); break; @@ -287,7 +290,8 @@ function App() { markerText = item.trainStationCode + " " + item.trainStationDesc; display = (item.latitude !== "0" && item.longitude !== "0") && - (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true); + (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true) && + (showFaovouritesOnly ? favourites.IrishRailStation.includes(item.trainStationCode) : true); break; @@ -300,40 +304,30 @@ function App() { toggleFavourite={toggleFavourite} favourites={favourites} /> - //
- //

{objectTitle}

- // - //
); markerText = item.busRouteAgencyName + " " + item.busRouteShortName + " " + item.busRouteLongName; display = (item.latitude !== "0" && item.longitude !== "0") && - (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true); + (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true) && + (showFaovouritesOnly ? favourites.Bus.includes(item.busRoute) : true); break; case "BusStop": objectTitle = item.busStopName + " Bus Stop"; popupContent = ( -
-

{objectTitle}

- -
+ ); markerText = item.busStopName; display = (item.latitude !== "0" && item.longitude !== "0") && - (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true); + (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true) && + (showFaovouritesOnly ? favourites.BusStop.includes(item.busStopID) : true); break; @@ -370,7 +364,8 @@ function App() { (showEnabled && item.luasStopIsEnabled === "1" || showDisabled && item.luasStopIsEnabled === "0") && (!showCycleAndRide || (showCycleAndRide && item.luasStopIsCycleAndRide === "1")) && (!showParkAndRide || (showParkAndRide && item.luasStopIsParkAndRide === "1")) && - (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true) + (numberInputValue && userLocationAvailable ? haversineDistance(userLocation, [item.latitude, item.longitude]) < numberInputValue : true) && + (showFaovouritesOnly ? favourites.LuasStop.includes(item.luasStopID) : true) ); break; @@ -469,6 +464,8 @@ function App() { setClusteringEnabled={setClusteringEnabled} fetchData={fetchData} userLocationAvailable={userLocationAvailable} + showFavouritesOnly={showFaovouritesOnly} + setShowFavouritesOnly={setShowFavouritesOnly} />
{ +const Sidebar = ({ selectedSources, setSelectedSources, clusteringEnabled, setClusteringEnabled, fetchData, userLocationAvailable, showFavouritesOnly, setShowFavouritesOnly }) => { const [isOpen, setIsOpen] = useState(false); const [enabledSources, setEnabledSources] = useState([]); // New state to track enabled sources const [numberInputValue, setNumberInputValue] = useState(""); // State to manage number input value @@ -183,41 +183,54 @@ const Sidebar = ({ selectedSources, setSelectedSources, clusteringEnabled, setCl setEnabledSources={setEnabledSources} /> ))} -
+ +
setClusteringEnabled(!clusteringEnabled)} + id="showFavouritesOnly" + checked={showFavouritesOnly} + onChange={() => setShowFavouritesOnly(!showFavouritesOnly)} /> - +
- {userLocationAvailable && ( -
- + +
setNumberInputValue(e.target.value)} - style={{maxWidth: "40%"}} + type="checkbox" + id="toggleClustering" + checked={clusteringEnabled} + onChange={() => setClusteringEnabled(!clusteringEnabled)} /> +
+ {userLocationAvailable && ( +
+ + setNumberInputValue(e.target.value)} + style={{maxWidth: "40%"}} + /> +
+ )} + +
)} -
- )} -
- ); -}; + ); + }; -Sidebar.propTypes = { - selectedSources: PropTypes.array.isRequired, - setSelectedSources: PropTypes.func.isRequired, - clusteringEnabled: PropTypes.bool.isRequired, - setClusteringEnabled: PropTypes.func.isRequired, - fetchData: PropTypes.func.isRequired, - userLocationAvailable: PropTypes.bool.isRequired, -}; + Sidebar.propTypes = { + selectedSources: PropTypes.array.isRequired, + setSelectedSources: PropTypes.func.isRequired, + clusteringEnabled: PropTypes.bool.isRequired, + setClusteringEnabled: PropTypes.func.isRequired, + fetchData: PropTypes.func.isRequired, + userLocationAvailable: PropTypes.bool.isRequired, + showFavouritesOnly: PropTypes.bool.isRequired, + setShowFavouritesOnly: PropTypes.func.isRequired, + }; -export default Sidebar + export default Sidebar