diff --git a/apps/hackathon/src/app/teams/browse/page.tsx b/apps/hackathon/src/app/teams/browse/page.tsx index 08382cc..d8ed113 100644 --- a/apps/hackathon/src/app/teams/browse/page.tsx +++ b/apps/hackathon/src/app/teams/browse/page.tsx @@ -17,6 +17,17 @@ import { Icon } from '@iconify/react'; const DEFAULT_PER_PAGE = 12; const PER_PAGE_OPTIONS = [6, 12, 24, 48]; +// Member filter options +const MEMBER_FILTER_OPTIONS = [ + { label: 'All Teams', value: '', minMembers: undefined, maxMembers: undefined }, + { label: 'Looking for Members (1-4)', value: 'looking', minMembers: 1, maxMembers: 4 }, + { label: '1 Member', value: '1', minMembers: 1, maxMembers: 1 }, + { label: '2 Members', value: '2', minMembers: 2, maxMembers: 2 }, + { label: '3 Members', value: '3', minMembers: 3, maxMembers: 3 }, + { label: '4 Members', value: '4', minMembers: 4, maxMembers: 4 }, + { label: '5 Members (Full)', value: '5', minMembers: 5, maxMembers: 5 }, +]; + // Skeleton card component for loading state const TeamCardSkeleton: FC = () => (
@@ -54,10 +65,12 @@ const BrowseTeamsPage: FC = (): ReactElement => { ); const initialSearch = searchParams.get('search') || ''; const initialCity = searchParams.get('city') || ''; + const initialMembers = searchParams.get('members') || ''; const [searchTerm, setSearchTerm] = useState(initialSearch); const [debouncedSearch, setDebouncedSearch] = useState(initialSearch); const [selectedCity, setSelectedCity] = useState(initialCity); + const [selectedMembers, setSelectedMembers] = useState(initialMembers); const [selectedTeamId, setSelectedTeamId] = useState(null); const [showJoinModal, setShowJoinModal] = useState(false); const [currentPage, setCurrentPage] = useState( @@ -74,6 +87,7 @@ const BrowseTeamsPage: FC = (): ReactElement => { per_page?: number; search?: string; city?: string; + members?: string; }) => { const newParams = new URLSearchParams(searchParams); @@ -109,6 +123,14 @@ const BrowseTeamsPage: FC = (): ReactElement => { } } + if (params.members !== undefined) { + if (params.members === '') { + newParams.delete('members'); + } else { + newParams.set('members', params.members); + } + } + setSearchParams(newParams, { replace: true }); }, [searchParams, setSearchParams] @@ -134,6 +156,11 @@ const BrowseTeamsPage: FC = (): ReactElement => { } }, [selectedCity]); + // Get member filter values + const memberFilter = MEMBER_FILTER_OPTIONS.find( + (opt) => opt.value === selectedMembers + ); + const { data: teamsData, isLoading, @@ -144,6 +171,8 @@ const BrowseTeamsPage: FC = (): ReactElement => { search: debouncedSearch, city: selectedCity || undefined, visibility: ETeamVisibility.PUBLIC, + minMembers: memberFilter?.minMembers, + maxMembers: memberFilter?.maxMembers, }); const { data: myTeamsData } = useMyTeams(); @@ -243,7 +272,7 @@ const BrowseTeamsPage: FC = (): ReactElement => { {/* Filters */}
-
+
+
+ + +
diff --git a/libs/service/src/hooks/teams/index.ts b/libs/service/src/hooks/teams/index.ts index e9b2257..b0cf0f3 100644 --- a/libs/service/src/hooks/teams/index.ts +++ b/libs/service/src/hooks/teams/index.ts @@ -125,6 +125,8 @@ export const useTeams = (params?: { city?: string; visibility?: string; search?: string; + minMembers?: number; + maxMembers?: number; }) => { return useQuery({ queryKey: teamKeys.list(params), @@ -135,6 +137,8 @@ export const useTeams = (params?: { if (params?.search) queryParams.append('search', params.search); if (params?.city) queryParams.append('city', params.city); if (params?.visibility) queryParams.append('visibility', params.visibility); + if (params?.minMembers) queryParams.append('min_members', String(params.minMembers)); + if (params?.maxMembers) queryParams.append('max_members', String(params.maxMembers)); const response = await hackathonApi.get>( `/teams/browse${queryParams.toString() ? `?${queryParams.toString()}` : ''}`