From 9038d6533e5bccd50a4937c80b8f841c640614d5 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Fri, 30 Jan 2026 16:49:10 -0500 Subject: [PATCH] feat: integrate ClockInPageLoaded event to initialize state on ClockInBloc --- .../src/presentation/bloc/clock_in_bloc.dart | 2 + .../src/presentation/pages/clock_in_page.dart | 801 +++++++++--------- 2 files changed, 405 insertions(+), 398 deletions(-) diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/bloc/clock_in_bloc.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/bloc/clock_in_bloc.dart index e934e636..551e8d32 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/bloc/clock_in_bloc.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/bloc/clock_in_bloc.dart @@ -33,6 +33,8 @@ class ClockInBloc extends Bloc { on(_onCheckIn); on(_onCheckOut); on(_onModeChanged); + + add(ClockInPageLoaded()); } AttendanceStatus _mapToStatus(Map map) { diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/pages/clock_in_page.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/pages/clock_in_page.dart index 1b0c42ee..f131f423 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/pages/clock_in_page.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/pages/clock_in_page.dart @@ -1,18 +1,19 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; -import 'package:lucide_icons/lucide_icons.dart'; import 'package:intl/intl.dart'; -import 'package:krow_domain/krow_domain.dart'; -import '../theme/app_colors.dart'; +import 'package:lucide_icons/lucide_icons.dart'; + import '../bloc/clock_in_bloc.dart'; import '../bloc/clock_in_event.dart'; import '../bloc/clock_in_state.dart'; +import '../theme/app_colors.dart'; import '../widgets/attendance_card.dart'; -import '../widgets/date_selector.dart'; -import '../widgets/swipe_to_check_in.dart'; -import '../widgets/lunch_break_modal.dart'; import '../widgets/commute_tracker.dart'; +import '../widgets/date_selector.dart'; +import '../widgets/lunch_break_modal.dart'; +import '../widgets/swipe_to_check_in.dart'; class ClockInPage extends StatefulWidget { const ClockInPage({super.key}); @@ -28,23 +29,24 @@ class _ClockInPageState extends State { void initState() { super.initState(); _bloc = Modular.get(); - _bloc.add(ClockInPageLoaded()); } @override Widget build(BuildContext context) { - return BlocProvider.value( + return BlocProvider.value( value: _bloc, child: BlocConsumer( listener: (context, state) { - if (state.status == ClockInStatus.failure && state.errorMessage != null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(state.errorMessage!)), - ); + if (state.status == ClockInStatus.failure && + state.errorMessage != null) { + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(state.errorMessage!))); } }, builder: (context, state) { - if (state.status == ClockInStatus.loading && state.todayShift == null) { + if (state.status == ClockInStatus.loading && + state.todayShift == null) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); @@ -64,416 +66,408 @@ class _ClockInPageState extends State { : '--:-- --'; return Scaffold( - backgroundColor: Colors.transparent, - body: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xFFF8FAFC), // slate-50 - Colors.white, - ], - ), + appBar: UiAppBar( + titleWidget: Text( + 'Clock In to your Shift', + style: UiTypography.title1m.textPrimary, ), - child: SafeArea( - child: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 100), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildHeader(), - - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - // Commute Tracker (shows before date selector when applicable) - if (todayShift != null) - CommuteTracker( - shift: todayShift, - hasLocationConsent: false, // Mock value - isCommuteModeOn: false, // Mock value - distanceMeters: 500, // Mock value for demo - etaMinutes: 8, // Mock value for demo - ), - // Date Selector - DateSelector( - selectedDate: state.selectedDate, - onSelect: (date) => _bloc.add(DateSelected(date)), - shiftDates: [ - DateFormat('yyyy-MM-dd').format(DateTime.now()), - ], + showBackButton: false, + centerTitle: false, + ), + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.only( + bottom: UiConstants.space24, + top: UiConstants.space6, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Commute Tracker (shows before date selector when applicable) + if (todayShift != null) + CommuteTracker( + shift: todayShift, + hasLocationConsent: false, // Mock value + isCommuteModeOn: false, // Mock value + distanceMeters: 500, // Mock value for demo + etaMinutes: 8, // Mock value for demo ), - const SizedBox(height: 20), + // Date Selector + DateSelector( + selectedDate: state.selectedDate, + onSelect: (date) => _bloc.add(DateSelected(date)), + shiftDates: [ + DateFormat('yyyy-MM-dd').format(DateTime.now()), + ], + ), + const SizedBox(height: 20), - // Today Attendance Section - const Align( - alignment: Alignment.centerLeft, - child: Text( - "Today Attendance", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), + // Today Attendance Section + const Align( + alignment: Alignment.centerLeft, + child: Text( + "Today Attendance", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColors.krowCharcoal, ), ), - const SizedBox(height: 12), - GridView.count( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - crossAxisCount: 2, - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.0, + ), + const SizedBox(height: 12), + GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: 2, + mainAxisSpacing: 12, + crossAxisSpacing: 12, + childAspectRatio: 1.0, + children: [ + AttendanceCard( + type: AttendanceType.checkin, + title: "Check In", + value: checkInStr, + subtitle: checkInTime != null + ? "On Time" + : "Pending", + scheduledTime: "09:00 AM", + ), + AttendanceCard( + type: AttendanceType.checkout, + title: "Check Out", + value: checkOutStr, + subtitle: checkOutTime != null + ? "Go Home" + : "Pending", + scheduledTime: "05:00 PM", + ), + AttendanceCard( + type: AttendanceType.breaks, + title: "Break Time", + // TODO: Connect to Data Connect when 'breakDuration' field is added to Shift schema. + value: "00:30 min", + subtitle: "Scheduled 00:30 min", + ), + const AttendanceCard( + type: AttendanceType.days, + title: "Total Days", + // TODO: Connect to Data Connect when 'staffStats' or similar aggregation API is available. + // Currently avoided to prevent fetching full shift history for a simple count. + value: "28", + subtitle: "Working Days", + ), + ], + ), + const SizedBox(height: 24), + + // Your Activity Header + const Text( + "Your Activity", + textAlign: TextAlign.start, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColors.krowCharcoal, + ), + ), + const SizedBox(height: 12), + + // Check-in Mode Toggle + const Align( + alignment: Alignment.centerLeft, + child: Text( + "Check-in Method", + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Color(0xFF334155), // slate-700 + ), + ), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: const Color(0xFFF1F5F9), // slate-100 + borderRadius: BorderRadius.circular(12), + ), + child: Row( children: [ - AttendanceCard( - type: AttendanceType.checkin, - title: "Check In", - value: checkInStr, - subtitle: checkInTime != null - ? "On Time" - : "Pending", - scheduledTime: "09:00 AM", - ), - AttendanceCard( - type: AttendanceType.checkout, - title: "Check Out", - value: checkOutStr, - subtitle: checkOutTime != null - ? "Go Home" - : "Pending", - scheduledTime: "05:00 PM", - ), - AttendanceCard( - type: AttendanceType.breaks, - title: "Break Time", - // TODO: Connect to Data Connect when 'breakDuration' field is added to Shift schema. - value: "00:30 min", - subtitle: "Scheduled 00:30 min", - ), - const AttendanceCard( - type: AttendanceType.days, - title: "Total Days", - // TODO: Connect to Data Connect when 'staffStats' or similar aggregation API is available. - // Currently avoided to prevent fetching full shift history for a simple count. - value: "28", - subtitle: "Working Days", + _buildModeTab( + "Swipe", + LucideIcons.mapPin, + 'swipe', + state.checkInMode, ), + // _buildModeTab("NFC Tap", LucideIcons.wifi, 'nfc', state.checkInMode), ], ), - const SizedBox(height: 24), + ), + const SizedBox(height: 16), - // Your Activity Header - // Your Activity Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Your Activity", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, + // Selected Shift Info Card + if (todayShift != null) + Container( + padding: const EdgeInsets.all(12), + margin: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: const Color(0xFFE2E8F0), + ), // slate-200 + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 2, + offset: const Offset(0, 1), ), - ), - GestureDetector( - onTap: () { - debugPrint('Navigating to shifts...'); - }, - child: Row( - children: const [ - Text( - "View all", + ], + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const Text( + "TODAY'S SHIFT", + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w600, + color: AppColors.krowBlue, + letterSpacing: 0.5, + ), + ), + const SizedBox(height: 2), + Text( + todayShift.title, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Color( + 0xFF1E293B, + ), // slate-800 + ), + ), + Text( + "${todayShift.clientName} • ${todayShift.location}", + style: const TextStyle( + fontSize: 12, + color: Color( + 0xFF64748B, + ), // slate-500 + ), + ), + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Text( + "9:00 AM - 5:00 PM", style: TextStyle( - color: AppColors.krowBlue, + fontSize: 12, fontWeight: FontWeight.w500, - fontSize: 14, + color: Color(0xFF475569), // slate-600 ), ), - SizedBox(width: 4), - Icon( - LucideIcons.chevronRight, - size: 16, - color: AppColors.krowBlue, + Text( + "\$${todayShift.hourlyRate}/hr", + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: AppColors.krowBlue, + ), ), ], ), - ), - ], - ), - const SizedBox(height: 12), - - // Check-in Mode Toggle - const Align( - alignment: Alignment.centerLeft, - child: Text( - "Check-in Method", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - _buildModeTab("Swipe", LucideIcons.mapPin, 'swipe', state.checkInMode), - // _buildModeTab("NFC Tap", LucideIcons.wifi, 'nfc', state.checkInMode), ], ), ), - const SizedBox(height: 16), - // Selected Shift Info Card - if (todayShift != null) - Container( - padding: const EdgeInsets.all(12), - margin: const EdgeInsets.only(bottom: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFE2E8F0), - ), // slate-200 - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "TODAY'S SHIFT", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: AppColors.krowBlue, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 2), - Text( - todayShift.title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF1E293B), // slate-800 - ), - ), - Text( - "${todayShift.clientName} • ${todayShift.location}", - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - const Text( - "9:00 AM - 5:00 PM", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), // slate-600 - ), - ), - Text( - "\$${todayShift.hourlyRate}/hr", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowBlue, - ), - ), - ], - ), - ], - ), - ), - - // Swipe To Check In / Checked Out State / No Shift State - if (todayShift != null && checkOutTime == null) ...[ - SwipeToCheckIn( - isCheckedIn: isCheckedIn, - mode: state.checkInMode, - isLoading: state.status == ClockInStatus.actionInProgress, - onCheckIn: () async { - // Show NFC dialog if mode is 'nfc' - if (state.checkInMode == 'nfc') { - await _showNFCDialog(context); - } else { - _bloc.add(CheckInRequested(shiftId: todayShift.id)); - } - }, - onCheckOut: () { - showDialog( - context: context, - builder: (context) => LunchBreakDialog( - onComplete: () { - Navigator.of(context).pop(); // Close dialog first - _bloc.add(const CheckOutRequested()); - }, - ), + // Swipe To Check In / Checked Out State / No Shift State + if (todayShift != null && checkOutTime == null) ...[ + SwipeToCheckIn( + isCheckedIn: isCheckedIn, + mode: state.checkInMode, + isLoading: + state.status == + ClockInStatus.actionInProgress, + onCheckIn: () async { + // Show NFC dialog if mode is 'nfc' + if (state.checkInMode == 'nfc') { + await _showNFCDialog(context); + } else { + _bloc.add( + CheckInRequested(shiftId: todayShift.id), ); - }, + } + }, + onCheckOut: () { + showDialog( + context: context, + builder: (context) => LunchBreakDialog( + onComplete: () { + Navigator.of( + context, + ).pop(); // Close dialog first + _bloc.add(const CheckOutRequested()); + }, + ), + ); + }, + ), + ] else if (todayShift != null && + checkOutTime != null) ...[ + // Shift Completed State + Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: const Color(0xFFECFDF5), // emerald-50 + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: const Color(0xFFA7F3D0), + ), // emerald-200 ), - ] else if (todayShift != null && checkOutTime != null) ...[ - // Shift Completed State - Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), // emerald-50 - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: const Color(0xFFA7F3D0), - ), // emerald-200 - ), - child: Column( - children: [ - Container( - width: 48, - height: 48, - decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), // emerald-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - color: Color(0xFF059669), // emerald-600 - size: 24, - ), + child: Column( + children: [ + Container( + width: 48, + height: 48, + decoration: const BoxDecoration( + color: Color(0xFFD1FAE5), // emerald-100 + shape: BoxShape.circle, ), - const SizedBox(height: 12), - const Text( - "Shift Completed!", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF065F46), // emerald-800 - ), + child: const Icon( + LucideIcons.check, + color: Color(0xFF059669), // emerald-600 + size: 24, ), - const SizedBox(height: 4), - const Text( - "Great work today", - style: TextStyle( - fontSize: 14, - color: Color(0xFF059669), // emerald-600 - ), + ), + const SizedBox(height: 12), + const Text( + "Shift Completed!", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color(0xFF065F46), // emerald-800 ), - ], - ), + ), + const SizedBox(height: 4), + const Text( + "Great work today", + style: TextStyle( + fontSize: 14, + color: Color(0xFF059669), // emerald-600 + ), + ), + ], ), - ] else ...[ - // No Shift State - Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - const Text( - "No confirmed shifts for today", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), // slate-600 - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 4), - const Text( - "Accept a shift to clock in", - style: TextStyle( - fontSize: 14, - color: Color(0xFF64748B), // slate-500 - ), - textAlign: TextAlign.center, - ), - ], - ), + ), + ] else ...[ + // No Shift State + Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: const Color(0xFFF1F5F9), // slate-100 + borderRadius: BorderRadius.circular(16), ), - ], + child: Column( + children: [ + const Text( + "No confirmed shifts for today", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Color(0xFF475569), // slate-600 + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 4), + const Text( + "Accept a shift to clock in", + style: TextStyle( + fontSize: 14, + color: Color(0xFF64748B), // slate-500 + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ], - // Checked In Banner - if (isCheckedIn && checkInTime != null) ...[ - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), // emerald-50 - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFA7F3D0), - ), // emerald-200 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Checked in at", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF059669), - ), + // Checked In Banner + if (isCheckedIn && checkInTime != null) ...[ + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xFFECFDF5), // emerald-50 + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: const Color(0xFFA7F3D0), + ), // emerald-200 + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const Text( + "Checked in at", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF059669), ), - Text( - DateFormat('h:mm a').format(checkInTime), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Color(0xFF065F46), - ), + ), + Text( + DateFormat( + 'h:mm a', + ).format(checkInTime), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Color(0xFF065F46), ), - ], - ), - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - color: Color(0xFF059669), ), + ], + ), + Container( + width: 40, + height: 40, + decoration: const BoxDecoration( + color: Color(0xFFD1FAE5), + shape: BoxShape.circle, ), - ], - ), + child: const Icon( + LucideIcons.check, + color: Color(0xFF059669), + ), + ), + ], ), - ], + ), + ], - const SizedBox(height: 16), + const SizedBox(height: 16), - // Recent Activity List - if (state.activityLog.isNotEmpty) ...state.activityLog.map( + // Recent Activity List + if (state.activityLog.isNotEmpty) + ...state.activityLog.map( (activity) => Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(12), @@ -490,7 +484,9 @@ class _ClockInPageState extends State { width: 40, height: 40, decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), + color: AppColors.krowBlue.withOpacity( + 0.1, + ), borderRadius: BorderRadius.circular(12), ), child: const Icon( @@ -502,23 +498,28 @@ class _ClockInPageState extends State { const SizedBox(width: 12), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( - DateFormat( - 'MMM d', - ).format(activity['date'] as DateTime), + DateFormat('MMM d').format( + activity['date'] as DateTime, + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Color(0xFF0F172A), // slate-900 + color: Color( + 0xFF0F172A, + ), // slate-900 ), ), Text( "${activity['start']} - ${activity['end']}", style: const TextStyle( fontSize: 12, - color: Color(0xFF64748B), // slate-500 + color: Color( + 0xFF64748B, + ), // slate-500 ), ), ], @@ -542,7 +543,6 @@ class _ClockInPageState extends State { ), ], ), - ), ), ), ); @@ -551,7 +551,12 @@ class _ClockInPageState extends State { ); } - Widget _buildModeTab(String label, IconData icon, String value, String currentMode) { + Widget _buildModeTab( + String label, + IconData icon, + String value, + String currentMode, + ) { final isSelected = currentMode == value; return Expanded( child: GestureDetector( @@ -678,7 +683,7 @@ class _ClockInPageState extends State { Future _showNFCDialog(BuildContext context) async { bool scanned = false; - + // Using a local navigator context since we are in a dialog await showDialog( context: context, @@ -771,11 +776,11 @@ class _ClockInPageState extends State { ); }, ); - + // After dialog closes, trigger the event if scan was successful (simulated) // In real app, we would check the dialog result if (scanned && _bloc.state.todayShift != null) { - _bloc.add(CheckInRequested(shiftId: _bloc.state.todayShift!.id)); + _bloc.add(CheckInRequested(shiftId: _bloc.state.todayShift!.id)); } } }