diff --git a/package.json b/package.json index 1d1ebdb9..ab6c1cba 100755 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "chartjs-adapter-date-fns": "^3.0.0", "chartjs-plugin-annotation": "^3.1.0", "date-fns": "^4.1.0", + "dompurify": "^3.3.2", "dotenv": "^16.4.7", "file-saver": "^2.0.5", "html2canvas": "^1.4.1", @@ -33,6 +34,7 @@ "react-ga4": "^2.1.0", "react-hot-toast": "^2.5.1", "react-icons": "^5.5.0", + "react-intersection-observer": "^10.0.3", "react-router": "7.6.3", "react-router-dom": "7.6.3", "react-scripts": "5.0.1", diff --git a/src/App.jsx b/src/App.jsx index e4d876e9..941f0372 100755 --- a/src/App.jsx +++ b/src/App.jsx @@ -6,10 +6,12 @@ import PlansPage from "./components/plansPage"; import PlanViewPage from "./components/plan_detailView"; import AgroHorticulture from "./pages/AgroHorticulture"; import RWBDashboard from "./pages/RWBDashboard"; +import ToastHandler from "./components/ui/ToastHandler"; function App() { return ( + } /> } /> diff --git a/src/components/buttons/select_button.jsx b/src/components/buttons/select_button.jsx index 6d632011..0f1f663e 100755 --- a/src/components/buttons/select_button.jsx +++ b/src/components/buttons/select_button.jsx @@ -1,7 +1,14 @@ -import { useMemo } from 'react'; -import Select from 'react-select'; +import { useMemo } from "react"; +import Select from "react-select"; -const SelectButton = ({ stateData, handleItemSelect, setState, currVal }) => { +const SelectButton = ({ + stateData, + handleItemSelect, + setState, + currVal, + className = "", + placeholder = "Select option", +}) => { // ---------- sort by label, keeping original untouched ---------- const sortedOptions = useMemo(() => { if (!stateData) return []; @@ -9,38 +16,76 @@ const SelectButton = ({ stateData, handleItemSelect, setState, currVal }) => { }, [stateData]); const customStyles = { - container: (provided) => ({ ...provided, width: '100%' }), + container: (provided) => ({ ...provided, width: "100%" }), control: (base, state) => ({ ...base, - borderColor: 'black', - backgroundColor: 'white', - textAlign: 'center', - width: '100%', + minHeight: 44, + borderRadius: 12, + borderColor: state.isFocused ? "#8B5CF6" : "#D1D5DB", + backgroundColor: state.isDisabled ? "#F9FAFB" : "white", + textAlign: "left", + width: "100%", + boxShadow: state.isFocused ? "0 0 0 3px rgba(139, 92, 246, 0.18)" : "none", + cursor: state.isDisabled ? "not-allowed" : "pointer", + transition: "border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease", + "&:hover": { + borderColor: state.isFocused ? "#8B5CF6" : "#A78BFA", + }, + }), + valueContainer: (base) => ({ + ...base, + paddingLeft: 10, + paddingRight: 10, + }), + placeholder: (base) => ({ + ...base, + color: "#6B7280", + }), + singleValue: (base) => ({ + ...base, + color: "#111827", }), option: (styles, { isFocused, isSelected }) => ({ ...styles, - color: '#111827', + color: "#111827", backgroundColor: isSelected - ? '#11182732' + ? "#EDE9FE" : isFocused - ? '#11182717' + ? "#F5F3FF" : undefined, - ':active': { ...styles[':active'], backgroundColor: '#11182717' }, + cursor: "pointer", + transition: "background-color 180ms ease", + ":active": { ...styles[":active"], backgroundColor: "#DDD6FE" }, + }), + menu: (provided) => ({ + ...provided, + width: "100%", + borderRadius: 12, + overflow: "hidden", + boxShadow: "0 16px 32px rgba(15, 23, 42, 0.14)", + }), + indicatorSeparator: () => ({ display: "none" }), + dropdownIndicator: (base, state) => ({ + ...base, + color: state.isFocused ? "#8B5CF6" : "#6B7280", + transition: "color 180ms ease, transform 180ms ease", + transform: state.selectProps.menuIsOpen ? "rotate(180deg)" : "rotate(0deg)", }), - menu: (provided) => ({ ...provided, width: '100%' }), }; return ( -
+