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

@@ -1,4 +1,5 @@
import { plural, verb } from './insights';
import { PERMISSIONS } from '@/pages/admin/permissions';
/**
* Dynamic greetings and suggested prompts.
@@ -133,16 +134,20 @@ const GREETINGS = {
return `${plural(f.hired.length, 'hire')} from ${plural(f.total, 'applicant')} — ${f.hireRate}% conversion.`;
},
/* The line the panel opens with: whatever most needs the author's attention,
which on an authoring console is an unfinished skill before it is a total. */
'admin.forge': (f) => {
const g = f.forge;
if (!g.courses.length) return 'No challenges published yet, so nothing can be proven here.';
if (g.locked.length && !g.ready.length) {
return `${plural(g.locked.length, 'challenge')} ${verb(g.locked.length, 'is', 'are')} gated by real-work requirements.`;
if (!g.library.length) return 'The library is empty — no skill is defined yet.';
const unscored = g.library.filter((c) => !c.challenge?.rubric?.length).length;
if (unscored) {
return `${plural(unscored, 'skill')} ${verb(unscored, 'has', 'have')} no Owliver criteria, so ${verb(unscored, 'it', 'they')} cannot verify anything yet.`;
}
if (!g.verified.length) {
return `Nothing verified yet — ${plural(g.ready.length, 'challenge')} ${verb(g.ready.length, 'is', 'are')} ready to start.`;
if (g.drafts.length) {
return `${plural(g.drafts.length, 'skill')} ${verb(g.drafts.length, 'is', 'are')} in draft and not visible to the workforce.`;
}
return `${plural(g.verified.length, 'skill')} verified, ${plural(g.ready.length, 'challenge')} ready to start.`;
return `${plural(g.published.length, 'skill')} published, ${plural(g.workforceVerified, 'verification')} earned.`;
},
'admin.talentPool': (f) => {
@@ -165,6 +170,15 @@ const GREETINGS = {
return `${plural(h.hires.length, 'hire')} placed, averaging ${h.avgQuality} at hire.`;
},
'admin.profile': (f) => {
const mine = f.user
? f.activity.filter((e) => e.user_email === f.user.email)
: [];
const full = PERMISSIONS.filter((p) => p.level === 'Full access').length;
if (!mine.length) return `${plural(full, 'scope')} at full access on this account.`;
return `${plural(full, 'scope')} at full access, ${plural(mine.length, 'event')} logged against this account.`;
},
'admin.activity': (f) => {
if (!f.activity.length) return 'No activity logged yet.';
const patterns = f.activitySignals.flags.length;
@@ -203,6 +217,7 @@ const TITLES = {
'admin.forge': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.talentPool': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.hiredHistory': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
'admin.profile': (f, name) => `Good ${timeOfDay(f.today)}${name ? `, ${name}` : ''}`,
};
/** Descriptions state what this page's assistant can actually do with the data. */
@@ -223,11 +238,13 @@ const DESCRIPTIONS = {
`Reading hiring performance across ${plural(f.openPositions.length, 'position')}, ${plural(f.total, 'candidate')} and ${plural(new Set(f.byRole.map((r) => r.category)).size, 'department')} — conversion, speed and outcomes.`,
'admin.activity': (f) => `${plural(f.activity.length, 'logged event')}, reconciled and profiled.`,
'admin.forge': (f) =>
`Reading ${plural(f.forge.courses.length, 'challenge')} — verified skills, what is ready to start and what is still locked.`,
`Reading ${plural(f.forge.library.length, 'skill')} — training, proof, what Owliver evaluates and how the workforce is doing with them.`,
'admin.talentPool': (f) =>
`Reading ${plural(f.profiles.length, 'talent profile')} — availability, career score and verification.`,
'admin.hiredHistory': (f) =>
`Reading ${plural(f.hiring.hires.length, 'hire')} across ${plural(f.hiring.byDepartment.length, 'department')} — quality, speed and outcomes.`,
'admin.profile': () =>
'Reading this account — permissions, security, preferences and your own activity.',
};
/**
@@ -284,9 +301,9 @@ const PLACEHOLDERS = {
'Ask Owliver about security concerns…',
],
'admin.forge': () => [
'Ask Owliver which challenge to take next…',
'Ask Owliver what is blocking a skill…',
'Ask Owliver about Forge progress…',
'Ask Owliver to create a skill training…',
'Ask Owliver what the library covers…',
'Ask Owliver what a skill verifies…',
],
'admin.talentPool': () => [
'Ask Owliver who to prioritize…',
@@ -298,6 +315,11 @@ const PLACEHOLDERS = {
'Ask Owliver which roles hired best…',
'Ask Owliver what stands out…',
],
'admin.profile': () => [
'Ask Owliver about your permissions…',
'Ask Owliver what you can change here…',
'Ask Owliver about your security settings…',
],
};
/* ── Suggested prompts ──────────────────────────────────────────────────── */
@@ -426,18 +448,22 @@ const PROMPTS = {
rather than offering the same questions regardless of state. */
'admin.forge': (f) => {
const g = f.forge;
const unscored = g.library.filter((c) => !c.challenge?.rubric?.length).length;
return [
g.next
? { label: `Should I take ${g.next.title}?`, prompt: `Which challenge should I complete next? Start with ${g.next.title}`, capability: 'forge-next' }
: { label: 'Which challenge should I take next?', prompt: 'Which challenge should I complete next?', capability: 'forge-next' },
g.locked.length
? { label: `${g.locked.length} blocked by requirements`, prompt: 'What is blocking my next skill?', capability: 'forge-blockers' }
: { label: 'What is blocking my next skill?', prompt: 'What is blocking my next skill?', capability: 'forge-blockers' },
g.ready.length
? { label: `${g.ready.length} ready to start`, prompt: 'Which challenges can I start right now?', capability: 'forge-ready' }
: { label: 'Which challenges can I start?', prompt: 'Which challenges can I start right now?', capability: 'forge-ready' },
{ label: 'Which skills am I closest to unlocking?', prompt: 'Which skills am I closest to unlocking?', capability: 'forge-skills' },
{ label: 'Summarize my Forge progress', prompt: 'Summarize my Forge progress', capability: 'forge-progress' },
/* The chip that creates something goes first: on an authoring console the
most likely next action is authoring. It carries no capability, so it
routes through the skill registry rather than the page responder. */
{ label: 'Create a skill training', prompt: 'Create a skill training' },
g.drafts.length
? { label: `${g.drafts.length} in draft`, prompt: 'Which skills are published?', capability: 'forge-published' }
: { label: `${g.published.length} published`, prompt: 'Which skills are published?', capability: 'forge-published' },
unscored
? { label: `${unscored} without Owliver criteria`, prompt: 'What gaps are left in the library?', capability: 'forge-gaps' }
: { label: 'What does Owliver evaluate?', prompt: 'What does Owliver evaluate?', capability: 'forge-evaluation' },
{ label: 'What skills do we currently have?', prompt: 'What skills do we currently have?', capability: 'forge-library' },
g.workforceVerified
? { label: `${g.workforceVerified} skills verified`, prompt: 'How is the workforce doing with these skills?', capability: 'forge-workforce' }
: { label: 'How is the workforce using these?', prompt: 'How is the workforce doing with these skills?', capability: 'forge-workforce' },
];
},
@@ -473,6 +499,22 @@ const PROMPTS = {
];
},
'admin.profile': (f) => {
const mine = f.user ? f.activity.filter((e) => e.user_email === f.user.email) : [];
const restricted = PERMISSIONS.filter((p) => p.level !== 'Full access').length;
return [
{ label: 'What are my permissions?', prompt: 'What are my permissions?', capability: 'profile-permissions' },
restricted
? { label: `${restricted} scopes are restricted`, prompt: 'Which scopes am I restricted on?', capability: 'profile-permissions' }
: { label: 'What can I do here?', prompt: 'What can I do on this page?', capability: 'profile-actions' },
{ label: 'How is my account secured?', prompt: 'How is my account secured?', capability: 'profile-security' },
{ label: 'What are my preferences set to?', prompt: 'What are my preferences set to?', capability: 'profile-preferences' },
mine.length
? { label: `My last ${mine.length} actions`, prompt: 'What is my recent activity?', capability: 'profile-activity' }
: { label: 'What can I change here?', prompt: 'What can I change on this page?', capability: 'profile-actions' },
];
},
'admin.activity': (f) => [
f.activitySignals.flags.length
? { label: `${f.activitySignals.flags.length} unusual patterns`, prompt: 'Show unusual activity on the platform', capability: 'unusual-activity' }