+
{approvedMentees.map(renderMenteeLink)}
{approvedMentees.length === 0 && (
No approved mentees available.
diff --git a/src/pages/MentorProfile/MentorProfile.component.tsx b/src/pages/MentorProfile/MentorProfile.component.tsx
index 8e86cb3e..391e5f9d 100644
--- a/src/pages/MentorProfile/MentorProfile.component.tsx
+++ b/src/pages/MentorProfile/MentorProfile.component.tsx
@@ -193,22 +193,28 @@ const MentorProfile: React.FC = () => {
diff --git a/src/pages/MentorRegistration/MentorRegistration.component.tsx b/src/pages/MentorRegistration/MentorRegistration.component.tsx
index aed43ad0..1d41b94f 100644
--- a/src/pages/MentorRegistration/MentorRegistration.component.tsx
+++ b/src/pages/MentorRegistration/MentorRegistration.component.tsx
@@ -14,6 +14,7 @@ import { useLoginModalContext } from '../../contexts/LoginModalContext';
import useMentor from '../../hooks/useMentor';
import { Link } from 'react-router-dom';
import TermsAgreementModalMentor from '../../components/TermsAgreementModal';
+import useCountries from '../../hooks/useCountries';
const steps = [
{
@@ -63,6 +64,12 @@ const MentorRegistrationPage: React.FC = () => {
error: categoriesError,
} = useCategories();
+ const {
+ data: allCountries,
+ isLoading: countriesLoading,
+ error: countriesError,
+ } = useCountries();
+
const {
createMentorApplication,
applicationError,
@@ -265,14 +272,25 @@ const MentorRegistrationPage: React.FC = () => {
register={register}
error={errors.contactNo}
/>
-
+
+
+ {!countriesLoading && (
+
+ )}
+
>
)}
{currentStep === 1 && (
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 (
-
-
-
-
-
-
-
-
- {allCategories.map((category: Category) => (
-
- ))}
+
+
+
+
-
-
-
+
- {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 && (
+
+
+
+ )}
+
+
+
+
);
diff --git a/src/schemas.ts b/src/schemas.ts
index e1f8ed34..1933f220 100644
--- a/src/schemas.ts
+++ b/src/schemas.ts
@@ -124,14 +124,14 @@ export const MentorApplicationSchema = z.object({
});
export const MenteeCheckInSchema = z.object({
- title: z.string().min(1, 'Title is required'),
+ month: z.string().min(1, 'Month is required'),
generalUpdatesAndFeedback: z
.string()
.min(5, 'Please provide general updates'),
progressTowardsGoals: z.string().min(5, 'Please summarize your progress'),
mediaContentLinks: z
.array(z.string().url('Please provide a valid URL'))
- .min(1, 'Please provide at least 1 media links'),
+ .optional(),
});
export const MentorFeedbackSchema = z.object({
diff --git a/src/types.ts b/src/types.ts
index 15d4bba7..fb8c4006 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -108,7 +108,7 @@ export type MenteeCheckInForm = z.infer
;
export interface MonthlyCheckIn {
uuid: string;
- title: string;
+ month: string;
checkInDate: string;
mediaContentLinks: string[];
isCheckedByMentor: boolean;