Files
nextcraft/apps/web/components/learner/progress-graph.tsx
T
CIAgent dc00a4f8f5 chore(P05): type & dependency hardening — mypy + recharts 3 (REQ-7-005)
Wave 5-1 mypy adoption (D-058 relaxed-first): mypy 2.3.1, [tool.mypy]
check_untyped_defs + no_implicit_optional + warn_unused_ignores +
warn_redundant_casts + warn_unreachable, no overrides (every dep ships
py.typed), files = ai_service + scripts/sandbox-agent.py + tests (not
excluded). 215 errors → 0: ~140 fixed at source incl. genuine bugs found
by the gate (LLMProvider protocol async-generator shape, SessionStore
protocol sync/async mismatch, structured_reply genericity, get_args
migrations, sandbox-agent Optional guard honesty, proctor test arg-order,
dead ExecResult kwarg, 16 sqlmodel col() sites); 34 live suppressions
scoped-coded + reasoned. Original 27 type:ignore dispositioned: 12 dead
removed, 15 scoped (warn_unused_ignores self-eliminates the rest).
Wired: scripts/typecheck.sh + package.json + turbo task + root
ai:typecheck — pnpm typecheck now 5 tsc + mypy.

Wave 5-2 recharts 2.15.4 → 3.10.1 (D-049/D-059): one breaking class
(Tooltip formatter ValueType typing); 2 one-line inference fixes on the
2 chart files; no rollback needed (well inside the G-106 timebox).
Deprecated direct dep resolved; uuid@9 gone from the tree. Build 248/248
with chart SSR markers verified in exported employer + dashboard pages.

Wave 5-3 deprecated-transitive audit (G-109): 4 lockfile entries remain,
all dev-only, none actionable within NFR budget — glob@7.2.3 + inflight +
rimraf@3 via Storybook docgen chain (flat-cache@3); glob@10.5.0 via
c8→test-exclude (D-052-binding coverage tool — swapping it is out of
budget). Python: no EOL packages; zero-warning regime under
filterwarnings=error is the machine-checked proof.

Counts: 670 py / 44 web / 64 cli, zero warnings, G-104 allowlist still
exactly 2.

---ci---
phase: 5
milestone: v0.7
status: execute
---/ci---
2026-09-27 10:08:07 +00:00

71 lines
1.9 KiB
TypeScript

'use client';
import {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from 'recharts';
import { colors } from '@nextcraft/ui';
const DATA = [
{ week: 'Week 1', mastery: 18 },
{ week: 'Week 2', mastery: 26 },
{ week: 'Week 3', mastery: 31 },
{ week: 'Week 4', mastery: 42 },
{ week: 'Week 5', mastery: 48 },
{ week: 'Week 6', mastery: 56 },
{ week: 'Week 7', mastery: 60 },
{ week: 'Week 8', mastery: 62 },
];
const tooltipStyle = {
borderRadius: 8,
border: `1px solid ${colors.neutral[200]}`,
fontSize: 12,
} as const;
const axisTick = { fontSize: 12, fill: colors.neutral[500] } as const;
export function ProgressGraph() {
return (
<div className="h-64 w-full">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={DATA} margin={{ top: 10, right: 16, left: -8, bottom: 0 }}>
<defs>
<linearGradient id="masteryFill" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={colors.primary[500]} stopOpacity={0.35} />
<stop offset="100%" stopColor={colors.primary[500]} stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke={colors.neutral[200]} />
<XAxis
dataKey="week"
tick={axisTick}
stroke={colors.neutral[300]}
/>
<YAxis
domain={[0, 100]}
tick={axisTick}
stroke={colors.neutral[300]}
tickFormatter={(v) => `${v}%`}
/>
<Tooltip
contentStyle={tooltipStyle}
formatter={(value) => [`${value}%`, 'Mastery']}
/>
<Area
type="monotone"
dataKey="mastery"
stroke={colors.primary[600]}
strokeWidth={2}
fill="url(#masteryFill)"
/>
</AreaChart>
</ResponsiveContainer>
</div>
);
}