diff --git a/src/app/components/ProjectCard.tsx b/src/app/components/ProjectCard.tsx index efae0f9..f89fbae 100644 --- a/src/app/components/ProjectCard.tsx +++ b/src/app/components/ProjectCard.tsx @@ -32,6 +32,7 @@ export function ProjectCard({ groupName={project.group?.name ?? 'ungrouped'} members={project.members} needsHelp={project.needsHelp} + hasVideo={project.hasVideo} voteCategories={voteCategories} /> ); @@ -62,6 +63,7 @@ export function ProjectListItem({ detail, members, needsHelp = false, + hasVideo = false, emptyMemberLabel = 'up for grabs', voteCategories = [], }: { @@ -74,6 +76,7 @@ export function ProjectListItem({ detail?: string; members: ProjectListMember[]; needsHelp?: boolean; + hasVideo?: boolean; emptyMemberLabel?: string; voteCategories?: string[]; }) { @@ -96,6 +99,7 @@ export function ProjectListItem({
{groupName} {detail && {detail}} + {needsHelp && looking for help}
@@ -124,11 +128,16 @@ function ProjectTags({project, className}: {project: ProjectSummary; className: {project.kind === 'idea' ? 'open idea' : (project.group?.name ?? 'ungrouped')} + {project.needsHelp && looking for help} ); } +function ProjectVideoTag({hasVideo}: {hasVideo: boolean}) { + return hasVideo ? has video : null; +} + export function MemberStack({ members, emptyLabel = 'up for grabs', diff --git a/src/app/queries/projects.ts b/src/app/queries/projects.ts index f7f3a3a..2033391 100644 --- a/src/app/queries/projects.ts +++ b/src/app/queries/projects.ts @@ -39,6 +39,7 @@ export function useProjects( kind?: 'project' | 'idea', group?: string, search?: string, + hasVideo?: boolean, cursor?: string, ) { const query = new URLSearchParams({ @@ -48,9 +49,10 @@ export function useProjects( if (kind) query.set('kind', kind); if (group) query.set('group', group); if (search) query.set('q', search); + if (hasVideo) query.set('hasVideo', 'true'); if (cursor) query.set('cursor', cursor); return useQuery({ - queryKey: ['projects', yearId, kind, group, search, cursor ?? null], + queryKey: ['projects', yearId, kind, group, search, hasVideo, cursor ?? null], queryFn: () => apiRequest(`/projects?${query}`), placeholderData: keepPreviousData, }); diff --git a/src/app/routes/ProjectsPage.tsx b/src/app/routes/ProjectsPage.tsx index b782ea4..87ab73c 100644 --- a/src/app/routes/ProjectsPage.tsx +++ b/src/app/routes/ProjectsPage.tsx @@ -38,6 +38,7 @@ export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { const [searchParams, setSearchParams] = useSearchParams(); const [kind, setKind] = useState<'project' | 'idea'>('project'); const group = searchParams.get('group') ?? ''; + const [hasVideoOnly, setHasVideoOnly] = useState(false); const [searchInput, setSearchInput] = useState(''); const [search, setSearch] = useState(''); const [cursor, setCursor] = useState(); @@ -52,6 +53,7 @@ export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { kind, kind === 'project' ? group || undefined : undefined, search || undefined, + kind === 'project' && hasVideoOnly ? true : undefined, cursor, ); const error = year.error ?? projects.error; @@ -215,6 +217,7 @@ export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { className={kind === 'idea' ? 'active' : ''} onClick={() => { setKind('idea'); + setHasVideoOnly(false); resetPagination(); }} > @@ -238,6 +241,19 @@ export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { )} + {kind === 'project' && ( + + )}
{(['grid', 'list'] as const).map((option) => (