import { useStore } from '@nanostores/react'; import { useEffect, useState } from 'react'; import { useAuth } from '../../hooks/use-auth'; import { useToast } from '../../hooks/use-toast'; import { getUrlParams, setUrlParams } from '../../lib/browser'; import { httpGet } from '../../lib/http'; import { pageProgressMessage } from '../../stores/page'; import { $currentTeam } from '../../stores/team'; import { GroupRoadmapItem } from './GroupRoadmapItem'; import { MemberCustomProgressModal } from './MemberCustomProgressModal'; import { MemberProgressItem } from './MemberProgressItem'; import { MemberProgressModal } from './MemberProgressModal'; export type UserProgress = { resourceTitle: string; resourceType: 'roadmap' | 'best-practice'; resourceId: string; isFavorite: boolean; done: number; learning: number; skipped: number; total: number; updatedAt: string; isCustomResource?: boolean; roadmapSlug?: string; aiRoadmapId?: string; }; export type TeamMember = { _id: string; role: string; name: string; email: string; avatar: string; progress: UserProgress[]; updatedAt: string; }; export type GroupByRoadmap = { resourceId: string; resourceTitle: string; resourceType: string; isCustomResource?: boolean; roadmapSlug?: string; members: { member: TeamMember; progress: UserProgress | undefined; }[]; }; const groupingTypes = [ { label: 'Members', value: 'member' }, { label: 'Roadmaps', value: 'roadmap' }, ] as const; export function TeamProgressPage() { const { t: teamId, gb: groupBy } = getUrlParams(); const [isLoading, setIsLoading] = useState(true); const toast = useToast(); const currentTeam = useStore($currentTeam); const user = useAuth(); const [showMemberProgress, setShowMemberProgress] = useState<{ resourceId: string; member: TeamMember; isCustomResource?: boolean; }>(); const [teamMembers, setTeamMembers] = useState([]); const [selectedGrouping, setSelectedGrouping] = useState< 'roadmap' | 'member' >(groupBy || 'member'); async function getTeamProgress() { const { response, error } = await httpGet( `${import.meta.env.PUBLIC_API_URL}/v1-get-team-progress/${teamId}`, ); if (error || !response) { toast.error(error?.message || 'Failed to get team progress'); return; } setTeamMembers( response.sort((a, b) => { if (a.email === user?.email) { return -1; } if (b.email === user?.email) { return 1; } return 0; }), ); } useEffect(() => { if (!teamId) { return; } getTeamProgress().then(() => { pageProgressMessage.set(''); setIsLoading(false); }); }, [teamId]); useEffect(() => { if (!selectedGrouping) { return; } setUrlParams({ gb: selectedGrouping }); }, [selectedGrouping]); const groupByRoadmap: GroupByRoadmap[] = []; for (const roadmap of currentTeam?.roadmaps || []) { let isCustomResource = false; const members: GroupByRoadmap['members'] = []; for (const member of teamMembers) { const progress = member.progress.find( (progress) => progress.resourceId === roadmap, ); if (!progress) { continue; } if (progress.isCustomResource && !isCustomResource) { isCustomResource = true; } members.push({ member, progress, }); } if (!members.length) { continue; } groupByRoadmap.push({ resourceId: roadmap, resourceTitle: members?.[0].progress?.resourceTitle || '', resourceType: 'roadmap', roadmapSlug: members?.[0].progress?.roadmapSlug, members, isCustomResource, }); } if (!teamId) { window.location.href = '/'; return; } if (isLoading) { return null; } const ProgressModal = showMemberProgress && !showMemberProgress.isCustomResource ? MemberProgressModal : MemberCustomProgressModal; return (
{showMemberProgress && ( { setShowMemberProgress(undefined); }} onShowMyProgress={() => { setShowMemberProgress({ resourceId: showMemberProgress.resourceId, member: teamMembers.find( (member) => member.email === user?.email, )!, isCustomResource: showMemberProgress.isCustomResource, }); }} /> )}
{groupingTypes.map((grouping) => ( ))}
{selectedGrouping === 'roadmap' && (
{groupByRoadmap.map((roadmap) => { return ( { setShowMemberProgress({ resourceId, member, isCustomResource: roadmap.isCustomResource, }); }} /> ); })}
)} {selectedGrouping === 'member' && (
{teamMembers.map((member) => { const canViewMemberProgress = currentTeam?.role !== 'member' || !currentTeam?.personalProgressOnly || member.email === user?.email; if (!canViewMemberProgress) { return null; } return ( { setShowMemberProgress({ resourceId, member, isCustomResource, }); }} /> ); })}
)}
); }