diff --git a/src/components/Projects/ProjectCard.tsx b/src/components/Projects/ProjectCard.tsx index efa0ac210..07337e392 100644 --- a/src/components/Projects/ProjectCard.tsx +++ b/src/components/Projects/ProjectCard.tsx @@ -5,10 +5,12 @@ import type { } from '../../lib/project.ts'; import { Users } from 'lucide-react'; import { formatCommaNumber } from '../../lib/number.ts'; +import { cn } from '../../lib/classname.ts'; type ProjectCardProps = { project: ProjectFileType; userCount?: number; + status?: 'completed' | 'started' | 'none'; }; const badgeVariants: Record = { @@ -18,7 +20,7 @@ const badgeVariants: Record = { }; export function ProjectCard(props: ProjectCardProps) { - const { project, userCount = 0 } = props; + const { project, userCount = 0, status } = props; const { frontmatter, id } = project; @@ -45,6 +47,21 @@ export function ProjectCard(props: ProjectCardProps) { ) : ( <>Be the first to solve! )} + + {status !== 'none' && ( + <> + · + + {status} + + + )} ); diff --git a/src/components/Projects/ProjectsList.tsx b/src/components/Projects/ProjectsList.tsx index aa2bb8c3e..e7158f40f 100644 --- a/src/components/Projects/ProjectsList.tsx +++ b/src/components/Projects/ProjectsList.tsx @@ -1,7 +1,7 @@ import { ProjectCard } from './ProjectCard.tsx'; import { HeartHandshake, Trash2 } from 'lucide-react'; import { cn } from '../../lib/classname.ts'; -import { useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { projectDifficulties, type ProjectDifficultyType, @@ -12,6 +12,8 @@ import { getUrlParams, setUrlParams, } from '../../lib/browser.ts'; +import { httpPost } from '../../lib/http.ts'; +import { isLoggedIn } from '../../lib/jwt.ts'; type DifficultyButtonProps = { difficulty: ProjectDifficultyType; @@ -38,6 +40,11 @@ function DifficultyButton(props: DifficultyButtonProps) { ); } +export type ListProjectStatusesResponse = Record< + string, + 'completed' | 'started' +>; + type ProjectsListProps = { projects: ProjectFileType[]; userCounts: Record; @@ -50,6 +57,25 @@ export function ProjectsList(props: ProjectsListProps) { const [difficulty, setDifficulty] = useState< ProjectDifficultyType | undefined >(urlDifficulty); + const [projectStatuses, setProjectStatuses] = + useState({}); + + const loadProjectStatuses = async () => { + const projectIds = projects.map((project) => project.id); + const { response, error } = await httpPost( + `${import.meta.env.PUBLIC_API_URL}/v1-list-project-statuses`, + { + projectIds, + }, + ); + + if (error || !response) { + console.error(error); + return; + } + + setProjectStatuses(response); + }; const projectsByDifficulty: Map = useMemo(() => { @@ -72,6 +98,14 @@ export function ProjectsList(props: ProjectsListProps) { ? projectsByDifficulty.get(difficulty) || [] : projects; + useEffect(() => { + if (!isLoggedIn()) { + return; + } + + loadProjectStatuses().finally(); + }, []); + return (
@@ -130,7 +164,13 @@ export function ProjectsList(props: ProjectsListProps) { }) .map((matchingProject) => { const count = userCounts[matchingProject?.id] || 0; - return ; + return ( + + ); })}