[frontend]: Add 'Favourite' functionality

This commit is contained in:
2025-03-14 21:11:15 +00:00
parent 2703ff7dc8
commit 4bec4459a9
3 changed files with 62 additions and 51 deletions

View File

@ -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.

View File

@ -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}
/>
// <div>
// <h3>{objectTitle}</h3>
// <ul>
// <li><b>Bus ID:</b> {item.busID}</li>
// <li><b>Bus Route ID:</b> {item.busRoute}</li>
// <li><b>Bus Route Short Name:</b> {item.busRouteShortName}</li>
// <li><b>Bus Route Long Name:</b> {item.busRouteLongName}</li>
// <li><b>Agency: </b> {item.busRouteAgencyName}</li>
// </ul>
// </div>
);
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 = (
<div>
<h3>{objectTitle}</h3>
<ul>
<li><b>Bus Stop ID:</b> {item.busStopID}</li>
<li><b>Bus Stop Name:</b> {item.busStopName}</li>
<li><b>Bus Stop Code:</b> {item.busStopCode || "N/A"}</li>
</ul>
</div>
<BusStopPopup
item={item}
objectTitle={objectTitle}
toggleFavourite={toggleFavourite}
favourites={favourites}
/>
);
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}
/>
<div style={{ flex: 1 }}>
<MapComponent

View File

@ -131,7 +131,7 @@ const CheckboxItem = ({ item, selectedSources, setSelectedSources, enabledSource
);
};
const Sidebar = ({ selectedSources, setSelectedSources, clusteringEnabled, setClusteringEnabled, fetchData, userLocationAvailable }) => {
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,7 +183,18 @@ const Sidebar = ({ selectedSources, setSelectedSources, clusteringEnabled, setCl
setEnabledSources={setEnabledSources}
/>
))}
<div style={{marginTop: "10px", display: "flex", alignItems: "center", gap: "8px"}}>
<div style={{marginTop: "10px", display: "flex", alignItems: "center", gap: "4px"}}>
<input
type="checkbox"
id="showFavouritesOnly"
checked={showFavouritesOnly}
onChange={() => setShowFavouritesOnly(!showFavouritesOnly)}
/>
<label htmlFor={"showFavouritesOnly"}>Show Favourites Only</label>
</div>
<div style={{marginTop: "10px", display: "flex", alignItems: "center", gap: "4px"}}>
<input
type="checkbox"
id="toggleClustering"
@ -218,6 +229,8 @@ Sidebar.propTypes = {
setClusteringEnabled: PropTypes.func.isRequired,
fetchData: PropTypes.func.isRequired,
userLocationAvailable: PropTypes.bool.isRequired,
showFavouritesOnly: PropTypes.bool.isRequired,
setShowFavouritesOnly: PropTypes.func.isRequired,
};
export default Sidebar