import { ProjectCard } from './ProjectCard.tsx'; import { Trash2 } from 'lucide-react'; import { cn } from '../../lib/classname.ts'; import { useEffect, useMemo, useState } from 'react'; import { deleteUrlParam, getUrlParams, setUrlParams, } from '../../lib/browser.ts'; import { httpPost } from '../../lib/http.ts'; import { isLoggedIn } from '../../lib/jwt.ts'; import { allowedOfficialProjectDifficulty, type AllowedOfficialProjectDifficulty, type OfficialProjectDocument, } from '../../queries/official-project.ts'; type DifficultyButtonProps = { difficulty: AllowedOfficialProjectDifficulty; isActive?: boolean; onClick?: () => void; }; function DifficultyButton(props: DifficultyButtonProps) { const { difficulty, onClick, isActive } = props; return ( ); } export type ListProjectStatusesResponse = Record< string, 'completed' | 'started' >; type ProjectsListProps = { projects: OfficialProjectDocument[]; userCounts: Record; }; export function ProjectsList(props: ProjectsListProps) { const { projects, userCounts } = props; const { difficulty: urlDifficulty } = getUrlParams(); const [difficulty, setDifficulty] = useState< AllowedOfficialProjectDifficulty | undefined >(urlDifficulty); const [projectStatuses, setProjectStatuses] = useState(); const loadProjectStatuses = async () => { if (!isLoggedIn()) { setProjectStatuses({}); return; } const projectIds = projects.map((project) => project.slug); 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< AllowedOfficialProjectDifficulty, OfficialProjectDocument[] > = useMemo(() => { const result = new Map< AllowedOfficialProjectDifficulty, OfficialProjectDocument[] >(); for (const project of projects) { const difficulty = project.difficulty; if (!result.has(difficulty)) { result.set(difficulty, []); } result.get(difficulty)?.push(project); } return result; }, [projects]); const matchingProjects = difficulty ? projectsByDifficulty.get(difficulty) || [] : projects; useEffect(() => { loadProjectStatuses().finally(); }, []); return (
{allowedOfficialProjectDifficulty.map((projectDifficulty) => ( { setDifficulty(projectDifficulty); setUrlParams({ difficulty: projectDifficulty }); }} difficulty={projectDifficulty} isActive={projectDifficulty === difficulty} /> ))} {difficulty && ( )}
{matchingProjects.length === 0 && (

No matching projects found.

)} {matchingProjects .sort((project) => { return project.difficulty === 'beginner' ? -1 : project.difficulty === 'intermediate' ? 0 : 1; }) .sort((a, b) => { return a.order - b.order; }) .map((matchingProject) => { const count = userCounts[matchingProject?.slug] || 0; return ( ); })}
); }