import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import '../core/theme.dart'; import '../models/compliance.dart'; import '../state/compliance_controller.dart'; import '../state/shifts_controller.dart'; import '../widgets/common.dart'; import 'shift_detail_screen.dart'; /// Everything one business asks for, on its own screen. /// /// The shift page shows the same check inline; this is the full read, grouped /// the way the compliance hub groups things, so it is obvious *which* kind of /// item is missing and where to go and fix it. class RequirementsScreen extends ConsumerWidget { const RequirementsScreen({super.key, required this.shiftId}); final String shiftId; @override Widget build(BuildContext context, WidgetRef ref) { final shift = ref.watch(shiftsProvider.notifier).byId(shiftId); if (shift == null) { return Scaffold( appBar: AppBar(), body: const Center(child: Text('That shift is no longer listed.')), ); } final compliance = ref.watch(complianceProvider); /// The items this shift needs, split by which compliance section they /// belong to, so each group can be labelled and linked separately. List group(ComplianceSection section) => compliance .section(section) .where((i) => shift.requirements.contains(i.title)) .toList(); final groups = <(ComplianceSection, String, List)>[ ( ComplianceSection.documents, 'Documents', group(ComplianceSection.documents), ), (ComplianceSection.wardrobe, 'Attire', group(ComplianceSection.wardrobe)), ( ComplianceSection.certificates, 'Certificates', group(ComplianceSection.certificates), ), ]; return Scaffold( appBar: AppBar( title: const Text('Requirements'), actions: [ Padding( padding: const EdgeInsets.only(right: 16), child: Center( child: IconButton( onPressed: () => context.push('/support'), icon: const Icon(LucideIcons.messageCircle, size: 20), tooltip: 'Message the manager', ), ), ), ], ), body: ListView( padding: const EdgeInsets.fromLTRB(20, 8, 20, 28), children: [ Text( '${shift.role} at ${shift.business}', style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w700, letterSpacing: -0.7, ), ), const SizedBox(height: 16), // The same summary the shift page shows, so the two never disagree. ShiftRequirements(shift: shift), for (final (section, label, items) in groups) if (items.isNotEmpty) ...[ SectionLabel( label, trailing: TextButton( onPressed: () => context.push('/compliance/${section.name}'), child: const Text('Manage'), ), ), KrowCard( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ for (var i = 0; i < items.length; i++) ...[ if (i > 0) const Divider(height: 1), _RequirementRow(item: items[i]), ], ], ), ), ], const SizedBox(height: 16), const InfoBanner( 'These are shared with the business only while you are booked on ' 'one of their shifts.', ), ], ), ); } } class _RequirementRow extends StatelessWidget { const _RequirementRow({required this.item}); final ComplianceItem item; @override Widget build(BuildContext context) { final ok = item.state == ComplianceState.verified; return Padding( padding: const EdgeInsets.symmetric(vertical: 11), child: Row( children: [ Container( width: 22, height: 22, decoration: BoxDecoration( color: ok ? KrowPalette.blueTint : const Color(0xFFF7E4AE), borderRadius: BorderRadius.circular(7), ), child: Icon( ok ? LucideIcons.check : LucideIcons.clock, size: 12, color: ok ? KrowPalette.blue : KrowPalette.ink, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 1), Text( item.subtitle, style: const TextStyle( fontSize: 12, height: 1.4, color: KrowPalette.mute, ), ), ], ), ), const SizedBox(width: 8), StatusChip(item.badge, tone: ok ? ChipTone.neutral : ChipTone.yellow), ], ), ); } }