From 38bc95c43fe871171bee37ca6fd36dabc61daa34 Mon Sep 17 00:00:00 2001 From: Dwayne Date: Sat, 4 Jan 2025 17:09:58 +0530 Subject: [PATCH 1/3] add emotion and MUI material dependencies --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 956b3ccc..f0e16865 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "author": "", "license": "ISC", "dependencies": { + "@emotion/react": "^11.13.5", + "@emotion/styled": "^11.13.5", "@hookform/resolvers": "^3.3.4", "@tanstack/react-query": "^5.28.4", "@tanstack/react-query-devtools": "^5.37.1", From 400f2a039f8da688ae939eb56f36fe625c9c0308 Mon Sep 17 00:00:00 2001 From: Dwayne Date: Sat, 4 Jan 2025 17:13:56 +0530 Subject: [PATCH 2/3] implement mentor filtering on mentor page --- src/pages/Mentors/index.tsx | 224 +++++++++++++++++++++++++----------- 1 file changed, 156 insertions(+), 68 deletions(-) diff --git a/src/pages/Mentors/index.tsx b/src/pages/Mentors/index.tsx index 7b84d1c8..e781b3e4 100644 --- a/src/pages/Mentors/index.tsx +++ b/src/pages/Mentors/index.tsx @@ -5,22 +5,25 @@ import { usePublicMentors } from '../../hooks/usePublicMentors'; import { type Mentor, type Category } from '../../types'; import MentorCard from '../../components/MentorCard/MentorCard.component'; import Loading from '../../assets/svg/Loading'; +import { ApplicationStatus } from '../../enums'; +import Slider from '@mui/material/Slider'; +import Box from '@mui/material/Box'; const Mentors = () => { const [selectedCategory, setSelectedCategory] = useState(null); + const [selectedCountries, setSelectedCountries] = useState([]); + const [selectedAvailableSlots, setSelectedAvailableSlots] = useState([0, 10]); const [sortedMentors, setSortedMentors] = useState([]); + const [uniqueCountries, setUniqueCountries] = useState([]); + const [uniqueAvailableSlots, setUniqueAvailableSlots] = useState([]); + const [isCountryDropdownOpen, setIsCountryDropdownOpen] = useState(false); + const [isSlotsDropdownOpen, setIsSlotsDropdownOpen] = useState(false); + const [isMobileFilterOpen, setIsMobileFilterOpen] = useState(false); const pageSize = 10; const { ref, inView } = useInView(); - - const { data, fetchNextPage, hasNextPage, isFetchingNextPage, status } = - usePublicMentors(selectedCategory, pageSize); - - const { - data: allCategories, - isLoading: categoriesLoading, - error: categoriesError, - } = useCategories(); + const { data, fetchNextPage, hasNextPage, isFetchingNextPage, status } = usePublicMentors(selectedCategory, pageSize); + const { data: allCategories, isLoading: categoriesLoading, error: categoriesError } = useCategories(); useEffect(() => { if (inView && hasNextPage) { @@ -31,21 +34,71 @@ const Mentors = () => { useEffect(() => { if (data) { const allMentors = data.pages.flatMap((page) => page.items); - setSortedMentors(allMentors); + const countries = allMentors.map((mentor) => mentor.application?.country).filter((country) => !!country); + setUniqueCountries([...new Set(countries)]); + const availableSlots = allMentors.map((mentor) => { + const approvedMenteesCount = mentor?.mentees ? mentor.mentees.filter((mentee) => mentee.state === ApplicationStatus.APPROVED).length : 0; + return Math.max(0, mentor.application.noOfMentees - approvedMenteesCount); + }).filter((slots, index, self) => self.indexOf(slots) === index); + setUniqueAvailableSlots(availableSlots); } }, [data]); + useEffect(() => { + if (data) { + let allMentors = data.pages.flatMap((page) => page.items); + if (selectedCountries.length > 0) { + allMentors = allMentors.filter((mentor) => selectedCountries.includes(mentor.application.country)); + } + const [minSlots, maxSlots] = selectedAvailableSlots; + if (minSlots > 0 || maxSlots < 10) { + allMentors = allMentors.filter((mentor) => { + const approvedMenteesCount = mentor?.mentees ? mentor.mentees.filter((mentee) => mentee.state === ApplicationStatus.APPROVED).length : 0; + return mentor?.application.noOfMentees ? Math.max(0, mentor.application.noOfMentees - approvedMenteesCount) >= minSlots && Math.max(0, mentor.application.noOfMentees - approvedMenteesCount) <= maxSlots : false; + }); + } + setSortedMentors(allMentors); + } + }, [data, selectedCountries, selectedAvailableSlots]); + const handleSortAZ = () => { const sorted = [...sortedMentors].sort((a, b) => a.application.firstName.localeCompare(b.application.firstName) - ); - setSortedMentors(sorted); + );setSortedMentors(sorted); }; const handleCategoryChange = (category: string | null) => { setSelectedCategory(category); }; + const handleCountryChange = (country: string) => { + setSelectedCountries((prevCountries) => { + if (prevCountries.includes(country)) { + return prevCountries.filter((c) => c !== country); + } else { + return [...prevCountries, country]; + } + }); + }; + + const handleAvailableSlotsChange = (event: Event, newValue: number | number[]) => { + if (Array.isArray(newValue)) { + setSelectedAvailableSlots(newValue); + } + }; + + const toggleCountryDropdown = () => { + setIsCountryDropdownOpen(!isCountryDropdownOpen); + }; + + const toggleSlotsDropdown = () => { + setIsSlotsDropdownOpen(!isSlotsDropdownOpen); + }; + + const toggleMobileFilter = () => { + setIsMobileFilterOpen(!isMobileFilterOpen); + }; + if (status === 'pending' || categoriesLoading) { return (
@@ -59,69 +112,104 @@ const Mentors = () => { } return ( -
-
-
-

Mentors

-
-
- -
-
- - {allCategories.map((category: Category) => ( - - ))} +
+
+ +
+

Filters

+ +
+

Categories

+
+ + {allCategories.map((category: Category) => ( + + ))} +
-
-
- -
+
+

+ +

+ {isCountryDropdownOpen && ( +
+ + {uniqueCountries.map((country) => ( + + ))} +
+ )} +
- {sortedMentors.length > 0 ? ( -
- {sortedMentors.map((mentor) => ( - - ))} +
+

+ +

+ {isSlotsDropdownOpen && ( + + `${value} slots`} + min={0} + max={10} + step={1} + /> + + )}
- ) : ( -

No mentors found for this category.

- )} - {isFetchingNextPage && ( -
- +
+
- )} +
-
+
+
+

Mentors

+
+ + {sortedMentors.length > 0 ? ( +
+ {sortedMentors.map((mentor) => ( + + ))} +
+ ) : ( +

No mentors found for this filter.

+ )} + + {isFetchingNextPage && ( +
+ +
+ )} + +
+
+
); From b4d0151d3d6fcf006d9f6690d10eb22fabe4c648 Mon Sep 17 00:00:00 2001 From: Dwayne Date: Sat, 4 Jan 2025 17:14:25 +0530 Subject: [PATCH 3/3] add emotion and MUI material dependencies --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index f0e16865..c085b15d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@emotion/react": "^11.13.5", "@emotion/styled": "^11.13.5", "@hookform/resolvers": "^3.3.4", + "@mui/material": "^6.3.1", "@tanstack/react-query": "^5.28.4", "@tanstack/react-query-devtools": "^5.37.1", "axios": "^1.4.0",