import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../models/compliance.dart'; import 'seed.dart'; /// The four compliance sections, each a list the worker can act on. enum ComplianceSection { documents, certificates, taxForms, wardrobe } extension ComplianceSectionX on ComplianceSection { String get title => switch (this) { ComplianceSection.documents => 'Documents', ComplianceSection.certificates => 'Certificates', ComplianceSection.taxForms => 'Tax forms', ComplianceSection.wardrobe => 'Attire', }; String get subtitle => switch (this) { ComplianceSection.documents => 'ID, SSN, work permit, address', ComplianceSection.certificates => 'Food handler, RBS and more', ComplianceSection.taxForms => 'Form I-9 and Form W-4', ComplianceSection.wardrobe => "Photos of what you'll wear", }; } class ComplianceData { const ComplianceData({ required this.documents, required this.certificates, required this.taxForms, required this.wardrobe, }); final List documents; final List certificates; final List taxForms; final List wardrobe; List section(ComplianceSection s) => switch (s) { ComplianceSection.documents => documents, ComplianceSection.certificates => certificates, ComplianceSection.taxForms => taxForms, ComplianceSection.wardrobe => wardrobe, }; List get all => [ ...documents, ...certificates, ...taxForms, ...wardrobe, ]; ComplianceData copyWith({ List? documents, List? certificates, List? taxForms, List? wardrobe, }) => ComplianceData( documents: documents ?? this.documents, certificates: certificates ?? this.certificates, taxForms: taxForms ?? this.taxForms, wardrobe: wardrobe ?? this.wardrobe, ); } class ComplianceController extends Notifier { @override ComplianceData build() => ComplianceData( documents: Seed.documents(), certificates: Seed.certificates(), taxForms: Seed.taxForms(), wardrobe: Seed.wardrobe(), ); List _apply( List list, String id, ComplianceItem Function(ComplianceItem) f, ) => [ for (final i in list) if (i.id == id) f(i) else i, ]; void _update( ComplianceSection section, String id, ComplianceItem Function(ComplianceItem) f, ) { final s = state; state = switch (section) { ComplianceSection.documents => s.copyWith( documents: _apply(s.documents, id, f), ), ComplianceSection.certificates => s.copyWith( certificates: _apply(s.certificates, id, f), ), ComplianceSection.taxForms => s.copyWith( taxForms: _apply(s.taxForms, id, f), ), ComplianceSection.wardrobe => s.copyWith( wardrobe: _apply(s.wardrobe, id, f), ), }; } /// Stand-in for the camera / file picker: attaching a file sends the item /// back for review. void uploadFile(ComplianceSection section, String id, String fileName) { _update( section, id, (i) => i.copyWith( state: ComplianceState.pending, statusLabel: 'In review', fileName: fileName, fileMeta: 'Uploaded just now', ), ); } void removeFile(ComplianceSection section, String id) { _update( section, id, (i) => ComplianceItem( id: i.id, title: i.title, subtitle: i.subtitle, state: ComplianceState.missing, statusLabel: 'Not added', required_: i.required_, ), ); } void setExpiry(ComplianceSection section, String id, DateTime date) { _update(section, id, (i) => i.copyWith(expires: date)); } ComplianceItem? find(ComplianceSection section, String id) { for (final i in state.section(section)) { if (i.id == id) return i; } return null; } } final complianceProvider = NotifierProvider( ComplianceController.new, ); /// `(verified, total)` across every required item — what the hub reports. final complianceProgressProvider = Provider<(int, int)>((ref) { final items = ref.watch(complianceProvider).all.where((i) => i.required_); final total = items.length; final done = items.where((i) => i.state == ComplianceState.verified).length; return (done, total); }); /// Whether the worker is cleared to take shifts at all. final isCompliantProvider = Provider((ref) { final (done, total) = ref.watch(complianceProgressProvider); return done == total; }); final sectionProgressProvider = Provider.family<(int, int), ComplianceSection>(( ref, section, ) { final items = ref .watch(complianceProvider) .section(section) .where((i) => i.required_); return ( items.where((i) => i.state == ComplianceState.verified).length, items.length, ); });