diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 1974969..82f8233 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -15,7 +15,8 @@ "Bash(git add:*)", "Bash(git commit:*)", "Bash(git push)", - "Bash(findstr:*)" + "Bash(findstr:*)", + "Bash(ls:*)" ], "deny": [], "ask": [] diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..156f765 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,9 @@ +{ + "mcpServers": { + "nx-mcp": { + "type": "stdio", + "command": "npx", + "args": ["nx", "mcp"] + } + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..91e8232 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,13 @@ + + + +# General Guidelines for working with Nx + +- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly +- You have access to the Nx MCP server and its tools, use them to help the user +- When answering questions about the repository, use the `nx_workspace` tool first to gain an understanding of the workspace architecture where applicable. +- When working in individual projects, use the `nx_project_details` mcp tool to analyze and understand the specific project structure and dependencies +- For questions around nx configuration, best practices or if you're unsure, use the `nx_docs` tool to get relevant, up-to-date docs. Always use this instead of assuming things about nx configuration +- If the user needs help with an Nx configuration or project graph error, use the `nx_workspace` tool to get any errors + + diff --git a/apps/hackathon/src/app/teams/browse/page.tsx b/apps/hackathon/src/app/teams/browse/page.tsx index 7c95e07..4df2c4d 100644 --- a/apps/hackathon/src/app/teams/browse/page.tsx +++ b/apps/hackathon/src/app/teams/browse/page.tsx @@ -31,6 +31,13 @@ const MEMBER_FILTER_OPTIONS = [ { label: '5 Members (Full)', value: '5', minMembers: 5, maxMembers: 5 }, ]; +// Submission status filter options +const SUBMISSION_FILTER_OPTIONS = [ + { label: 'All Teams', value: '' }, + { label: 'Submitted', value: 'true' }, + { label: 'Not Submitted', value: 'false' }, +]; + // Skeleton card component for loading state const TeamCardSkeleton: FC = () => (
@@ -72,11 +79,13 @@ const BrowseTeamsPage: FC = (): ReactElement => { const initialSearch = searchParams.get('search') || ''; const initialCity = searchParams.get('city') || ''; const initialMembers = searchParams.get('members') || ''; + const initialSubmission = searchParams.get('submission') || ''; const [searchTerm, setSearchTerm] = useState(initialSearch); const [debouncedSearch, setDebouncedSearch] = useState(initialSearch); const [selectedCity, setSelectedCity] = useState(initialCity); const [selectedMembers, setSelectedMembers] = useState(initialMembers); + const [selectedSubmission, setSelectedSubmission] = useState(initialSubmission); const [selectedTeamId, setSelectedTeamId] = useState(null); const [showJoinModal, setShowJoinModal] = useState(false); const [currentPage, setCurrentPage] = useState( @@ -94,6 +103,7 @@ const BrowseTeamsPage: FC = (): ReactElement => { search?: string; city?: string; members?: string; + submission?: string; }) => { const newParams = new URLSearchParams(searchParams); @@ -137,6 +147,14 @@ const BrowseTeamsPage: FC = (): ReactElement => { } } + if (params.submission !== undefined) { + if (params.submission === '') { + newParams.delete('submission'); + } else { + newParams.set('submission', params.submission); + } + } + setSearchParams(newParams, { replace: true }); }, [searchParams, setSearchParams] @@ -167,6 +185,9 @@ const BrowseTeamsPage: FC = (): ReactElement => { (opt) => opt.value === selectedMembers ); + // Convert submission filter value to boolean + const hasSubmissionFilter = selectedSubmission === 'true' ? true : selectedSubmission === 'false' ? false : undefined; + const { data: teamsData, isLoading, @@ -179,6 +200,7 @@ const BrowseTeamsPage: FC = (): ReactElement => { visibility: ETeamVisibility.PUBLIC, minMembers: memberFilter?.minMembers, maxMembers: memberFilter?.maxMembers, + hasSubmission: hasSubmissionFilter, }); const { data: myTeamsData } = useMyTeams(); @@ -278,7 +300,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 7eb462f..a727879 100644 --- a/libs/service/src/hooks/teams/index.ts +++ b/libs/service/src/hooks/teams/index.ts @@ -127,6 +127,7 @@ export const useTeams = (params?: { search?: string; minMembers?: number; maxMembers?: number; + hasSubmission?: boolean; }) => { return useQuery({ queryKey: teamKeys.list(params), @@ -139,6 +140,7 @@ export const useTeams = (params?: { 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)); + if (params?.hasSubmission !== undefined) queryParams.append('has_submission', String(params.hasSubmission)); const response = await hackathonApi.get>( `/teams/browse${queryParams.toString() ? `?${queryParams.toString()}` : ''}`