810485ecc8
---ci--- phase: 7 milestone: v0.1 status: complete requirements: covered: [REQ-001, REQ-002, REQ-003, REQ-004, REQ-005, REQ-006, REQ-007, REQ-008, REQ-009, REQ-010, REQ-011, REQ-012, REQ-013, REQ-014, REQ-015, REQ-016, REQ-017, REQ-018, REQ-019, REQ-020, REQ-021, REQ-022, REQ-023, REQ-024, REQ-025, REQ-026, REQ-027, REQ-028] partial: [] ---/ci--- Milestone v0.1 (nextcraft-ui-prototype) complete. Summary: - 7 phases (P0 pre-execution + P1-P6 execution + P7 final review) - 28 requirements covered (all complete) - 4 surfaces: Learner (7 pages), Marketplace (5), Employer Dashboard (4), Admin (4) - 19 routes, 104 TypeScript files - Shared component library (5 primitives + design tokens) - Mock data: 5 competency stacks (70 competencies), 20 jobs, 15 candidates, 10 employers - Tech: Next.js 15, Tailwind CSS v4, lucide-react, recharts, @xyflow/react, Inter font - Storybook with 6 stories - Dark mode, breadcrumbs, role switcher, responsive design - Build passes, typecheck passes, Storybook build passes Phases: P0 pre-execution → v0.0.1 P1 project-scaffolding → v0.0.2 P2 learner-surface → v0.0.3 P3 marketplace-surface → v0.0.4 P4 employer-dashboard → v0.0.5 P5 admin-surface → v0.0.6 P6 polish-integration → v0.0.7 P7 final-review-ship → v0.1.0 (milestone release)
470 lines
16 KiB
TypeScript
470 lines
16 KiB
TypeScript
/**
|
|
* Nextcraft — Admin Surface Mock Data
|
|
*
|
|
* Mock data for the admin surface only: platform metrics, activity feed,
|
|
* system health, learner roster (admin view), and marketplace moderation
|
|
* queues. Pure prototype data — no backend, no business logic.
|
|
*/
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Platform metrics (REQ-022)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface PlatformMetric {
|
|
id: string;
|
|
label: string;
|
|
value: number;
|
|
/** Rendered suffix (e.g. "%" or ""). */
|
|
suffix: string;
|
|
/** Trend vs previous period, in percentage points (signed). */
|
|
trendPct: number;
|
|
/** Lucide icon name (resolved by the page). */
|
|
icon: string;
|
|
/** Tailwind color token used for the icon chip. */
|
|
tone: 'indigo' | 'emerald' | 'amber' | 'rose' | 'cyan' | 'violet';
|
|
}
|
|
|
|
export const platformMetrics: PlatformMetric[] = [
|
|
{
|
|
id: 'metric-learners',
|
|
label: 'Total Learners',
|
|
value: 1247,
|
|
suffix: '',
|
|
trendPct: 4.2,
|
|
icon: 'Users',
|
|
tone: 'indigo',
|
|
},
|
|
{
|
|
id: 'metric-employers',
|
|
label: 'Total Employers',
|
|
value: 89,
|
|
suffix: '',
|
|
trendPct: 1.8,
|
|
icon: 'Building2',
|
|
tone: 'emerald',
|
|
},
|
|
{
|
|
id: 'metric-placements',
|
|
label: 'Active Placements',
|
|
value: 312,
|
|
suffix: '',
|
|
trendPct: 6.5,
|
|
icon: 'Briefcase',
|
|
tone: 'amber',
|
|
},
|
|
{
|
|
id: 'metric-completion',
|
|
label: 'Completion Rate',
|
|
value: 38,
|
|
suffix: '%',
|
|
trendPct: 2.1,
|
|
icon: 'GraduationCap',
|
|
tone: 'violet',
|
|
},
|
|
{
|
|
id: 'metric-nps',
|
|
label: 'NPS Score',
|
|
value: 47,
|
|
suffix: '',
|
|
trendPct: -1.2,
|
|
icon: 'ThumbsUp',
|
|
tone: 'cyan',
|
|
},
|
|
];
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Activity feed (REQ-022)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface ActivityEvent {
|
|
id: string;
|
|
message: string;
|
|
/** Relative-time label shown to the user (kept static for the prototype). */
|
|
relativeTime: string;
|
|
/** Lucide icon name. */
|
|
icon: string;
|
|
/** Tailwind color token used for the icon chip. */
|
|
tone: 'indigo' | 'emerald' | 'amber' | 'rose' | 'cyan' | 'violet';
|
|
}
|
|
|
|
export const activityFeed: ActivityEvent[] = [
|
|
{
|
|
id: 'act-001',
|
|
message: 'New learner registered: Sarah Chen joined AI Orchestration Engineer stack',
|
|
relativeTime: '5 min ago',
|
|
icon: 'UserPlus',
|
|
tone: 'indigo',
|
|
},
|
|
{
|
|
id: 'act-002',
|
|
message: "Competency mastered: Marcus Lee completed 'Multi-Agent Communication'",
|
|
relativeTime: '23 min ago',
|
|
icon: 'CheckCircle',
|
|
tone: 'emerald',
|
|
},
|
|
{
|
|
id: 'act-003',
|
|
message: "New job posted: OpenAI Labs posted 'Senior LLM Engineer'",
|
|
relativeTime: '1 hour ago',
|
|
icon: 'Briefcase',
|
|
tone: 'amber',
|
|
},
|
|
{
|
|
id: 'act-004',
|
|
message: 'Placement recorded: Alex Rivera hired at Anthropic Research',
|
|
relativeTime: '2 hours ago',
|
|
icon: 'Award',
|
|
tone: 'violet',
|
|
},
|
|
{
|
|
id: 'act-005',
|
|
message: 'Employer verified: Hugging Face completed identity verification',
|
|
relativeTime: '3 hours ago',
|
|
icon: 'ShieldCheck',
|
|
tone: 'emerald',
|
|
},
|
|
{
|
|
id: 'act-006',
|
|
message: 'Microcredential issued: 5 learners earned RAG Pipeline Design credential',
|
|
relativeTime: '5 hours ago',
|
|
icon: 'GraduationCap',
|
|
tone: 'cyan',
|
|
},
|
|
{
|
|
id: 'act-007',
|
|
message: "Oral defense completed: Jamie Park defended 'Agent Architecture Patterns'",
|
|
relativeTime: '8 hours ago',
|
|
icon: 'MessageSquare',
|
|
tone: 'indigo',
|
|
},
|
|
{
|
|
id: 'act-008',
|
|
message: 'New enrollment spike: 23 new learners in Computational Sciences',
|
|
relativeTime: '12 hours ago',
|
|
icon: 'TrendingUp',
|
|
tone: 'rose',
|
|
},
|
|
{
|
|
id: 'act-009',
|
|
message: "Competency published: 'Guardrails & Output Validation' added to AI Orchestration stack",
|
|
relativeTime: '1 day ago',
|
|
icon: 'BookOpen',
|
|
tone: 'violet',
|
|
},
|
|
{
|
|
id: 'act-010',
|
|
message: 'Employer application submitted: Mistral AI requested marketplace access',
|
|
relativeTime: '2 days ago',
|
|
icon: 'Building2',
|
|
tone: 'amber',
|
|
},
|
|
];
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// System health (REQ-022)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type ServiceStatus = 'operational' | 'degraded' | 'down';
|
|
|
|
export interface ServiceHealth {
|
|
id: string;
|
|
name: string;
|
|
status: ServiceStatus;
|
|
}
|
|
|
|
export const serviceHealth: ServiceHealth[] = [
|
|
{ id: 'svc-web', name: 'Web Server', status: 'operational' },
|
|
{ id: 'svc-db', name: 'Database', status: 'operational' },
|
|
{ id: 'svc-ai-tutor', name: 'AI Tutor Service', status: 'operational' },
|
|
{ id: 'svc-assessment', name: 'Assessment Engine', status: 'degraded' },
|
|
{ id: 'svc-jobs', name: 'Job Aggregation', status: 'operational' },
|
|
{ id: 'svc-search', name: 'Search Service', status: 'operational' },
|
|
];
|
|
|
|
/** 30-day uptime bars (mock percentages for the simple visual). */
|
|
export const uptimeBars: number[] = [
|
|
99.98, 99.99, 99.95, 99.97, 100.0, 99.91, 99.88, 99.97, 99.99, 99.96, 99.92,
|
|
99.98, 99.99, 99.95, 100.0, 99.97, 99.93, 99.9, 99.96, 99.98, 99.99, 99.94,
|
|
99.97, 99.96, 99.92, 99.99, 99.98, 99.95, 99.97, 99.96,
|
|
];
|
|
|
|
export interface SystemStats {
|
|
errorRate: string;
|
|
avgResponseMs: number;
|
|
}
|
|
|
|
export const systemStats: SystemStats = {
|
|
errorRate: '0.02%',
|
|
avgResponseMs: 142,
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Learner roster (admin view) (REQ-023)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type LearnerStatus = 'active' | 'completed' | 'paused';
|
|
|
|
export interface AdminLearnerCompetency {
|
|
id: string;
|
|
name: string;
|
|
status: 'mastered' | 'in_progress' | 'available' | 'locked';
|
|
}
|
|
|
|
export interface AdminLearnerCredential {
|
|
id: string;
|
|
name: string;
|
|
issuedAt: string;
|
|
score: number;
|
|
}
|
|
|
|
export interface AdminLearner {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
stackId: string;
|
|
stackName: string;
|
|
progressPct: number;
|
|
masteredCount: number;
|
|
totalCompetencies: number;
|
|
status: LearnerStatus;
|
|
joinedAt: string;
|
|
competencies: AdminLearnerCompetency[];
|
|
credentials: AdminLearnerCredential[];
|
|
}
|
|
|
|
const STACKS = [
|
|
{ id: 'stack-orchestration', name: 'AI Orchestration Engineer' },
|
|
{ id: 'stack-safety', name: 'AI Safety & Governance Lead' },
|
|
{ id: 'stack-designer', name: 'Human-AI Product Designer' },
|
|
{ id: 'stack-operator', name: 'AI-Augmented Field Operator' },
|
|
{ id: 'stack-science', name: 'Computational Sciences Practitioner' },
|
|
];
|
|
|
|
const STACK_TOTALS: Record<string, number> = {
|
|
'stack-orchestration': 15,
|
|
'stack-safety': 14,
|
|
'stack-designer': 13,
|
|
'stack-operator': 12,
|
|
'stack-science': 16,
|
|
};
|
|
|
|
const COMP_NAME_BANK: Record<string, string[]> = {
|
|
'stack-orchestration': [
|
|
'Agent Architecture Patterns',
|
|
'Multi-Agent Communication',
|
|
'Tool Use & Function Calling',
|
|
'Prompt Engineering Fundamentals',
|
|
'RAG Pipeline Design',
|
|
'Vector Databases & Embeddings',
|
|
'LLM Evaluation & Metrics',
|
|
'Guardrails & Output Validation',
|
|
'Agent Memory Systems',
|
|
'Workflow Orchestration',
|
|
'Model Routing & Cascading',
|
|
'Streaming & Incremental Output',
|
|
'Observability for Agents',
|
|
'Cost Optimization Strategies',
|
|
'Production Deployment Patterns',
|
|
],
|
|
'stack-safety': [
|
|
'Alignment Fundamentals',
|
|
'Red Teaming Methodologies',
|
|
'Model Card Authoring',
|
|
'Bias Auditing',
|
|
'AI Policy Frameworks',
|
|
'Risk Taxonomy & Classification',
|
|
'Interpretability Techniques',
|
|
'Incident Response for AI',
|
|
'Data Provenance & Lineage',
|
|
'Jailbreak & Prompt Injection Defense',
|
|
'Model Monitoring in Production',
|
|
'Privacy-Preserving ML',
|
|
'Governance Documentation',
|
|
'Stakeholder Communication',
|
|
],
|
|
'stack-designer': [
|
|
'Agentic Interaction Patterns',
|
|
'Conversational UX',
|
|
'AI Transparency Patterns',
|
|
'Human-in-the-Loop Design',
|
|
'Prompt UX',
|
|
'Failure & Fallback Design',
|
|
'Multimodal Interface Design',
|
|
'Trust & Calibration',
|
|
'Accessibility for AI Interfaces',
|
|
'Persona & Tone Systems',
|
|
'Evaluation of AI UX',
|
|
'Onboarding to Agentic Systems',
|
|
'AI Ethics in Product Design',
|
|
],
|
|
'stack-operator': [
|
|
'AI Co-Pilot Operation',
|
|
'Robotics Safety Protocols',
|
|
'Predictive Maintenance Alerts',
|
|
'Computer Vision Inspection',
|
|
'Sensor Data Interpretation',
|
|
'Digital Twin Fundamentals',
|
|
'Augmented Reality Overlays',
|
|
'Edge Model Deployment',
|
|
'Calibration & Drift Correction',
|
|
'Field Data Collection',
|
|
'Autonomous System Supervision',
|
|
'Safety-Critical Decision Making',
|
|
],
|
|
'stack-science': [
|
|
'Scientific Computing with Python',
|
|
'ML for Scientific Discovery',
|
|
'Molecular & Materials Simulation',
|
|
'Climate Modeling Fundamentals',
|
|
'Bioinformatics Pipelines',
|
|
'High-Performance Computing',
|
|
'Scientific Data Visualization',
|
|
'Reproducible Research Practices',
|
|
'Statistical Inference',
|
|
'Physics-Informed Neural Networks',
|
|
'Generative Models for Science',
|
|
'Causal Inference Methods',
|
|
'Experiment Design',
|
|
'Data Assimilation',
|
|
'Scientific Writing with AI',
|
|
'Open Science & FAIR Data',
|
|
],
|
|
};
|
|
|
|
function buildCompetencies(
|
|
stackId: string,
|
|
mastered: number,
|
|
inProgress: number,
|
|
): AdminLearnerCompetency[] {
|
|
const names = COMP_NAME_BANK[stackId] ?? [];
|
|
const out: AdminLearnerCompetency[] = names.map((name, i) => {
|
|
let status: AdminLearnerCompetency['status'] = 'locked';
|
|
if (i < mastered) status = 'mastered';
|
|
else if (i < mastered + inProgress) status = 'in_progress';
|
|
else if (i < mastered + inProgress + 3) status = 'available';
|
|
return { id: `${stackId}-c${i.toString().padStart(3, '0')}`, name, status };
|
|
});
|
|
return out;
|
|
}
|
|
|
|
function buildCredentials(
|
|
stackId: string,
|
|
mastered: number,
|
|
): AdminLearnerCredential[] {
|
|
const names = COMP_NAME_BANK[stackId] ?? [];
|
|
const count = Math.min(mastered, 6);
|
|
const out: AdminLearnerCredential[] = [];
|
|
for (let i = 0; i < count; i++) {
|
|
out.push({
|
|
id: `mc-${stackId}-${i}`,
|
|
name: names[i] ?? `Competency ${i + 1}`,
|
|
issuedAt: `2026-0${(i % 8) + 1}-${((i * 4) % 27 + 1).toString().padStart(2, '0')}T10:00:00Z`,
|
|
score: 80 + ((i * 7) % 18),
|
|
});
|
|
}
|
|
return out;
|
|
}
|
|
|
|
interface RosterSeed {
|
|
name: string;
|
|
email: string;
|
|
stackIdx: number;
|
|
mastered: number;
|
|
inProgress: number;
|
|
status: LearnerStatus;
|
|
joinedAt: string;
|
|
}
|
|
|
|
const ROSTER_SEEDS: RosterSeed[] = [
|
|
{ name: 'Sarah Chen', email: 'sarah.chen@example.com', stackIdx: 0, mastered: 9, inProgress: 2, status: 'active', joinedAt: '2026-05-12T09:00:00Z' },
|
|
{ name: 'Marcus Lee', email: 'marcus.lee@example.com', stackIdx: 0, mastered: 14, inProgress: 1, status: 'active', joinedAt: '2026-02-03T09:00:00Z' },
|
|
{ name: 'Jamie Park', email: 'jamie.park@example.com', stackIdx: 0, mastered: 15, inProgress: 0, status: 'completed', joinedAt: '2025-12-01T09:00:00Z' },
|
|
{ name: 'Alex Rivera', email: 'alex.rivera@example.com', stackIdx: 1, mastered: 10, inProgress: 2, status: 'active', joinedAt: '2026-04-18T09:00:00Z' },
|
|
{ name: 'Priya Sharma', email: 'priya.sharma@example.com', stackIdx: 1, mastered: 5, inProgress: 3, status: 'active', joinedAt: '2026-06-22T09:00:00Z' },
|
|
{ name: 'Diego Morales', email: 'diego.morales@example.com', stackIdx: 1, mastered: 14, inProgress: 0, status: 'completed', joinedAt: '2025-11-10T09:00:00Z' },
|
|
{ name: 'Riley Thompson', email: 'riley.thompson@example.com', stackIdx: 2, mastered: 7, inProgress: 2, status: 'active', joinedAt: '2026-07-01T09:00:00Z' },
|
|
{ name: 'Maya Patel', email: 'maya.patel@example.com', stackIdx: 2, mastered: 3, inProgress: 1, status: 'paused', joinedAt: '2026-08-15T09:00:00Z' },
|
|
{ name: 'Jordan Kim', email: 'jordan.kim@example.com', stackIdx: 2, mastered: 13, inProgress: 0, status: 'completed', joinedAt: '2026-01-20T09:00:00Z' },
|
|
{ name: 'Sam Wilson', email: 'sam.wilson@example.com', stackIdx: 3, mastered: 4, inProgress: 2, status: 'active', joinedAt: '2026-08-02T09:00:00Z' },
|
|
{ name: 'Taylor Brooks', email: 'taylor.brooks@example.com', stackIdx: 3, mastered: 12, inProgress: 0, status: 'completed', joinedAt: '2026-01-05T09:00:00Z' },
|
|
{ name: 'Casey Nguyen', email: 'casey.nguyen@example.com', stackIdx: 4, mastered: 8, inProgress: 3, status: 'active', joinedAt: '2026-03-30T09:00:00Z' },
|
|
{ name: 'Morgan Davis', email: 'morgan.davis@example.com', stackIdx: 4, mastered: 16, inProgress: 0, status: 'completed', joinedAt: '2025-10-14T09:00:00Z' },
|
|
{ name: 'Avery Garcia', email: 'avery.garcia@example.com', stackIdx: 4, mastered: 2, inProgress: 1, status: 'paused', joinedAt: '2026-08-28T09:00:00Z' },
|
|
{ name: 'Quinn Foster', email: 'quinn.foster@example.com', stackIdx: 0, mastered: 6, inProgress: 3, status: 'active', joinedAt: '2026-07-19T09:00:00Z' },
|
|
];
|
|
|
|
export const adminLearners: AdminLearner[] = ROSTER_SEEDS.map((seed, i) => {
|
|
const stack = STACKS[seed.stackIdx];
|
|
const total = STACK_TOTALS[stack.id];
|
|
const competencies = buildCompetencies(stack.id, seed.mastered, seed.inProgress);
|
|
const credentials = buildCredentials(stack.id, seed.mastered);
|
|
const progressPct = Math.round((seed.mastered / total) * 100);
|
|
return {
|
|
id: `adm-lrn-${(i + 1).toString().padStart(3, '0')}`,
|
|
name: seed.name,
|
|
email: seed.email,
|
|
stackId: stack.id,
|
|
stackName: stack.name,
|
|
progressPct,
|
|
masteredCount: seed.mastered,
|
|
totalCompetencies: total,
|
|
status: seed.status,
|
|
joinedAt: seed.joinedAt,
|
|
competencies,
|
|
credentials,
|
|
};
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Marketplace moderation queues (REQ-025)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface JobReviewItem {
|
|
id: string;
|
|
title: string;
|
|
employerName: string;
|
|
submittedAt: string;
|
|
stackName: string;
|
|
location: string;
|
|
}
|
|
|
|
export const jobReviewQueue: JobReviewItem[] = [
|
|
{ id: 'rev-001', title: 'Senior LLM Engineer', employerName: 'OpenAI Labs', submittedAt: '2026-09-08T14:00:00Z', stackName: 'AI Orchestration Engineer', location: 'San Francisco, CA (Remote)' },
|
|
{ id: 'rev-002', title: 'AI Safety Auditor', employerName: 'Anthropic Research', submittedAt: '2026-09-09T11:30:00Z', stackName: 'AI Safety & Governance Lead', location: 'San Francisco, CA' },
|
|
{ id: 'rev-003', title: 'Agentic UX Designer', employerName: 'Hugging Face', submittedAt: '2026-09-09T16:45:00Z', stackName: 'Human-AI Product Designer', location: 'Remote' },
|
|
{ id: 'rev-004', title: 'Field Robotics Lead', employerName: 'Boston Dynamics', submittedAt: '2026-09-10T08:15:00Z', stackName: 'AI-Augmented Field Operator', location: 'Waltham, MA' },
|
|
{ id: 'rev-005', title: 'Climate ML Researcher', employerName: 'DeepMind', submittedAt: '2026-09-10T10:00:00Z', stackName: 'Computational Sciences Practitioner', location: 'London (Remote)' },
|
|
];
|
|
|
|
export interface EmployerVerificationItem {
|
|
id: string;
|
|
name: string;
|
|
logoInitials: string;
|
|
industry: string;
|
|
submittedAt: string;
|
|
location: string;
|
|
}
|
|
|
|
export const employerVerificationQueue: EmployerVerificationItem[] = [
|
|
{ id: 'ver-001', name: 'Mistral AI', logoInitials: 'MA', industry: 'Artificial Intelligence', submittedAt: '2026-09-07T09:00:00Z', location: 'Paris, France' },
|
|
{ id: 'ver-002', name: 'Cohere', logoInitials: 'CO', industry: 'Language Models', submittedAt: '2026-09-08T13:20:00Z', location: 'Toronto, Canada' },
|
|
{ id: 'ver-003', name: 'Scale AI', logoInitials: 'SA', industry: 'Data & Annotation', submittedAt: '2026-09-09T17:00:00Z', location: 'San Francisco, CA' },
|
|
];
|
|
|
|
export type FlaggedContentType = 'Job Posting' | 'Review' | 'Employer Profile';
|
|
|
|
export interface FlaggedContentItem {
|
|
id: string;
|
|
contentType: FlaggedContentType;
|
|
title: string;
|
|
flaggedBy: string;
|
|
reason: string;
|
|
flaggedAt: string;
|
|
}
|
|
|
|
export const flaggedContentQueue: FlaggedContentItem[] = [
|
|
{ id: 'flag-001', contentType: 'Job Posting', title: 'Junior Prompt Engineer', flaggedBy: 'Automated filter', reason: 'Suspicious salary range', flaggedAt: '2026-09-09T12:00:00Z' },
|
|
{ id: 'flag-002', contentType: 'Review', title: 'Anonymous review on OpenAI Labs', flaggedBy: 'User report', reason: 'Inappropriate language', flaggedAt: '2026-09-09T18:30:00Z' },
|
|
{ id: 'flag-003', contentType: 'Employer Profile', title: 'Stealth Startup 42', flaggedBy: 'Moderator', reason: 'Unverified contact info', flaggedAt: '2026-09-10T07:45:00Z' },
|
|
{ id: 'flag-004', contentType: 'Job Posting', title: 'ML Internship', flaggedBy: 'Automated filter', reason: 'Missing required fields', flaggedAt: '2026-09-10T09:15:00Z' },
|
|
]; |