Skip to content

Commit

Permalink
style: adjust style
Browse files Browse the repository at this point in the history
  • Loading branch information
ZL-Asica committed Dec 6, 2024
1 parent 58898f0 commit 014b64c
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 104 deletions.
94 changes: 53 additions & 41 deletions src/components/Home/DonorDashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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 ? (
<div>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
}}
>
<Box
display='flex'
gap={2}
alignItems='center'
mb={3}
sx={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<SearchBar onSearchChange={setSearchQuery} />
<Filters
Expand All @@ -67,15 +81,13 @@ const DonorDashboard = () => {
/>
</Box>

<Box sx={{ display: 'flex', flexDirection: 'column' }}>
{filteredByNeedsAndDescription.map((org) => (
<OrganizationCard
organization={org}
key={org.uid}
/>
))}
</Box>
</div>
{filteredOrganizations.map((org) => (
<OrganizationCard
organization={org}
key={org.uid}
/>
))}
</Box>
) : (
<Typography
variant='body1'
Expand Down
122 changes: 75 additions & 47 deletions src/components/common/Filters.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import React, { useState } from 'react';
import { Box, Button, TextField, Popover, InputAdornment } from '@mui/material';
import { useState } from 'react';
import {
Box,
Button,
Popover,
FormControl,
InputLabel,
Select,
MenuItem,
TextField,
} from '@mui/material';
import FilterListIcon from '@mui/icons-material/FilterList';

import { useOrganizationStore } from '@/stores';

interface FiltersProps {
needsQuery: string;
setNeedsQuery: (query: string) => void;
Expand All @@ -11,32 +22,40 @@ interface FiltersProps {
setLocationQuery: (query: string) => void;
}

const Filters: React.FC<FiltersProps> = ({
const Filters = ({
needsQuery,
setNeedsQuery,
descriptionQuery,
setDescriptionQuery,
locationQuery,
setLocationQuery,
}) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
}: FiltersProps) => {
const organizationProfiles = useOrganizationStore(
(state) => state.organizationProfiles
);

const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const [anchorElement, setAnchorElement] = useState<null | HTMLElement>(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 (
<Box>
<Button
variant='contained'
onClick={handleOpen}
onClick={(event_) => setAnchorElement(event_.currentTarget)}
startIcon={<FilterListIcon />}
sx={{ marginTop: 2 }}
>
Expand All @@ -45,7 +64,7 @@ const Filters: React.FC<FiltersProps> = ({
<Popover
id={id}
open={open}
anchorEl={anchorEl}
anchorEl={anchorElement}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
Expand All @@ -65,50 +84,59 @@ const Filters: React.FC<FiltersProps> = ({
width: '300px',
}}
>
<TextField
label='Filter by Needs'
variant='outlined'
value={needsQuery}
onChange={(e) => setNeedsQuery(e.target.value)}
slotProps={{
input: {
startAdornment: (
<InputAdornment position='start'>
<FilterListIcon />
</InputAdornment>
),
},
}}
/>
{/* Needs dropdown */}
<FormControl fullWidth>
<InputLabel id='needs-filter-label'>Filter by Needs</InputLabel>
<Select
labelId='needs-filter-label'
value={needsQuery}
onChange={(event_) => setNeedsQuery(event_.target.value)}
MenuProps={{
anchorOrigin: {
vertical: 'bottom',
horizontal: 'left',
},
transformOrigin: {
vertical: 'top',
horizontal: 'left',
},
PaperProps: {
style: {
maxHeight: 'calc(80vh - 96px)',
overflowY: 'auto',
},
},
disablePortal: false,
}}
>
<MenuItem value=''>All</MenuItem>
{needsOptions.map((need, index) => (
<MenuItem
key={index}
value={String(need)}
>
{String(need)}
</MenuItem>
))}
</Select>
</FormControl>

{/* Description text field */}
<TextField
label='Filter by Description'
variant='outlined'
fullWidth
value={descriptionQuery}
onChange={(e) => setDescriptionQuery(e.target.value)}
slotProps={{
input: {
startAdornment: (
<InputAdornment position='start'>
<FilterListIcon />
</InputAdornment>
),
},
}}
onChange={(event_) => setDescriptionQuery(event_.target.value)}
/>

{/* Location text field */}
<TextField
label='Filter by Location'
variant='outlined'
fullWidth
value={locationQuery}
onChange={(e) => setLocationQuery(e.target.value)}
slotProps={{
input: {
startAdornment: (
<InputAdornment position='start'>
<FilterListIcon />
</InputAdornment>
),
},
}}
onChange={(event_) => setLocationQuery(event_.target.value)}
/>
</Box>
</Popover>
Expand Down
25 changes: 9 additions & 16 deletions src/components/common/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ChangeEvent } from 'react';
import { useCallback, useMemo, useEffect, useState } from 'react';
import { TextField, Box, Button } from '@mui/material';
import { TextField } from '@mui/material';
import { useSearchParams } from 'react-router-dom';
import { debounce } from 'es-toolkit/compat';

Expand Down Expand Up @@ -42,21 +42,14 @@ const SearchBar = ({ onSearchChange }: SearchBarProps) => {
}, [searchParams, onSearchChange]);

return (
<Box
display='flex'
alignItems='center'
mt={3}
mx={2}
>
<TextField
label='Search organizations...'
variant='outlined'
fullWidth
sx={{ marginRight: 1 }}
value={query}
onChange={handleInputChange}
/>
</Box>
<TextField
label='Search organizations...'
variant='outlined'
fullWidth
sx={{ mx: 1, mt: 3, mr: 2 }}
value={query}
onChange={handleInputChange}
/>
);
};

Expand Down

0 comments on commit 014b64c

Please sign in to comment.