diff --git a/app/courses/[courseId]/progress/page.tsx b/app/courses/[courseId]/progress/page.tsx index 41e31b7e..89dda90e 100644 --- a/app/courses/[courseId]/progress/page.tsx +++ b/app/courses/[courseId]/progress/page.tsx @@ -62,11 +62,12 @@ export default function LearningProgress() { skills { skillName skillCategory - skillValue + skillValue { + skillValue + } skillAllUsersStats { skillValueSum participantCount - averageSkillValue } } } @@ -94,6 +95,76 @@ export default function LearningProgress() { const [showAverageProgress, setAverageProgress] = useState(false); + type skillItem = { + skillValue: number; + skillAverageValue: number; + maxParticipantCount: number; + }; + + const getCategorySkillKey = (category: string, skillName: string) => { + return `${category}_${skillName}`; + }; + + const progressBySkill = useMemo(() => { + const progressBySkillValues = new Map< + string, + { + progressSum: number; + averageProgressSum: number; + count: number; + maxParticipantCount: number; + } + >(); + + uniqueCategories.forEach((category) => { + skillsByCategory[category].forEach((skill) => { + const key = getCategorySkillKey(category, skill.skillName); + + if (!progressBySkillValues.has(key)) { + progressBySkillValues.set(key, { + progressSum: 0, + averageProgressSum: 0, + count: 0, + maxParticipantCount: 0, + }); + } + + const progressItem = progressBySkillValues.get(key)!; + + progressItem.progressSum += skill.skillValue.skillValue; + progressItem.averageProgressSum += + skill.skillAllUsersStats.skillValueSum; + progressItem.count++; + progressItem.maxParticipantCount = Math.max( + progressItem.maxParticipantCount, + skill.skillAllUsersStats.participantCount + ); + }); + }); + + const result = new Map(); + progressBySkillValues.forEach( + ( + { + progressSum: sum, + averageProgressSum: averageSum, + count, + maxParticipantCount, + }, + key + ) => { + result.set(key, { + skillValue: sum / count, + skillAverageValue: + averageSum / count / course.numberOfCourseMemberships, + maxParticipantCount, + }); + } + ); + + return result; + }, [course.numberOfCourseMemberships, skillsByCategory, uniqueCategories]); + const sortedCategories = useMemo(() => { if (uniqueCategories.length === 0) return []; return [...uniqueCategories].sort((a, b) => { @@ -104,14 +175,16 @@ export default function LearningProgress() { ).values() ); const progressSum = uniqueSkillsInCategory.reduce((sum, skill) => { - const progress = skill.skillValue; + const progress = + progressBySkill.get(getCategorySkillKey(category, skill.skillName)) + ?.skillValue ?? 0; return sum + progress; }, 0); return (progressSum / uniqueSkillsInCategory.length) * 100; }; return getTotalProgress(b) - getTotalProgress(a); }); - }, [skillsByCategory, uniqueCategories]); + }, [progressBySkill, skillsByCategory, uniqueCategories]); const currentUniqueSkills = useMemo(() => { if (sortedCategories.length === 0) return []; @@ -123,9 +196,23 @@ export default function LearningProgress() { return acc; }, [] as (typeof skillsByCategory)[string]) .sort((skillA, skillB) => { - return skillB.skillValue - skillA.skillValue; + const progressA = + progressBySkill.get( + getCategorySkillKey( + sortedCategories[selectedCategory], + skillA.skillName + ) + )?.skillValue ?? 0; + const progressB = + progressBySkill.get( + getCategorySkillKey( + sortedCategories[selectedCategory], + skillB.skillName + ) + )?.skillValue ?? 0; + return progressB - progressA; }); - }, [selectedCategory, skillsByCategory, sortedCategories]); + }, [progressBySkill, selectedCategory, skillsByCategory, sortedCategories]); const urgentChapters = useMemo(() => { return course.chapters.elements.filter((chapter) => { @@ -172,11 +259,12 @@ export default function LearningProgress() { const tempMap = new Map(); course.skills.forEach((skill) => { - tempMap.set(skill.skillName, skill.skillValue * 100); + const key = getCategorySkillKey(skill.skillCategory, skill.skillName); + tempMap.set(key, (progressBySkill.get(key)?.skillValue ?? 0) * 100); }); sessionStorage.setItem("previousProgress", JSON.stringify([...tempMap])); - }, [course.skills, uniqueCategories.length]); + }, [course.skills, progressBySkill, uniqueCategories.length]); const theme = useTheme(); @@ -257,14 +345,19 @@ export default function LearningProgress() { ); const progressSum = uniqueSkillsInCategory.reduce((sum, skill) => { - const progress = skill.skillValue * 100; + const progress = + (progressBySkill.get( + getCategorySkillKey(category, skill.skillName) + )?.skillValue ?? 0) * 100; return sum + progress; }, 0); const averageProgressSum = uniqueSkillsInCategory.reduce( (sum, skill) => { const averageProgress = - skill.skillAllUsersStats.averageSkillValue * 100; + (progressBySkill.get( + getCategorySkillKey(category, skill.skillName) + )?.skillAverageValue ?? 0) * 100; return sum + averageProgress; }, 0 @@ -272,18 +365,25 @@ export default function LearningProgress() { const maxParticipantCountForaSkill = Math.max( ...uniqueSkillsInCategory.map( - (skill) => skill.skillAllUsersStats.participantCount + (skill) => + progressBySkill.get( + getCategorySkillKey(category, skill.skillName) + )?.maxParticipantCount ?? 0 ) ); const categoryProgressValue = progressSum / uniqueSkillsInCategory.length; + const categoryAverageProgressValue = averageProgressSum / uniqueSkillsInCategory.length; const tempSumPreviousProgress = uniqueSkillsInCategory.reduce( (sum, skill) => - sum + (previousProgress.get(skill.skillName) ?? 0), + sum + + (previousProgress.get( + getCategorySkillKey(category, skill.skillName) + ) ?? 0), 0 ); @@ -381,13 +481,22 @@ export default function LearningProgress() { ) ); - const skillProgressValue = currentSkill.skillValue * 100; + const key = getCategorySkillKey( + currentSkill.skillCategory, + currentSkill.skillName + ); + + const skillProgressValue = + (progressBySkill.get(key)?.skillValue ?? 0) * 100; + const skillAverageProgressValue = - currentSkill.skillAllUsersStats.averageSkillValue * 100; + (progressBySkill.get(key)?.skillAverageValue ?? 0) * 100; + + const maxParticipantCount = + progressBySkill.get(key)?.maxParticipantCount ?? 0; const previousSkillProgressValue = - previousProgress.get(currentSkill.skillName) ?? - skillProgressValue; + previousProgress.get(key) ?? skillProgressValue; return (