refactor(ts-migration): type src/api and the first of src/lib for noImplicitAny
Phase 12 step 1, in progress. The flag is not enabled yet — these are the
annotations it will require, landed first so the switch itself is a
one-line commit with a number that is already zero.
`noImplicitAny` projects 3496 errors across 242 files. This clears 179 of
them in 7 files: all of `src/api` (107 -> 0) and `workforce`,
`hiringRecords` in `src/lib`.
The leverage is real and worth recording, because it shapes the rest of
the step. Eight annotations on `aiEngine`'s prompt readers cleared 27
errors: where a value is `any`, every callback beneath it — `.map((c) =>
…)`, `.filter((r) => …)` — has no contextual type and errors on its own.
Typing the source fixes the callbacks for free, so this works bottom-up,
sources first.
Types are taken from what already exists wherever possible. The generated
entity types fit `workforce` and `hiringRecords` without a single
cascade: `JobPosting`, `JobApplication`, `Staff`, `AIInterview`,
`WorkerProfile`, `Assignment`, `Course`. `PreferencesUpdateResult` in
`src/types/user.ts` already described `updatePreferences`'s return.
`buildInsights` takes the other builders' outputs, so its parameters are
`ReturnType<typeof byDepartment>` and friends rather than a restatement
that could drift.
Two things are recorded rather than fixed:
`buildHires` probes four fields that are not `staff` columns —
`timeToHire`, `score`, `company` and `department` are absent from
`information_schema` and from the generated `Staff`. They are read as
fallbacks, so at run time they are always `undefined` and the other
branch always wins. `HireSourceRow` writes them down as optional so the
dead fallbacks are visible; removing the reads would be a behaviour
change. `Hire` likewise widens `profile_tier`, because the builder's
default `'skilled'` is lower-case where the column's check constraint
spells it `'Skilled'`.
`aiEngine`'s talent pool stays `any[]`. It is `JSON.parse` output from a
block embedded in a prompt, carrying computed fields like `match_score`
that no entity declares — typing it `WorkerProfile[]` would assert a
shape nothing validates.
One mistake worth keeping. I replaced an inline lookup with a hoisted
`const URGENCY = {…}`, and per-file esbuild said the output was
unchanged: with `--minify-syntax` it inlines a single-use const straight
back. The production bundle disagreed — `43e7f268` against `74d17e2d`.
Reverted to a type assertion, which erases. Hoisting reads as a tidy-up
and is a real change to the emitted code; the two checks disagreeing is
exactly why both are run.
typecheck 0 under the committed config; 3317 under the probe, from 3496
lint exit 0
npm test 1684/1691, the same 7 failures
build exit 0, bundle back to 74d17e2d…
emitted JS 7/7 identical
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HBG1wnuRfJKCstGB8Fekr8
This commit is contained in:
138
src/api/seed.ts
138
src/api/seed.ts
@@ -11,7 +11,7 @@
|
||||
import { SHIFT_RECORDS } from './attendanceSeed';
|
||||
import { DEMO_USER } from './demoUser';
|
||||
|
||||
const iso = (date) => new Date(`${date}T09:00:00.000Z`).toISOString();
|
||||
const iso = (date: string) => new Date(`${date}T09:00:00.000Z`).toISOString();
|
||||
|
||||
/* ── Reference data ────────────────────────────────────────────────────── */
|
||||
|
||||
@@ -347,7 +347,7 @@ const JOB_POSTINGS = [
|
||||
|
||||
/* ── Applications ──────────────────────────────────────────────────────── */
|
||||
|
||||
const breakdown = (over) => ({
|
||||
const breakdown = (over?: Record<string, number>) => ({
|
||||
experience: 0, english: 0, reliability: 0, certifications: 0, availability: 0,
|
||||
personality: 0, culture_fit: 0, communication_style: 0, attendance_expectations: 0,
|
||||
physical_requirements: 0, leadership_expectations: 0, job_related_answers: 0,
|
||||
@@ -356,13 +356,13 @@ const breakdown = (over) => ({
|
||||
});
|
||||
|
||||
/** An applicant who has not been screened yet — every AI field stays empty. */
|
||||
const unscreened = (over) => ({
|
||||
const unscreened = (over?: Record<string, any>) => ({
|
||||
status: 'applied',
|
||||
ai_score: 0,
|
||||
certifications: [],
|
||||
availability: [],
|
||||
skills: [],
|
||||
companies_worked: [],
|
||||
certifications: [] as string[],
|
||||
availability: [] as string[],
|
||||
skills: [] as string[],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
created_date: iso('2026-08-04'),
|
||||
updated_date: iso('2026-08-04'),
|
||||
@@ -428,7 +428,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['ServSafe', 'CPR / First Aid'],
|
||||
availability: ['Weekdays', 'Weekends', 'Evenings'],
|
||||
skills: ['Menu design', 'Brigade leadership', 'Food costing', 'Plated dinners', 'Offsite catering'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.9,
|
||||
professional_summary:
|
||||
'Executive chef with 12 years across hotel banquets and high-end offsite catering. Has run brigades of 20+ and holds plate standards at 400 covers.',
|
||||
@@ -480,7 +480,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Guard Card', 'CPR / First Aid'],
|
||||
availability: ['Weekends', 'Evenings', 'Overnight'],
|
||||
skills: ['Crowd management', 'De-escalation', 'Incident reporting', 'Access control'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.8,
|
||||
professional_summary:
|
||||
'Licensed event security officer with five years across concerts and corporate activations. Known for defusing situations before they escalate.',
|
||||
@@ -514,7 +514,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Guard Card'],
|
||||
availability: ['Weekends', 'Evenings'],
|
||||
skills: ['Access control', 'Incident reporting'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
professional_summary: 'Venue security officer transitioning into private event work.',
|
||||
job_posting_id: 'job_security',
|
||||
@@ -562,7 +562,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['RBS Alcohol Server', 'TIPS Certified'],
|
||||
availability: ['Weekdays', 'Evenings'],
|
||||
skills: ['Batch cocktails', 'Craft cocktails', 'Bar setup', 'Inventory control'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.7,
|
||||
professional_summary:
|
||||
'Corporate event bartender with six years on Bay Area tech campuses. Builds batched programs that hold quality at volume.',
|
||||
@@ -605,7 +605,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Food Handler Card'],
|
||||
availability: ['Weekends', 'Evenings'],
|
||||
skills: ['Synchronized service', 'Tray service', 'Wine service', 'Guest relations'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.6,
|
||||
professional_summary:
|
||||
'Fine dining event server with four years of coursed banquet service and wine knowledge.',
|
||||
@@ -639,7 +639,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Food Handler Card'],
|
||||
availability: ['Weekends'],
|
||||
skills: ['Banquet service', 'Tray service', 'Table resets'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.4,
|
||||
professional_summary: 'Banquet server with three years of seated dinner service.',
|
||||
selfie_url: 'https://i.pravatar.cc/240?img=44',
|
||||
@@ -673,7 +673,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: [],
|
||||
availability: ['Weekends', 'Evenings'],
|
||||
skills: ['Table service'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
professional_summary: 'Restaurant server moving into event work.',
|
||||
job_posting_id: 'job_server_fine',
|
||||
@@ -695,7 +695,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['TIPS Certified'],
|
||||
availability: ['Weekends', 'Evenings'],
|
||||
skills: ['Classic cocktails', 'Bar setup', 'Speed pouring'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.2,
|
||||
professional_summary: 'Event bartender with three years of high-volume weekend service.',
|
||||
job_posting_id: 'job_bartender',
|
||||
@@ -728,7 +728,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['TIPS Certified'],
|
||||
availability: ['Evenings'],
|
||||
skills: ['Bar setup', 'Wine service'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 4.0,
|
||||
professional_summary: 'Barback stepping up to bartending at private events.',
|
||||
job_posting_id: 'job_bartender',
|
||||
@@ -761,7 +761,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: [],
|
||||
availability: ['Weekends'],
|
||||
skills: [],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
professional_summary: 'Looking for a first hospitality role.',
|
||||
job_posting_id: 'job_bartender',
|
||||
@@ -795,7 +795,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Forklift Operator'],
|
||||
availability: ['Weekdays', 'Early mornings'],
|
||||
skills: ['Order picking', 'Scanner operation', 'Pallet staging'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 3.9,
|
||||
professional_summary: 'Warehouse picker with forklift certification.',
|
||||
job_posting_id: 'job_picker',
|
||||
@@ -827,7 +827,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: [],
|
||||
availability: ['Weekdays'],
|
||||
skills: ['Order picking'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
professional_summary: 'Fulfillment associate seeking steady warehouse shifts.',
|
||||
job_posting_id: 'job_picker',
|
||||
@@ -854,7 +854,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Food Handler Card'],
|
||||
availability: ['Weekdays', 'Weekends'],
|
||||
skills: ['Banquet leadership', 'BEO reading', 'Floor coordination'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
professional_summary: 'Banquet server with lead-shift experience in hotel events.',
|
||||
job_posting_id: 'job_banquet',
|
||||
@@ -874,7 +874,7 @@ const JOB_APPLICATIONS = [
|
||||
certifications: ['Food Handler Card'],
|
||||
availability: ['Weekdays', 'Weekends', 'Evenings'],
|
||||
skills: ['Floor leadership', 'Client relations', 'Event reporting'],
|
||||
companies_worked: [],
|
||||
companies_worked: [] as string[],
|
||||
client_rating: 0,
|
||||
professional_summary: 'Hotel banquet captain with six years directing event floors.',
|
||||
job_posting_id: 'job_banquet',
|
||||
@@ -900,7 +900,7 @@ const JOB_APPLICATIONS = [
|
||||
|
||||
/* ── AI interviews ─────────────────────────────────────────────────────── */
|
||||
|
||||
const transcript = (candidate, role) => [
|
||||
const transcript = (candidate: string, role: string) => [
|
||||
{ role: 'assistant', content: `Hi ${candidate.split(' ')[0]} — thanks for making time. Tell me about the busiest ${role} shift you've worked and how you handled it.`, timestamp: iso('2026-08-04') },
|
||||
{ role: 'user', content: 'We were short two people on a 300-guest event. I re-sectioned the floor, moved the strongest server to the head tables, and pulled the rest into a runner rotation so nothing sat under the lamps.', timestamp: iso('2026-08-04'), response_time_seconds: 11 },
|
||||
{ role: 'assistant', content: 'What broke first, and what did you do the moment you noticed?', timestamp: iso('2026-08-04') },
|
||||
@@ -919,7 +919,7 @@ const AI_INTERVIEWS = [
|
||||
verdict: 'maybe',
|
||||
hire_recommendation: 'Worth a trial shift on a coursed dinner before committing to the season.',
|
||||
integrity_score: 100,
|
||||
ai_flags: [],
|
||||
ai_flags: [] as string[],
|
||||
category_scores: {
|
||||
communication: 78, confidence: 71, experience_relevance: 74, culture_fit: 76,
|
||||
problem_solving: 69, personality: 77, communication_style: 76,
|
||||
@@ -947,11 +947,11 @@ const AI_INTERVIEWS = [
|
||||
verdict: 'maybe',
|
||||
hire_recommendation: '',
|
||||
integrity_score: 100,
|
||||
ai_flags: [],
|
||||
ai_flags: [] as string[],
|
||||
category_scores: {},
|
||||
strengths: [],
|
||||
concerns: [],
|
||||
best_fit_roles: [],
|
||||
strengths: [] as string[],
|
||||
concerns: [] as string[],
|
||||
best_fit_roles: [] as string[],
|
||||
summary: '',
|
||||
reasoning: '',
|
||||
created_date: iso('2026-08-05'),
|
||||
@@ -967,11 +967,11 @@ const AI_INTERVIEWS = [
|
||||
verdict: 'maybe',
|
||||
hire_recommendation: '',
|
||||
integrity_score: 100,
|
||||
ai_flags: [],
|
||||
ai_flags: [] as string[],
|
||||
category_scores: {},
|
||||
strengths: [],
|
||||
concerns: [],
|
||||
best_fit_roles: [],
|
||||
strengths: [] as string[],
|
||||
concerns: [] as string[],
|
||||
best_fit_roles: [] as string[],
|
||||
summary: '',
|
||||
reasoning: '',
|
||||
created_date: iso('2026-08-05'),
|
||||
@@ -987,11 +987,11 @@ const AI_INTERVIEWS = [
|
||||
verdict: 'maybe',
|
||||
hire_recommendation: '',
|
||||
integrity_score: 100,
|
||||
ai_flags: [],
|
||||
ai_flags: [] as string[],
|
||||
category_scores: {},
|
||||
strengths: [],
|
||||
concerns: [],
|
||||
best_fit_roles: [],
|
||||
strengths: [] as string[],
|
||||
concerns: [] as string[],
|
||||
best_fit_roles: [] as string[],
|
||||
summary: '',
|
||||
reasoning: '',
|
||||
created_date: iso('2026-08-03'),
|
||||
@@ -1015,7 +1015,7 @@ const STAFF = [
|
||||
ai_score: 92,
|
||||
status: 'onboarding',
|
||||
client_rating: 0,
|
||||
endorsed_skills: [],
|
||||
endorsed_skills: [] as string[],
|
||||
created_date: iso('2026-07-25'),
|
||||
},
|
||||
{
|
||||
@@ -1031,7 +1031,7 @@ const STAFF = [
|
||||
ai_score: 94,
|
||||
status: 'onboarding',
|
||||
client_rating: 0,
|
||||
endorsed_skills: [],
|
||||
endorsed_skills: [] as string[],
|
||||
created_date: iso('2026-07-25'),
|
||||
},
|
||||
{
|
||||
@@ -1047,7 +1047,7 @@ const STAFF = [
|
||||
ai_score: 97,
|
||||
status: 'onboarding',
|
||||
client_rating: 0,
|
||||
endorsed_skills: [],
|
||||
endorsed_skills: [] as string[],
|
||||
created_date: iso('2026-07-25'),
|
||||
},
|
||||
];
|
||||
@@ -1085,7 +1085,7 @@ const COURSES = [
|
||||
{ criterion: 'Protects the table experience', weight: 30 },
|
||||
],
|
||||
},
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] },
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] as string[] },
|
||||
quiz: [
|
||||
{
|
||||
question: 'A guest flags an allergy mid-service. What happens first?',
|
||||
@@ -1127,7 +1127,7 @@ const COURSES = [
|
||||
{ criterion: 'Escalates appropriately', weight: 30 },
|
||||
],
|
||||
},
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] },
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] as string[] },
|
||||
quiz: [
|
||||
{
|
||||
question: 'A guest shows clear signs of intoxication. What do you do?',
|
||||
@@ -1151,7 +1151,7 @@ const COURSES = [
|
||||
proof_skill: 'Hazard Identification',
|
||||
skill_id: 'food_safety',
|
||||
target_level: 'beginner',
|
||||
required_level: null,
|
||||
required_level: null as string | null,
|
||||
completion_criteria: ['Work through the training material', 'Submit evidence for the challenge'],
|
||||
verification_criteria: ['Identifies temperature violations', 'Spots cross-contamination risk', 'Notes obstruction hazards'],
|
||||
challenge: {
|
||||
@@ -1164,7 +1164,7 @@ const COURSES = [
|
||||
{ criterion: 'Notes obstruction hazards', weight: 20 },
|
||||
],
|
||||
},
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] },
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] as string[] },
|
||||
quiz: [
|
||||
{
|
||||
question: 'What is the danger zone for cold-held food?',
|
||||
@@ -1201,7 +1201,7 @@ const COURSES = [
|
||||
],
|
||||
},
|
||||
unlock_requirements: { min_shifts: 5, min_reliability: 70, required_badges: ['Service Fundamentals'] },
|
||||
quiz: [],
|
||||
quiz: [] as unknown[],
|
||||
pass_score: 80,
|
||||
status: 'active',
|
||||
created_date: iso('2026-06-16'),
|
||||
@@ -1293,7 +1293,7 @@ const MODULE_TABLE: [string, string, string, number, string, string, string[]][]
|
||||
['food_safety', 'advanced', 'Incident Response & Reporting', 18, 'roleplay', 'A suspected foodborne incident, in the hour it matters.', ['Isolates the product', 'Documents accurately', 'Notifies the right people']],
|
||||
];
|
||||
|
||||
const SKILL_CATEGORY = {
|
||||
const SKILL_CATEGORY: Record<string, string> = {
|
||||
server: 'Service',
|
||||
bartending: 'Bar',
|
||||
leadership: 'Leadership',
|
||||
@@ -1304,20 +1304,20 @@ const SKILL_CATEGORY = {
|
||||
const LEVEL_ORDER = ['beginner', 'intermediate', 'advanced', 'expert'];
|
||||
|
||||
/** Level → the rung below it, which is what a module requires before it opens. */
|
||||
const requiredLevelFor = (level) => LEVEL_ORDER[LEVEL_ORDER.indexOf(level) - 1] || null;
|
||||
const requiredLevelFor = (level: string) => LEVEL_ORDER[LEVEL_ORDER.indexOf(level) - 1] || null;
|
||||
|
||||
/** Difficulty is the existing field; level drives it so the two never disagree. */
|
||||
const DIFFICULTY_FOR = { beginner: 'beginner', intermediate: 'intermediate', advanced: 'advanced', expert: 'advanced' };
|
||||
const DIFFICULTY_FOR: Record<string, string> = { beginner: 'beginner', intermediate: 'intermediate', advanced: 'advanced', expert: 'advanced' };
|
||||
|
||||
const XP_FOR = { beginner: 100, intermediate: 150, advanced: 220, expert: 300 };
|
||||
const XP_FOR: Record<string, number> = { beginner: 100, intermediate: 150, advanced: 220, expert: 300 };
|
||||
|
||||
const PROMPT_FOR = {
|
||||
const PROMPT_FOR: Record<string, (title: string) => string> = {
|
||||
roleplay: (title) => `Work through a ${title.toLowerCase()} scenario with Owliver, start to finish.`,
|
||||
video: (title) => `Record yourself demonstrating ${title.toLowerCase()} as you would on a live shift.`,
|
||||
photo_identify: (title) => `Mark everything a ${title.toLowerCase()} check should catch in this photo.`,
|
||||
};
|
||||
|
||||
const slug = (title) => title.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
|
||||
const slug = (title: string) => title.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
|
||||
|
||||
const TRAINING_MODULES = MODULE_TABLE.map(
|
||||
([skill_id, target_level, title, minutes, type, description, criteria], i) => ({
|
||||
@@ -1341,8 +1341,8 @@ const TRAINING_MODULES = MODULE_TABLE.map(
|
||||
ai_persona: type === 'roleplay' ? 'A guest or teammate in a live service situation.' : undefined,
|
||||
rubric: (Array.isArray(criteria) ? criteria : []).map((criterion, n) => ({ criterion, weight: n === 0 ? 40 : 30 })),
|
||||
},
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] },
|
||||
quiz: [],
|
||||
unlock_requirements: { min_shifts: 0, min_reliability: 0, required_badges: [] as string[] },
|
||||
quiz: [] as unknown[],
|
||||
pass_score: 70,
|
||||
status: 'active',
|
||||
created_date: iso('2026-06-20'),
|
||||
@@ -1354,7 +1354,7 @@ const TRAINING_MODULES = MODULE_TABLE.map(
|
||||
const COURSE_LIBRARY = [...COURSES, ...TRAINING_MODULES];
|
||||
|
||||
/** A module id from its skill and title, so profiles read like the ladder does. */
|
||||
const mod = (skill, title) => `mod_${skill}_${slug(title)}`;
|
||||
const mod = (skill: string, title: string) => `mod_${skill}_${slug(title)}`;
|
||||
|
||||
/**
|
||||
* Completed training on a worker profile.
|
||||
@@ -1362,7 +1362,7 @@ const mod = (skill, title) => `mod_${skill}_${slug(title)}`;
|
||||
* Titles are looked up rather than repeated, so a renamed module cannot leave a
|
||||
* profile claiming a course that no longer goes by that name.
|
||||
*/
|
||||
const completions = (ids, date, score = 88) =>
|
||||
const completions = (ids: string[], date: string, score = 88) =>
|
||||
ids.map((id) => ({
|
||||
course_id: id,
|
||||
title: COURSE_LIBRARY.find((c) => c.id === id)?.title || id,
|
||||
@@ -1535,7 +1535,7 @@ const WORKER_PROFILES = [
|
||||
earned_badges: [
|
||||
{ name: 'Service Fundamentals', level: 'bronze', course_id: 'course_service_basics', earned_date: iso('2026-07-28') },
|
||||
],
|
||||
capabilities: [],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 6,
|
||||
attendance_score: 92,
|
||||
performance_score: 0,
|
||||
@@ -1605,8 +1605,8 @@ const WORKER_PROFILES = [
|
||||
'2026-08-02',
|
||||
89
|
||||
),
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 38,
|
||||
attendance_score: 96,
|
||||
performance_score: 88,
|
||||
@@ -1653,8 +1653,8 @@ const WORKER_PROFILES = [
|
||||
'2026-07-30',
|
||||
85
|
||||
),
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 21,
|
||||
attendance_score: 93,
|
||||
performance_score: 81,
|
||||
@@ -1701,8 +1701,8 @@ const WORKER_PROFILES = [
|
||||
'2026-08-05',
|
||||
76
|
||||
),
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 4,
|
||||
attendance_score: 100,
|
||||
performance_score: 0,
|
||||
@@ -1745,8 +1745,8 @@ const WORKER_PROFILES = [
|
||||
},
|
||||
xp: 0,
|
||||
completed_courses: [],
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 0,
|
||||
attendance_score: 100,
|
||||
performance_score: 0,
|
||||
@@ -1789,8 +1789,8 @@ const WORKER_PROFILES = [
|
||||
},
|
||||
xp: 0,
|
||||
completed_courses: [],
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 0,
|
||||
attendance_score: 100,
|
||||
performance_score: 0,
|
||||
@@ -1833,8 +1833,8 @@ const WORKER_PROFILES = [
|
||||
},
|
||||
xp: 0,
|
||||
completed_courses: [],
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 0,
|
||||
attendance_score: 100,
|
||||
performance_score: 0,
|
||||
@@ -1877,8 +1877,8 @@ const WORKER_PROFILES = [
|
||||
},
|
||||
xp: 0,
|
||||
completed_courses: [],
|
||||
earned_badges: [],
|
||||
capabilities: [],
|
||||
earned_badges: [] as unknown[],
|
||||
capabilities: [] as unknown[],
|
||||
shifts_completed: 0,
|
||||
attendance_score: 100,
|
||||
performance_score: 0,
|
||||
@@ -2024,7 +2024,7 @@ const ASSIGNMENTS = [
|
||||
worker_email: 'marco.rivera@email.com',
|
||||
worker_name: 'Marco Rivera',
|
||||
starts_at: iso('2026-07-01'),
|
||||
ends_at: null,
|
||||
ends_at: null as string | null,
|
||||
status: 'active',
|
||||
source: 'seed',
|
||||
match_score: 92,
|
||||
|
||||
Reference in New Issue
Block a user