Files
krow-worker-app/lib/state/seed.dart
2026-09-17 22:26:11 +05:30

393 lines
11 KiB
Dart

import '../models/compliance.dart';
import '../models/shift.dart';
import '../models/timecard.dart';
/// Demo content. Everything is anchored to "now" so the app is live whenever
/// it is opened: the next shift always starts in 41 minutes.
abstract final class Seed {
static DateTime get _now => DateTime.now();
static DateTime _at(int dayOffset, int hour, int minute) {
final base = _now.add(Duration(days: dayOffset));
return DateTime(base.year, base.month, base.day, hour, minute);
}
static const _baristaReqs = [
'Government ID',
'Food handler certification',
'Black pants',
'Black shirt',
'Non-slip black shoes',
];
static List<Shift> shifts() {
final now = _now;
// Inside the 30-minute clock-in window, so the app opens on a shift you
// can actually start.
final soon = now.add(const Duration(minutes: 20));
return [
// Today: the shift you are about to clock into.
Shift(
id: 's1',
role: 'Barista',
business: 'Zoox',
venue: 'Zoox - San Jose Hub',
address: '848 E Gish Rd, San Jose CA',
start: soon,
end: soon.add(const Duration(hours: 6)),
rate: 21.00,
status: ShiftStatus.booked,
distanceMiles: 2.4,
manager: 'Kirk R. - Owner',
requirements: _baristaReqs,
),
Shift(
id: 's2',
role: 'Server',
business: 'Google LLC',
venue: 'Google LLC - Midpoint',
address: 'Midpoint, Sunnyvale CA',
start: _at(1, 13, 0),
end: _at(1, 18, 0),
rate: 24.00,
status: ShiftStatus.booked,
distanceMiles: 3.1,
manager: 'Dana W. - Floor lead',
requirements: _baristaReqs,
),
// Open market, highest paying first.
Shift(
id: 's3',
role: 'Bartender',
business: 'Google LLC',
venue: 'Google LLC - Midpoint',
address: 'Midpoint, Sunnyvale CA',
start: _at(2, 16, 0),
end: _at(2, 23, 0),
rate: 28.00,
status: ShiftStatus.open,
distanceMiles: 3.1,
requirements: [..._baristaReqs, 'Responsible beverage service'],
),
Shift(
id: 's4',
role: 'Barista',
business: 'Zoox',
venue: 'Zoox - San Jose Hub',
address: '848 E Gish Rd, San Jose CA',
start: _at(3, 18, 0),
end: _at(3, 23, 50),
rate: 21.00,
status: ShiftStatus.open,
distanceMiles: 2.4,
requirements: _baristaReqs,
),
Shift(
id: 's5',
role: 'Host',
business: 'Google LLC',
venue: 'Google LLC - Midpoint',
address: 'Midpoint, Sunnyvale CA',
start: _at(4, 11, 0),
end: _at(4, 17, 0),
rate: 19.50,
status: ShiftStatus.open,
distanceMiles: 3.1,
requirements: _baristaReqs,
),
Shift(
id: 's6',
role: 'Banquet server',
business: 'Legendary Events',
venue: 'Legendary Events - Convention Centre',
address: '150 W San Carlos St, San Jose CA',
start: _at(5, 9, 0),
end: _at(5, 17, 30),
rate: 22.50,
status: ShiftStatus.open,
distanceMiles: 4.8,
requirements: _baristaReqs,
),
// Worked history.
Shift(
id: 's7',
role: 'Barista',
business: 'Zoox',
venue: 'Zoox - San Jose Hub',
address: '848 E Gish Rd, San Jose CA',
start: _at(-4, 17, 50),
end: _at(-4, 23, 50),
rate: 21.00,
status: ShiftStatus.completed,
distanceMiles: 2.4,
clockIn: _at(-4, 18, 1),
clockOut: _at(-4, 23, 50),
requirements: _baristaReqs,
),
Shift(
id: 's8',
role: 'Barista',
business: 'Google LLC',
venue: 'Google LLC - Midpoint',
address: 'Midpoint, Sunnyvale CA',
start: _at(-6, 11, 0),
end: _at(-6, 18, 0),
rate: 21.00,
status: ShiftStatus.cancelled,
distanceMiles: 3.1,
requirements: _baristaReqs,
),
Shift(
id: 's9',
role: 'Barista',
business: 'Google LLC',
venue: 'Google LLC - Midpoint',
address: 'Midpoint, Sunnyvale CA',
start: _at(-13, 9, 0),
end: _at(-13, 15, 0),
rate: 21.00,
status: ShiftStatus.noShow,
distanceMiles: 3.1,
requirements: _baristaReqs,
),
];
}
static List<Timecard> timecards() {
final worked = shifts().firstWhere((s) => s.id == 's7');
return [
Timecard(
id: 'tc1',
shiftId: worked.id,
role: worked.role,
business: worked.business,
scheduledStart: worked.start,
scheduledEnd: worked.end,
clockIn: worked.clockIn!,
clockOut: worked.clockOut!,
breakMinutes: worked.breakMinutes,
rate: worked.rate,
status: TimecardStatus.needsReview,
submittedAt: worked.clockOut!.add(const Duration(minutes: 12)),
),
];
}
static List<ComplianceItem> documents() => [
ComplianceItem(
id: 'd1',
title: 'Government ID',
subtitle: 'State ID or passport',
state: ComplianceState.verified,
fileName: 'government-id-front.jpg',
fileMeta: '2.1 MB - uploaded 2 Aug',
expires: DateTime(2029, 3, 14),
),
ComplianceItem(
id: 'd2',
title: 'Social security',
subtitle: 'Card or SSA letter',
state: ComplianceState.verified,
fileName: 'ssn-card.jpg',
fileMeta: '1.2 MB - uploaded 2 Aug',
),
ComplianceItem(
id: 'd3',
title: 'Work permit',
subtitle: 'Right-to-work evidence',
state: ComplianceState.verified,
fileName: 'work-permit.pdf',
fileMeta: '640 KB - uploaded 2 Aug',
),
ComplianceItem(
id: 'd4',
title: 'Proof of address',
subtitle: 'Bill or statement, last 90 days',
state: ComplianceState.pending,
statusLabel: 'In review',
fileName: 'utility-bill.pdf',
fileMeta: '380 KB - uploaded yesterday',
),
];
static List<ComplianceItem> certificates() => [
ComplianceItem(
id: 'c1',
title: 'Food handler certification',
subtitle: 'Accepted by all California venues',
state: ComplianceState.verified,
statusLabel: 'Validated',
fileName: 'food-safety-certificate.pdf',
fileMeta: '840 KB - uploaded 2 Aug',
expires: DateTime(2027, 3, 14),
),
ComplianceItem(
id: 'c2',
title: 'Responsible beverage service',
subtitle: 'Needed for bartender shifts',
state: ComplianceState.verified,
statusLabel: 'Validated',
fileName: 'rbs-certificate.pdf',
fileMeta: '510 KB - uploaded 2 Aug',
expires: DateTime(2028, 1, 9),
),
ComplianceItem(
id: 'c3',
title: 'CPR / AED',
subtitle: 'Adds around 4 shifts a week near you',
state: ComplianceState.missing,
statusLabel: 'Not added',
required_: false,
),
ComplianceItem(
id: 'c4',
title: 'Forklift licence',
subtitle: 'Warehouse and logistics roles',
state: ComplianceState.missing,
statusLabel: 'Not added',
required_: false,
),
];
static List<ComplianceItem> taxForms() => [
ComplianceItem(
id: 't1',
title: 'Form I-9',
subtitle: 'Employment eligibility verification',
state: ComplianceState.verified,
statusLabel: 'Approved',
fileName: 'i9-form.pdf',
fileMeta: 'Approved 3 Aug',
),
ComplianceItem(
id: 't2',
title: 'Form W-4',
subtitle: 'Sets how much tax is withheld',
state: ComplianceState.verified,
statusLabel: 'Approved',
fileName: 'w4-form.pdf',
fileMeta: 'Approved 3 Aug',
),
];
static List<ComplianceItem> wardrobe() => [
ComplianceItem(
id: 'w1',
title: 'Black pants',
subtitle: 'Solid black dress pants or slacks',
state: ComplianceState.verified,
statusLabel: 'Approved',
fileName: 'black-pants.jpg',
fileMeta: '1.4 MB - uploaded 2 Aug',
),
ComplianceItem(
id: 'w2',
title: 'Black shirt',
subtitle: 'Plain, no logos',
state: ComplianceState.verified,
statusLabel: 'Approved',
fileName: 'black-shirt.jpg',
fileMeta: '1.1 MB - uploaded 2 Aug',
),
ComplianceItem(
id: 'w3',
title: 'Non-slip black shoes',
subtitle: 'Closed-toe, required on every shift',
state: ComplianceState.verified,
statusLabel: 'Approved',
fileName: 'black-shoes.jpg',
fileMeta: '0.9 MB - uploaded 2 Aug',
),
ComplianceItem(
id: 'w4',
title: 'Black belt',
subtitle: 'Plain, simple buckle',
state: ComplianceState.missing,
statusLabel: 'Not added',
required_: false,
),
];
static const workSettings = <String>[
'Hospitality',
'Restaurant',
'Warehouse',
'Logistics',
'Events',
'Stadiums',
'Education',
'Healthcare & cafeteria',
'Convention centre',
'Catering',
];
static const skills = <String>[
'Food prep',
'Cooking',
'Grilling',
'Dishwashing',
'Food service',
'Banquet',
'Bartender',
'Barista',
'Customer service',
'Safe food handling',
'Event setup',
];
static const supportTopics = <String>[
'Shift issue',
'Pay or billing',
'Schedule clash',
'Account',
'Bug report',
'Feature idea',
];
static const faqs = <String, List<(String, String)>>{
'Getting started': [
(
'How do I finish my worker profile?',
'Open Profile, then Compliance. Work down the sections until every one '
'shows a green tick. You can accept shifts as soon as documents, '
'tax forms and attire are complete.',
),
(
"Why can't I apply to shifts yet?",
'Businesses only see workers who are fully compliant. Anything still '
'marked yellow on the compliance hub is blocking you.',
),
],
'Shifts and attendance': [
(
'How does clock-in work?',
'The clock-in button unlocks 30 minutes before your shift starts, once '
'you are within 150 m of the venue. Tap out when you leave and the '
'timecard submits itself.',
),
(
'What happens if I request a swap?',
'Your shift is offered to other qualified workers. You stay responsible '
'for it until someone accepts, so keep an eye on notifications.',
),
(
'What counts as a no-show?',
'Not clocking in within 30 minutes of the scheduled start, with no '
'cancellation. No-shows cost 15 points of trust index each.',
),
],
'Pay and compliance': [
(
'When do I actually get paid?',
'Semi-monthly. Each period closes on the 15th and the last day of the '
'month, and pays 11 days later.',
),
(
'How are documents verified?',
'A reviewer checks each upload by hand, usually within one business '
'day. You get a notification either way.',
),
],
};
}