update ui design for all pages

This commit is contained in:
2026-08-12 18:56:56 +05:30
parent 25c4ee4a6a
commit 3beb66059b
58 changed files with 7892 additions and 1891 deletions

View File

@@ -41,6 +41,7 @@ export function buildFacts({
activity = [],
courses = [],
profile = null,
user = null,
today = new Date(),
}) {
const scored = applications.filter((a) => a.ai_score > 0);
@@ -207,6 +208,37 @@ export function buildFacts({
level,
count: forgeCourses.filter((c) => c.difficulty === level).length,
})).filter((d) => d.count),
/* ── The same library, read by the administrator who owns it ──────────
Everything above answers "what can I prove"; everything below answers
"what have we built, and how is the workforce doing with it". Both are
derived from the same records, so the panel cannot disagree with the page
whichever question is asked. Publication state is read with the same
mapping the Forge page uses: `active` is Published. */
library: courses,
published: courses.filter((c) => c.status === 'active' || c.status === 'published'),
drafts: courses.filter((c) => c.status === 'draft'),
archived: courses.filter((c) => c.status === 'archived' || c.status === 'inactive'),
withChallenge: courses.filter((c) => c.challenge?.type),
withTraining: courses.filter((c) => c.training_outline?.length || c.quiz?.length),
byCategory: [...courses.reduce((map, c) => {
const key = c.category || 'Uncategorised';
map.set(key, (map.get(key) || 0) + 1);
return map;
}, new Map())]
.map(([category, count]) => ({ category, count }))
.sort((a, b) => b.count - a.count),
/* Verifications the workforce actually holds, counted off worker profiles
rather than off the library — a badge is something a person has. */
workforceVerified: profiles.reduce((sum, p) => {
const ids = new Set(courses.map((c) => c.id));
return sum + (p.earned_badges || []).filter((b) => ids.has(b.course_id)).length;
}, 0),
usage: courses.map((c) => ({
course: c,
completed: profiles.filter((p) => (p.completed_courses || []).some((x) => x.course_id === c.id)).length,
verified: profiles.filter((p) => (p.earned_badges || []).some((b) => b.course_id === c.id)).length,
})),
};
/* ── Talent pool ─────────────────────────────────────────────────────────
@@ -281,6 +313,10 @@ export function buildFacts({
return {
today,
/* The signed-in account — identity and preferences, for the pages that are
about the operator rather than the workforce. */
user,
/* Applications */
applications,
total: applications.length,