'use client'; import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared'; import { BadgeDisplay, XpBar, } from '@contractspec/example.learning-journey-ui-shared'; import { Card, CardContent, CardHeader, CardTitle, } from '@contractspec/lib.ui-kit-web/ui/card'; import { MasteryRing } from '../components/MasteryRing'; export function Progress({ track, progress }: LearningViewProps) { const totalXp = track.totalXp ?? track.steps.reduce((sum, s) => sum + (s.xpReward ?? 0), 0) + (track.completionRewards?.xp ?? 0); const completedSteps = progress.completedStepIds.length; const totalSteps = track.steps.length; const percentComplete = totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0; // Group steps by metadata surface for mastery rings const surfaces = new Map(); track.steps.forEach((step) => { const surface = (step.metadata?.surface as string) ?? 'general'; const current = surfaces.get(surface) ?? { total: 0, completed: 0 }; surfaces.set(surface, { total: current.total + 1, completed: current.completed + (progress.completedStepIds.includes(step.id) ? 1 : 0), }); }); const surfaceColors: ('green' | 'blue' | 'violet' | 'orange')[] = [ 'green', 'blue', 'violet', 'orange', ]; return (
{/* XP Progress */} Experience Points
{progress.xpEarned.toLocaleString()} / {totalXp.toLocaleString()} XP
{track.completionRewards?.xp && percentComplete < 100 && (

🎁 Complete all steps for a{' '} +{track.completionRewards.xp} XP {' '} bonus!

)}
{/* Mastery Rings */} 🎯 Skill Mastery
{Array.from(surfaces.entries()).map(([surface, data], index) => ( ))}
{/* Badges */} 🏅 Badges Earned {progress.badges.length === 0 && (

Complete the track to earn your first badge!

)}
{/* Step Breakdown */} 📊 Step Breakdown
{track.steps.map((step) => { const isCompleted = progress.completedStepIds.includes(step.id); return (
{isCompleted ? '✓' : '○'} {step.title}
{step.xpReward && ( {isCompleted ? '+' : ''} {step.xpReward} XP )}
); })}
); }