diff --git a/editor.planx.uk/src/pages/Filters.tsx b/editor.planx.uk/src/pages/Filters.tsx index 0b88b11306..73787e5cfc 100644 --- a/editor.planx.uk/src/pages/Filters.tsx +++ b/editor.planx.uk/src/pages/Filters.tsx @@ -3,9 +3,12 @@ import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import { styled } from "@mui/material/styles"; import Typography from "@mui/material/Typography"; -import React from "react"; +import React, { useEffect, useState } from "react"; +import { useNavigation } from "react-navi"; import ChecklistItem from "ui/shared/ChecklistItem/ChecklistItem"; +import { FlowSummary } from "./FlowEditor/lib/store/editor"; + const FiltersContainer = styled(Box)(({ theme }) => ({ width: "100%", display: "flex", @@ -41,7 +44,106 @@ const FiltersFooter = styled(Box)(({ theme }) => ({ padding: theme.spacing(1.5, 2), })); -const Filters: React.FC = () => { +interface FiltersProps { + flows: FlowSummary[]; + setFilteredFlows: React.Dispatch>; +} + +interface FilterState { + status?: "online" | "offline"; + applicationType?: "submission" | "guidance"; + serviceType?: "statutory" | "discretionary"; +} + +type FilterKeys = keyof FilterState; +type FilterValues = FilterState[keyof FilterState]; + +export const Filters: React.FC = ({ + flows, + setFilteredFlows, +}) => { + { + /* + - thinking here is to build in type safety into the filter categories + - create a fn to setFlows based on the filters selected + - could we build a component which has the Column, Typo and ChecklistItems + ~ This way we could build a type safe filterOptions array which we can iterate over to create + the filter options. Could make it scale nicely + - I've also added a new flows list called filteredFlows so we can maintain an original + */ + } + + const [filters, setFilters] = useState(); + + const navigation = useNavigation(); + + const addToSearchParams = (params: FilterState) => { + const newSearchParams = new URLSearchParams(); + filters && + Object.entries(params).forEach(([key, value]) => { + if (value) { + newSearchParams.set(key, value); + } else { + newSearchParams.delete(key); + } + }); + + navigation.navigate( + { + pathname: window.location.pathname, + search: newSearchParams.toString() + ? `?${newSearchParams.toString()}` + : "", + }, + { + replace: true, + }, + ); + }; + + useEffect(() => { + const params = new URLSearchParams(window.location.search); + let filterObj = {}; + params.forEach((value, key) => { + switch (key) { + case "status": + filterObj = { ...filterObj, status: value }; + break; + case "applicationType": + filterObj = { ...filterObj, applicationType: value }; + break; + case "serviceType": + filterObj = { ...filterObj, serviceType: value }; + break; + } + setFilters(filterObj); + }); + }, []); + + const handleFiltering = () => { + const filterByStatus = flows.filter((flow: FlowSummary) => { + if (filters?.status) { + return flow.status === filters.status; + } else { + return true; + } + }); + filterByStatus && setFilteredFlows(filterByStatus); + filters && addToSearchParams(filters); + if ( + !filters?.status && + !filters?.applicationType && + !filters?.serviceType + ) { + setFilteredFlows(flows); + } + }; + + const handleChange = (filterKey: FilterKeys, filterValue: FilterValues) => + filters?.[filterKey] === filterValue + ? setFilters({ ...filters, [filterKey]: undefined }) + : setFilters({ ...filters, [filterKey]: filterValue }); + return ( @@ -53,51 +155,51 @@ const Filters: React.FC = () => { Online status {}} + onChange={() => handleChange("status", "online")} label={"Online"} - checked={false} + checked={filters?.status === "online"} variant="compact" /> {}} + onChange={() => handleChange("status", "offline")} label={"Offline"} - checked={false} + checked={filters?.status === "offline"} variant="compact" /> Application type {}} + onChange={() => handleChange("applicationType", "submission")} label={"Submission"} - checked={false} + checked={filters?.applicationType === "submission"} variant="compact" /> {}} + onChange={() => handleChange("applicationType", "guidance")} label={"Guidance"} - checked={false} + checked={filters?.applicationType === "guidance"} variant="compact" /> Service type {}} + onChange={() => handleChange("serviceType", "statutory")} label={"Statutory"} - checked={false} + checked={filters?.serviceType === "statutory"} variant="compact" /> {}} + onChange={() => handleChange("serviceType", "discretionary")} label={"Discretionary"} - checked={false} + checked={filters?.serviceType === "discretionary"} variant="compact" /> - diff --git a/editor.planx.uk/src/pages/Team.tsx b/editor.planx.uk/src/pages/Team.tsx index c20a8cc8a5..bba5bbbff9 100644 --- a/editor.planx.uk/src/pages/Team.tsx +++ b/editor.planx.uk/src/pages/Team.tsx @@ -318,7 +318,9 @@ const GetStarted: React.FC<{ flows: FlowSummary[] }> = ({ flows }) => ( ); -const AddFlowButton: React.FC<{ flows: FlowSummary[] }> = ({ flows }) => { +const AddFlowButton: React.FC<{ flows: FlowSummary[] | null }> = ({ + flows, +}) => { const { navigate } = useNavigation(); const { teamId, createFlow, teamSlug } = useStore(); @@ -348,6 +350,9 @@ const Team: React.FC = () => { (state) => [state.getTeam(), state.canUserEditTeam, state.getFlows], ); const [flows, setFlows] = useState(null); + const [filteredFlows, setFilteredFlows] = useState( + null, + ); const fetchFlows = useCallback(() => { getFlows(teamId).then((flows) => { @@ -358,6 +363,7 @@ const Team: React.FC = () => { ), ); setFlows(sortedFlows); + setFilteredFlows(sortedFlows); }); }, [teamId, setFlows, getFlows]); @@ -365,7 +371,7 @@ const Team: React.FC = () => { fetchFlows(); }, [fetchFlows]); - const teamHasFlows = flows && Boolean(flows.length); + const teamHasFlows = filteredFlows && Boolean(filteredFlows.length); const showAddFlowButton = teamHasFlows && canUserEditTeam(slug); return ( @@ -409,7 +415,7 @@ const Team: React.FC = () => { - + {flows && } {teamHasFlows && ( <> { - {flows.map((flow) => ( + {filteredFlows.map((flow) => (