From acd877a90829d16bba6d4aaf8e9153b80982a8be Mon Sep 17 00:00:00 2001 From: teetangh Date: Fri, 13 Dec 2024 02:36:58 +0530 Subject: [PATCH] fixed the explore experts page with search and filter working --- .../experts/components/ConsultantCard.tsx | 8 +- .../experts/components/FeaturedExperts.tsx | 4 +- .../experts/components/FiltersSection.tsx | 59 +++--------- app/explore/experts/components/SearchBar.tsx | 33 ++++++- .../experts/components/Testimonials.tsx | 3 +- app/explore/experts/page.tsx | 94 +++++++++++-------- 6 files changed, 108 insertions(+), 93 deletions(-) diff --git a/app/explore/experts/components/ConsultantCard.tsx b/app/explore/experts/components/ConsultantCard.tsx index 2cef303..f45c22e 100644 --- a/app/explore/experts/components/ConsultantCard.tsx +++ b/app/explore/experts/components/ConsultantCard.tsx @@ -63,7 +63,9 @@ export function ConsultantCard({ consultant, metadata }: ConsultantCardProps) { )}
-

{consultant.description}

+

+ {consultant.description} +

Experience: {consultant.experience} @@ -108,8 +110,8 @@ export function ConsultantCard({ consultant, metadata }: ConsultantCardProps) {
- {consultant.rating.toFixed(1)} ({consultant.reviews?.length || 0}{" "} - reviews) + {consultant.rating.toFixed(1)} ( + {consultant.reviews?.length || 0} reviews)
diff --git a/app/explore/experts/components/FeaturedExperts.tsx b/app/explore/experts/components/FeaturedExperts.tsx index 505d9ff..9510544 100644 --- a/app/explore/experts/components/FeaturedExperts.tsx +++ b/app/explore/experts/components/FeaturedExperts.tsx @@ -16,8 +16,8 @@ export function FeaturedExperts() { Top Consultants

- Discover the best of the best. Our top consultants are ready to help - you with your business needs. + Discover the best of the best. Our top consultants are ready to + help you with your business needs.

diff --git a/app/explore/experts/components/FiltersSection.tsx b/app/explore/experts/components/FiltersSection.tsx index 720e951..0cf10ed 100644 --- a/app/explore/experts/components/FiltersSection.tsx +++ b/app/explore/experts/components/FiltersSection.tsx @@ -1,6 +1,5 @@ "use client"; -import { Input } from "@/components/ui/input"; import { Select, SelectContent, @@ -9,7 +8,7 @@ import { SelectValue, } from "@/components/ui/select"; import { Domain, SubDomain, Tag } from "@prisma/client"; -import { useState, useEffect } from "react"; +import { useState } from "react"; interface FiltersSectionProps { metadata: { @@ -25,8 +24,6 @@ interface FiltersSectionProps { setSelectedTags: (tags: string[]) => void; experienceYears: number; setExperienceYears: (years: number) => void; - pricing: number; - setPricing: (price: number) => void; } function XIcon(props: React.SVGProps) { @@ -59,18 +56,10 @@ export function FiltersSection({ setSelectedTags, experienceYears, setExperienceYears, - pricing, - setPricing, }: FiltersSectionProps) { const [searchTerm, setSearchTerm] = useState(""); const [isDropdownOpen, setIsDropdownOpen] = useState(false); - // Reset subdomain and tags when domain changes - useEffect(() => { - setSelectedSubdomain(null); - setSelectedTags([]); - }, [selectedDomain, setSelectedSubdomain, setSelectedTags]); - const handleDomainChange = (value: string) => { setSelectedDomain(value); setSelectedSubdomain(null); @@ -96,15 +85,16 @@ export function FiltersSection({ }; // Filter tags based on selected domain and search term - const filteredTags = metadata?.tags.filter((tag) => { - if (selectedDomain && tag.domainId !== selectedDomain) return false; - if (!searchTerm) return true; - if (selectedTags.includes(tag.name)) return false; - return tag.name.toLowerCase().includes(searchTerm.toLowerCase()); - }) || []; + const filteredTags = + metadata?.tags.filter((tag) => { + if (selectedDomain && tag.domainId !== selectedDomain) return false; + if (!searchTerm) return true; + if (selectedTags.includes(tag.name)) return false; + return tag.name.toLowerCase().includes(searchTerm.toLowerCase()); + }) || []; return ( -
+
-
-
- - setPricing(Number(e.target.value))} - className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" - /> -
- $0 - $500 - $1000+ -
-
- ${pricing === 1000 ? "1000+" : pricing} -
-
-
); } diff --git a/app/explore/experts/components/SearchBar.tsx b/app/explore/experts/components/SearchBar.tsx index fc90405..688d35a 100644 --- a/app/explore/experts/components/SearchBar.tsx +++ b/app/explore/experts/components/SearchBar.tsx @@ -1,20 +1,47 @@ "use client"; import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +export type SortOption = "nameAsc" | "nameDesc" | "reviewCount" | "rating"; interface SearchBarProps { onSearch: (value: string) => void; + onSort: (option: SortOption) => void; + sortBy: SortOption; } -export function SearchBar({ onSearch }: SearchBarProps) { +export function SearchBar({ onSearch, onSort, sortBy }: SearchBarProps) { return ( -
+
onSearch(e.target.value)} /> +
+ +
); } diff --git a/app/explore/experts/components/Testimonials.tsx b/app/explore/experts/components/Testimonials.tsx index d1624b7..41c2bd9 100644 --- a/app/explore/experts/components/Testimonials.tsx +++ b/app/explore/experts/components/Testimonials.tsx @@ -13,7 +13,8 @@ export function Testimonials() {

- Hear from our valued customers about their experience with our experts. + Hear from our valued customers about their experience with our + experts.

diff --git a/app/explore/experts/page.tsx b/app/explore/experts/page.tsx index b590d94..f9bf0ff 100644 --- a/app/explore/experts/page.tsx +++ b/app/explore/experts/page.tsx @@ -7,7 +7,7 @@ import { FiltersSection } from "./components/FiltersSection"; import { ConsultantCard } from "./components/ConsultantCard"; import { FeaturedExperts } from "./components/FeaturedExperts"; import { Testimonials } from "./components/Testimonials"; -import { SearchBar } from "./components/SearchBar"; +import { SearchBar, SortOption } from "./components/SearchBar"; interface MetaData { domains: Domain[]; @@ -31,9 +31,11 @@ function FindExperts() { const [selectedTags, setSelectedTags] = useState([]); const [searchTerm, setSearchTerm] = useState(""); const [experienceYears, setExperienceYears] = useState(0); - const [pricing, setPricing] = useState(0); const [selectedDomain, setSelectedDomain] = useState(null); - const [selectedSubdomain, setSelectedSubdomain] = useState(null); + const [selectedSubdomain, setSelectedSubdomain] = useState( + null, + ); + const [sortBy, setSortBy] = useState("nameAsc"); useEffect(() => { async function fetchData() { @@ -67,20 +69,29 @@ function FindExperts() { if (consultant.user.email?.toLowerCase().includes(searchLower)) return true; // Search in consultant details - if (consultant.description?.toLowerCase().includes(searchLower)) return true; - if (consultant.specialization?.toLowerCase().includes(searchLower)) return true; - if (consultant.qualifications?.toLowerCase().includes(searchLower)) return true; + if (consultant.description?.toLowerCase().includes(searchLower)) + return true; + if (consultant.specialization?.toLowerCase().includes(searchLower)) + return true; + if (consultant.qualifications?.toLowerCase().includes(searchLower)) + return true; // Search in domain and subdomain names if (consultant.domain.name.toLowerCase().includes(searchLower)) return true; - if (consultant.subDomains.some(sd => - sd.name.toLowerCase().includes(searchLower) - )) return true; + if ( + consultant.subDomains.some((sd) => + sd.name.toLowerCase().includes(searchLower), + ) + ) + return true; // Search in tags - if (consultant.tags.some(tag => - tag.name.toLowerCase().includes(searchLower) - )) return true; + if ( + consultant.tags.some((tag) => + tag.name.toLowerCase().includes(searchLower), + ) + ) + return true; return false; }; @@ -98,7 +109,7 @@ function FindExperts() { const filterByTags = (consultant: TConsultantProfile) => { if (selectedTags.length === 0) return true; return selectedTags.every((tagName) => - consultant.tags.some((t) => t.name === tagName) + consultant.tags.some((t) => t.name === tagName), ); }; @@ -114,25 +125,35 @@ function FindExperts() { return years >= experienceYears; }; - const filterByPrice = (consultant: TConsultantProfile) => { - if (pricing === 0) return true; - // Check if any subscription plan's price is less than or equal to the filter price - return consultant.subscriptionPlans.some( - (plan) => plan.price / 100 <= pricing - ); + // Sort function + const sortConsultants = (consultants: TConsultantProfile[]) => { + return [...consultants].sort((a, b) => { + switch (sortBy) { + case "nameAsc": + return (a.user.name || "").localeCompare(b.user.name || ""); + case "nameDesc": + return (b.user.name || "").localeCompare(a.user.name || ""); + case "reviewCount": + return (b.reviews?.length || 0) - (a.reviews?.length || 0); + case "rating": + return (b.rating || 0) - (a.rating || 0); + default: + return 0; + } + }); }; - // Apply all filters using useMemo to optimize performance - const filteredConsultants = useMemo(() => { - return consultants.filter( + // Apply all filters and sorting using useMemo + const filteredAndSortedConsultants = useMemo(() => { + const filtered = consultants.filter( (consultant) => filterBySearch(consultant) && filterByDomain(consultant) && filterBySubdomain(consultant) && filterByTags(consultant) && - filterByExperience(consultant) && - filterByPrice(consultant) + filterByExperience(consultant), ); + return sortConsultants(filtered); }, [ consultants, searchTerm, @@ -140,22 +161,22 @@ function FindExperts() { selectedSubdomain, selectedTags, experienceYears, - pricing, + sortBy, ]); // Group consultants by domain const groupedConsultants = useMemo(() => { const grouped = new Map(); - - filteredConsultants.forEach((consultant) => { + + filteredAndSortedConsultants.forEach((consultant) => { if (!grouped.has(consultant.domain.id)) { grouped.set(consultant.domain.id, []); } grouped.get(consultant.domain.id)?.push(consultant); }); - + return grouped; - }, [filteredConsultants]); + }, [filteredAndSortedConsultants]); if (isLoading) { return ( @@ -172,8 +193,8 @@ function FindExperts() { Find an Expert

- Search for experts in various fields. Enter keywords to find experts in - specific areas. + Search for experts in various fields. Enter keywords to find experts + in specific areas.

@@ -187,11 +208,9 @@ function FindExperts() { setSelectedTags={setSelectedTags} experienceYears={experienceYears} setExperienceYears={setExperienceYears} - pricing={pricing} - setPricing={setPricing} /> - +
{metadata?.domains.map((domain) => { @@ -212,11 +231,12 @@ function FindExperts() {
); })} - - {filteredConsultants.length === 0 && ( + + {filteredAndSortedConsultants.length === 0 && (

- No consultants found matching your criteria. Try adjusting your filters. + No consultants found matching your criteria. Try adjusting your + filters.

)}