[frontend]: Prevent user from deselecting all filters in a group

This commit is contained in:
2025-04-06 03:48:14 +01:00
parent 729b54942e
commit 56a4bfe27e
4 changed files with 102 additions and 57 deletions

View File

@ -23,6 +23,7 @@
"react-leaflet": "^5.0.0",
"react-leaflet-markercluster": "^5.0.0-rc.0",
"react-router-dom": "^7.3.0",
"react-toastify": "^11.0.5",
"recharts": "^2.15.1",
"tailwindcss": "^4.0.9"
},
@ -4459,6 +4460,19 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-toastify": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz",
"integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1"
},
"peerDependencies": {
"react": "^18 || ^19",
"react-dom": "^18 || ^19"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",

View File

@ -25,6 +25,7 @@
"react-leaflet": "^5.0.0",
"react-leaflet-markercluster": "^5.0.0-rc.0",
"react-router-dom": "^7.3.0",
"react-toastify": "^11.0.5",
"recharts": "^2.15.1",
"tailwindcss": "^4.0.9"
},

View File

@ -2,6 +2,9 @@ import React, { useState, useEffect, useMemo, useRef } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Cookies from "js-cookie";
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import Navbar from "./components/Navbar";
import Statistics from "./components/Statistics.jsx";
import Help from "./components/Help.jsx";
@ -441,6 +444,7 @@ function App() {
}, [memoizedFilteredMarkers]);
return (
<>
<Router>
<Navbar />
<Routes>
@ -497,6 +501,8 @@ function App() {
<Route path="/help" element={<Help />} />
</Routes>
</Router>
<ToastContainer position="bottom-right"/>
</>
);
}
export default App;

View File

@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from "react";
import PropTypes from 'prop-types';
import Cookies from "js-cookie";
import { toast } from 'react-toastify';
const menuData = [
{
@ -19,7 +20,7 @@ const menuData = [
{ id: "terminated", name: "Terminated", endsec: true },
{ id: "early", name: "Early" },
{ id: "on-time", name: "On-time" },
{ id: "late", name: "Late" },
{ id: "late", name: "Late", endsec: true },
],
},
{ id: "irish-rail-stations", name: "Irish Rail Stations" },
@ -42,11 +43,22 @@ const menuData = [
{ id: "enabled", name: "Enabled" },
{ id: "disabled", name: "Disabled", endsec: true },
{ id: "park-and-ride", name: "Must be Park & Ride" },
{ id: "cycle-and-ride", name: "Must be Cycle & Ride" },
{ id: "cycle-and-ride", name: "Must be Cycle & Ride", endsec: true },
],
},
];
const sectionGroups = [
["irish-rail", "bus", "luas-stops"],
["irish-rail-trains", "irish-rail-stations"],
["mainline", "suburban", "dart"],
["running", "not-yet-running", "terminated"],
["early", "on-time", "late"],
["buses", "bus-stops"],
["red-line", "green-line"],
["enabled", "disabled"],
];
const customDefaultChecked = ["mainline","suburban","dart","running","not-yet-running","terminated","early","on-time","late","disabled","buses","irish-rail-trains","luas-stops","enabled","green-line","red-line","irish-rail","bus"]
const getAllDefaultCheckedIds = (data) => {
@ -66,14 +78,26 @@ const getAllDefaultCheckedIds = (data) => {
};
const CheckboxItem = ({ item, selectedSources, setSelectedSources, enabledSources, setEnabledSources, level = 0, parentChecked = true }) => {
console.log("item id: " + item.id);
console.log(selectedSources.includes(item.id));
const isChecked = selectedSources.includes(item.id);
const isDisabled = !parentChecked; // Disable if any parent is not checked
const isEnabled = isChecked && parentChecked; // Only enabled if checked and parent is checked
const handleCheckboxChange = () => {
if (isChecked) {
if (item.id != "park-and-ride" && item.id != "cycle-and-ride") {
// Find which section this item is in
const section = sectionGroups.find(group => group.includes(item.id));
if (section.length > 1) {
const selectedInSection = section.filter(id => selectedSources.includes(id));
if (selectedInSection.length === 1 && selectedInSection[0] === item.id) {
toast.warn("At least one item in this section must be selected");
return; // Don't allow unchecking the last one
}
}
}
}
setSelectedSources((prev) =>
isChecked
? prev.filter((id) => id !== item.id)