diff --git a/src/components/CreateProject/StaffAllocation.tsx b/src/components/CreateProject/StaffAllocation.tsx index c408b57..7c5b806 100644 --- a/src/components/CreateProject/StaffAllocation.tsx +++ b/src/components/CreateProject/StaffAllocation.tsx @@ -24,8 +24,10 @@ import { TabsProps, Tab, Tabs, + SelectChangeEvent, } from "@mui/material"; import differenceBy from "lodash/differenceBy"; +import uniq from "lodash/uniq"; interface StaffResult { id: string; @@ -100,16 +102,17 @@ const StaffAllocation: React.FC = ({ const [selectedStaff, setSelectedStaff] = React.useState< typeof filteredStaff >(initiallySelectedStaff); - const filters = React.useMemo<(keyof StaffResult)[]>( - () => ["team", "grade"], - [], - ); + + // Adding / Removing staff const addStaff = React.useCallback((staff: StaffResult) => { setSelectedStaff((staffs) => [...staffs, staff]); }, []); const removeStaff = React.useCallback((staff: StaffResult) => { setSelectedStaff((staffs) => staffs.filter((s) => s.id !== staff.id)); }, []); + const clearStaff = React.useCallback(() => { + setSelectedStaff([]); + }, []); const staffPoolColumns = React.useMemo[]>( () => [ @@ -145,6 +148,7 @@ const StaffAllocation: React.FC = ({ [removeStaff, t], ); + // Query related const [query, setQuery] = React.useState(""); const onQueryInputChange = React.useCallback< React.ChangeEventHandler @@ -154,18 +158,55 @@ const StaffAllocation: React.FC = ({ const clearQueryInput = React.useCallback(() => { setQuery(""); }, []); + const columnFilters = React.useMemo<(keyof StaffResult)[]>( + () => ["team", "grade"], + [], + ); + const filterValues = React.useMemo(() => { + return columnFilters.reduce<{ [filter in keyof StaffResult]?: string[] }>( + (acc, filter) => { + return { + ...acc, + [filter]: uniq(allStaff.map((staff) => staff[filter])), + }; + }, + {}, + ); + }, [columnFilters, allStaff]); + const defaultFilterValues = React.useMemo(() => { + return columnFilters.reduce<{ [filter in keyof StaffResult]?: string }>( + (acc, filter) => { + return { ...acc, [filter]: "All" }; + }, + {}, + ); + }, [columnFilters]); + const [filters, setFilters] = React.useState(defaultFilterValues); + const makeFilterSelect = React.useCallback( + (filter: keyof StaffResult) => (event: SelectChangeEvent) => { + setFilters((f) => ({ ...f, [filter]: event.target.value })); + }, + [], + ); React.useEffect(() => { setFilteredStaff( - allStaff.filter( - (staff) => - staff.name.toLowerCase().includes(query) || - staff.id.toLowerCase().includes(query) || - staff.title.toLowerCase().includes(query), - ), + allStaff.filter((staff) => { + const q = query.toLowerCase(); + return ( + (staff.name.toLowerCase().includes(q) || + staff.id.toLowerCase().includes(q) || + staff.title.toLowerCase().includes(q)) && + Object.entries(filters).every(([filterKey, filterValue]) => { + const staffColumnValue = staff[filterKey as keyof StaffResult]; + return staffColumnValue === filterValue || filterValue === "All"; + }) + ); + }), ); - }, [allStaff, query]); + }, [allStaff, filters, query]); + // Tab related const [tabIndex, setTabIndex] = React.useState(0); const handleTabChange = React.useCallback>( (_e, newValue) => { @@ -174,6 +215,12 @@ const StaffAllocation: React.FC = ({ [], ); + const reset = React.useCallback(() => { + clearQueryInput(); + clearStaff(); + setFilters(defaultFilterValues); + }, [clearQueryInput, clearStaff, defaultFilterValues]); + return ( @@ -201,7 +248,7 @@ const StaffAllocation: React.FC = ({ }} /> - {filters.map((filter, idx) => { + {columnFilters.map((filter, idx) => { const label = staffPoolColumns.find( (c) => c.name === filter, )!.label; @@ -210,8 +257,18 @@ const StaffAllocation: React.FC = ({ {label} - {t("All")} + {filterValues[filter]?.map((option, index) => ( + + {option} + + ))} @@ -220,7 +277,7 @@ const StaffAllocation: React.FC = ({ - + {tabIndex === 0 && ( @@ -240,7 +297,7 @@ const StaffAllocation: React.FC = ({ -