Files
nextcraft/packages/mock-data/admin.ts
T
CIAgent 810485ecc8 docs(milestone): complete v0.1-nextcraft-ui-prototype
---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)
2026-09-10 22:47:56 +00:00

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' },
];