[frontend]: Add 'Favourite' functionality
This commit is contained in:
1
diary.md
1
diary.md
@ -3,6 +3,7 @@
|
|||||||
- Add 'favourite' button to train station pop-up.
|
- Add 'favourite' button to train station pop-up.
|
||||||
- Create `IrishRailTrainPopup` with favourite button.
|
- Create `IrishRailTrainPopup` with favourite button.
|
||||||
- Create `BusPopup` with favourite button.
|
- Create `BusPopup` with favourite button.
|
||||||
|
- Create `BusStopPopup` with favourite button.
|
||||||
|
|
||||||
## Wed 12 Mar 2025
|
## Wed 12 Mar 2025
|
||||||
- Fix search input freezing when there's a large number of data.
|
- Fix search input freezing when there's a large number of data.
|
||||||
|
@ -13,6 +13,7 @@ import LuasPopup from "./components/LuasPopup";
|
|||||||
import TrainStationPopup from "./components/TrainStationPopup";
|
import TrainStationPopup from "./components/TrainStationPopup";
|
||||||
import IrishRailTrainPopup from "./components/IrishRailTrainPopup";
|
import IrishRailTrainPopup from "./components/IrishRailTrainPopup";
|
||||||
import BusPopup from "./components/BusPopup.jsx";
|
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 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 PERMANENT_DATA_API = "https://a6y312dpuj.execute-api.us-east-1.amazonaws.com/permanent_data";
|
||||||
@ -35,6 +36,7 @@ const defaultFavourites = {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [favourites, setFavourites] = useState(defaultFavourites);
|
const [favourites, setFavourites] = useState(defaultFavourites);
|
||||||
|
const [showFaovouritesOnly, setShowFavouritesOnly] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
@ -270,7 +272,8 @@ function App() {
|
|||||||
((showRunning && trainStatus == "Running") || (showNotYetRunning && trainStatus == "Not yet running") || (showTerminated && trainStatus == "Terminated")) &&
|
((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 == "Running" && showEarly && punctualityStr == "early") || (trainStatus == "Running" && showOnTime && punctualityStr == "On time") || (trainStatus == "Running" && showLate && punctualityStr == "late")
|
||||||
|| (trainStatus == "Not yet running" && showNotYetRunning) || (trainStatus == "Terminated" && showTerminated))) &&
|
|| (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;
|
break;
|
||||||
|
|
||||||
@ -287,7 +290,8 @@ function App() {
|
|||||||
|
|
||||||
markerText = item.trainStationCode + " " + item.trainStationDesc;
|
markerText = item.trainStationCode + " " + item.trainStationDesc;
|
||||||
display = (item.latitude !== "0" && item.longitude !== "0") &&
|
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;
|
break;
|
||||||
|
|
||||||
@ -300,40 +304,30 @@ function App() {
|
|||||||
toggleFavourite={toggleFavourite}
|
toggleFavourite={toggleFavourite}
|
||||||
favourites={favourites}
|
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;
|
markerText = item.busRouteAgencyName + " " + item.busRouteShortName + " " + item.busRouteLongName;
|
||||||
display = (item.latitude !== "0" && item.longitude !== "0") &&
|
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;
|
break;
|
||||||
|
|
||||||
case "BusStop":
|
case "BusStop":
|
||||||
objectTitle = item.busStopName + " Bus Stop";
|
objectTitle = item.busStopName + " Bus Stop";
|
||||||
popupContent = (
|
popupContent = (
|
||||||
<div>
|
<BusStopPopup
|
||||||
<h3>{objectTitle}</h3>
|
item={item}
|
||||||
<ul>
|
objectTitle={objectTitle}
|
||||||
<li><b>Bus Stop ID:</b> {item.busStopID}</li>
|
toggleFavourite={toggleFavourite}
|
||||||
<li><b>Bus Stop Name:</b> {item.busStopName}</li>
|
favourites={favourites}
|
||||||
<li><b>Bus Stop Code:</b> {item.busStopCode || "N/A"}</li>
|
/>
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
markerText = item.busStopName;
|
markerText = item.busStopName;
|
||||||
display = (item.latitude !== "0" && item.longitude !== "0") &&
|
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;
|
break;
|
||||||
|
|
||||||
@ -370,7 +364,8 @@ function App() {
|
|||||||
(showEnabled && item.luasStopIsEnabled === "1" || showDisabled && item.luasStopIsEnabled === "0") &&
|
(showEnabled && item.luasStopIsEnabled === "1" || showDisabled && item.luasStopIsEnabled === "0") &&
|
||||||
(!showCycleAndRide || (showCycleAndRide && item.luasStopIsCycleAndRide === "1")) &&
|
(!showCycleAndRide || (showCycleAndRide && item.luasStopIsCycleAndRide === "1")) &&
|
||||||
(!showParkAndRide || (showParkAndRide && item.luasStopIsParkAndRide === "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;
|
break;
|
||||||
@ -469,6 +464,8 @@ function App() {
|
|||||||
setClusteringEnabled={setClusteringEnabled}
|
setClusteringEnabled={setClusteringEnabled}
|
||||||
fetchData={fetchData}
|
fetchData={fetchData}
|
||||||
userLocationAvailable={userLocationAvailable}
|
userLocationAvailable={userLocationAvailable}
|
||||||
|
showFavouritesOnly={showFaovouritesOnly}
|
||||||
|
setShowFavouritesOnly={setShowFavouritesOnly}
|
||||||
/>
|
/>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<MapComponent
|
<MapComponent
|
||||||
|
@ -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 [isOpen, setIsOpen] = useState(false);
|
||||||
const [enabledSources, setEnabledSources] = useState([]); // New state to track enabled sources
|
const [enabledSources, setEnabledSources] = useState([]); // New state to track enabled sources
|
||||||
const [numberInputValue, setNumberInputValue] = useState(""); // State to manage number input value
|
const [numberInputValue, setNumberInputValue] = useState(""); // State to manage number input value
|
||||||
@ -183,7 +183,18 @@ const Sidebar = ({ selectedSources, setSelectedSources, clusteringEnabled, setCl
|
|||||||
setEnabledSources={setEnabledSources}
|
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
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="toggleClustering"
|
id="toggleClustering"
|
||||||
@ -218,6 +229,8 @@ Sidebar.propTypes = {
|
|||||||
setClusteringEnabled: PropTypes.func.isRequired,
|
setClusteringEnabled: PropTypes.func.isRequired,
|
||||||
fetchData: PropTypes.func.isRequired,
|
fetchData: PropTypes.func.isRequired,
|
||||||
userLocationAvailable: PropTypes.bool.isRequired,
|
userLocationAvailable: PropTypes.bool.isRequired,
|
||||||
|
showFavouritesOnly: PropTypes.bool.isRequired,
|
||||||
|
setShowFavouritesOnly: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Sidebar
|
export default Sidebar
|
||||||
|
Reference in New Issue
Block a user