From 227a348709839eb77ea10f6b6e1750ccc23b0634 Mon Sep 17 00:00:00 2001 From: WelldoneM Date: Fri, 6 Dec 2024 10:43:18 -0600 Subject: [PATCH 1/3] filters --- src/components/Home/DonorDashboard/index.tsx | 49 +++++++- src/components/common/Filters.tsx | 119 +++++++++++++++++++ src/components/common/SearchBar.tsx | 55 ++++++--- src/components/common/index.tsx | 1 + 4 files changed, 201 insertions(+), 23 deletions(-) create mode 100644 src/components/common/Filters.tsx diff --git a/src/components/Home/DonorDashboard/index.tsx b/src/components/Home/DonorDashboard/index.tsx index 658f048..194db65 100644 --- a/src/components/Home/DonorDashboard/index.tsx +++ b/src/components/Home/DonorDashboard/index.tsx @@ -7,10 +7,13 @@ import OrganizationCard from './OrganizationCard'; import { useOrganizationStore } from '@/stores'; -import { SearchBar, LoadingCircle } from '@/components/common'; +import { SearchBar, LoadingCircle, Filters } from '@/components/common'; const DonorDashboard = () => { const [searchQuery, setSearchQuery] = useState(''); + const [needsQuery, setNeedsQuery] = useState(''); + const [descriptionQuery, setDescriptionQuery] = useState(''); + const [locationQuery, setLocationQuery] = useState(''); const { organizationProfiles, fetchProfiles, @@ -43,14 +46,48 @@ const DonorDashboard = () => { ); }); + //filtering organizations based on needs and description + const filteredByNeedsAndDescription = filter(filteredOrganizations, (org) => { + const matchesNeeds = needsQuery + ? some(org.needs, (need) => + lowerCase(need.itemName || '').includes(lowerCase(needsQuery)) + ) + : true; + + const matchesDescription = descriptionQuery + ? lowerCase(org.description || '').includes(lowerCase(descriptionQuery)) + : true; + + const matchesLocation = locationQuery + ? lowerCase(org.location || '').includes(lowerCase(locationQuery)) + : true; + + return matchesNeeds && matchesDescription && matchesLocation; + }); + return organizationProfiles.length > 0 ? (
- + + + + - {filteredOrganizations.map((org) => ( + {filteredByNeedsAndDescription.map((org) => ( void; + descriptionQuery: string; + setDescriptionQuery: (query: string) => void; + locationQuery: string; + setLocationQuery: (query: string) => void; +} + +const Filters: React.FC = ({ + needsQuery, + setNeedsQuery, + descriptionQuery, + setDescriptionQuery, + locationQuery, + setLocationQuery, +}) => { + const [anchorEl, setAnchorEl] = useState(null); + + const handleOpen = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const open = Boolean(anchorEl); + const id = open ? 'filters-popover' : undefined; + + return ( + + + + + setNeedsQuery(e.target.value)} + slotProps={{ + input: { + startAdornment: ( + + + + ), + }, + }} + /> + setDescriptionQuery(e.target.value)} + slotProps={{ + input: { + startAdornment: ( + + + + ), + }, + }} + /> + setLocationQuery(e.target.value)} + slotProps={{ + input: { + startAdornment: ( + + + + ), + }, + }} + /> + + + + ); +}; + +export default Filters; diff --git a/src/components/common/SearchBar.tsx b/src/components/common/SearchBar.tsx index db76a90..57c29ad 100644 --- a/src/components/common/SearchBar.tsx +++ b/src/components/common/SearchBar.tsx @@ -1,4 +1,34 @@ -import { TextField, Box, Button } from '@mui/material'; +// import { TextField, Box} from '@mui/material'; + +// interface SearchBarProps { +// searchQuery: string; +// setSearchQuery: (query: string) => void; +// } + +// const SearchBar: React.FC = ({ +// searchQuery, +// setSearchQuery, +// }) => ( +// +// setSearchQuery(e.target.value)} +// /> +// +// ); + +// export default SearchBar; + +import { TextField, Box } from '@mui/material'; interface SearchBarProps { searchQuery: string; @@ -9,22 +39,13 @@ const SearchBar: React.FC = ({ searchQuery, setSearchQuery, }) => ( - - setSearchQuery(e.target.value)} - /> - - + setSearchQuery(e.target.value)} + /> ); export default SearchBar; diff --git a/src/components/common/index.tsx b/src/components/common/index.tsx index 28914be..91b687e 100644 --- a/src/components/common/index.tsx +++ b/src/components/common/index.tsx @@ -5,3 +5,4 @@ export { default as ProtectedRoute } from './ProtectedRoute'; export { default as CustomDialog } from './CustomDialog'; export { default as RoleSelectionModal } from './RoleSelectionModal'; export { default as Layout } from './Layout'; +export { default as Filters } from './Filters'; From 1aefcf1fe80882a8ff8ea3c78d69dd13b3a1c086 Mon Sep 17 00:00:00 2001 From: WelldoneM Date: Fri, 6 Dec 2024 10:46:36 -0600 Subject: [PATCH 2/3] changes to search bar --- src/components/common/SearchBar.tsx | 32 +---------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/src/components/common/SearchBar.tsx b/src/components/common/SearchBar.tsx index 57c29ad..71ee2d3 100644 --- a/src/components/common/SearchBar.tsx +++ b/src/components/common/SearchBar.tsx @@ -1,34 +1,4 @@ -// import { TextField, Box} from '@mui/material'; - -// interface SearchBarProps { -// searchQuery: string; -// setSearchQuery: (query: string) => void; -// } - -// const SearchBar: React.FC = ({ -// searchQuery, -// setSearchQuery, -// }) => ( -// -// setSearchQuery(e.target.value)} -// /> -// -// ); - -// export default SearchBar; - -import { TextField, Box } from '@mui/material'; +import { TextField } from '@mui/material'; interface SearchBarProps { searchQuery: string; From 014b64c14e1aceebee9fdc8591afe32260955f98 Mon Sep 17 00:00:00 2001 From: ZL Asica <40444637+ZL-Asica@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:50:19 -0600 Subject: [PATCH 3/3] style: adjust style --- src/components/Home/DonorDashboard/index.tsx | 94 +++++++------- src/components/common/Filters.tsx | 122 ++++++++++++------- src/components/common/SearchBar.tsx | 25 ++-- 3 files changed, 137 insertions(+), 104 deletions(-) diff --git a/src/components/Home/DonorDashboard/index.tsx b/src/components/Home/DonorDashboard/index.tsx index 294b0d1..0170d2a 100644 --- a/src/components/Home/DonorDashboard/index.tsx +++ b/src/components/Home/DonorDashboard/index.tsx @@ -1,6 +1,5 @@ import { Box, Typography } from '@mui/material'; -import { filter, lowerCase, some } from 'es-toolkit/compat'; -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import OrganizationCard from './OrganizationCard'; @@ -18,43 +17,58 @@ const DonorDashboard = () => { (state) => state.organizationProfiles ); - // Filtered organizations based on search query - const filteredOrganizations = filter(organizationProfiles, (org) => { - if (!org.name) return false; - const searchTerm = lowerCase(searchQuery); - return ( - lowerCase(org.name).includes(searchTerm) || - lowerCase(org.location).includes(searchTerm) || - some(org.needs, (need) => lowerCase(need).includes(searchTerm)) - ); - }); + const filteredOrganizations = useMemo(() => { + return organizationProfiles.filter((org) => { + const matchesSearch = searchQuery + ? org.name.toLowerCase().includes(searchQuery.toLowerCase()) || + org.location.toLowerCase().includes(searchQuery.toLowerCase()) || + (org.needs || []).some((need) => + need.itemName.toLowerCase().includes(searchQuery.toLowerCase()) + ) + : true; - //filtering organizations based on needs and description - const filteredByNeedsAndDescription = filter(filteredOrganizations, (org) => { - const matchesNeeds = needsQuery - ? some(org.needs, (need) => - lowerCase(need.itemName || '').includes(lowerCase(needsQuery)) - ) - : true; + const matchesNeeds = needsQuery + ? (org.needs || []).some((need) => + need.itemName.toLowerCase().includes(needsQuery.toLowerCase()) + ) + : true; - const matchesDescription = descriptionQuery - ? lowerCase(org.description || '').includes(lowerCase(descriptionQuery)) - : true; + const matchesDescription = descriptionQuery + ? org.description + ?.toLowerCase() + .includes(descriptionQuery.toLowerCase()) + : true; - const matchesLocation = locationQuery - ? lowerCase(org.location || '').includes(lowerCase(locationQuery)) - : true; + const matchesLocation = locationQuery + ? org.location.toLowerCase().includes(locationQuery.toLowerCase()) + : true; - return matchesNeeds && matchesDescription && matchesLocation; - }); + return ( + matchesSearch && matchesNeeds && matchesDescription && matchesLocation + ); + }); + }, [ + organizationProfiles, + searchQuery, + needsQuery, + descriptionQuery, + locationQuery, + ]); return organizationProfiles.length > 0 ? ( -
+ { /> - - {filteredByNeedsAndDescription.map((org) => ( - - ))} - -
+ {filteredOrganizations.map((org) => ( + + ))} +
) : ( void; @@ -11,32 +22,40 @@ interface FiltersProps { setLocationQuery: (query: string) => void; } -const Filters: React.FC = ({ +const Filters = ({ needsQuery, setNeedsQuery, descriptionQuery, setDescriptionQuery, locationQuery, setLocationQuery, -}) => { - const [anchorEl, setAnchorEl] = useState(null); +}: FiltersProps) => { + const organizationProfiles = useOrganizationStore( + (state) => state.organizationProfiles + ); - const handleOpen = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; + const [anchorElement, setAnchorElement] = useState(null); const handleClose = () => { - setAnchorEl(null); + setAnchorElement(null); }; - const open = Boolean(anchorEl); + const open = Boolean(anchorElement); const id = open ? 'filters-popover' : undefined; + const needsOptions = [ + ...new Set( + organizationProfiles.flatMap( + (org) => org.needs?.flatMap((need) => need.itemName) || [] + ) + ), + ].filter(Boolean); + return (