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 adfa9cf8..29df8a28 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 @@ -9,7 +9,6 @@ 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/commute_tracker.dart'; import '../widgets/date_selector.dart'; import '../widgets/lunch_break_modal.dart'; @@ -39,9 +38,11 @@ class _ClockInPageState extends State { listener: (BuildContext context, ClockInState state) { if (state.status == ClockInStatus.failure && state.errorMessage != null) { - ScaffoldMessenger.of( + UiSnackbar.show( context, - ).showSnackBar(SnackBar(content: Text(state.errorMessage!))); + message: state.errorMessage!, + type: UiSnackbarType.error, + ); } }, builder: (BuildContext context, ClockInState state) { @@ -110,14 +111,10 @@ class _ClockInPageState extends State { const SizedBox(height: 20), // Your Activity Header - const Text( + Text( "Your Activity", textAlign: TextAlign.start, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), + style: UiTypography.headline4m, ), const SizedBox(height: 16), @@ -135,15 +132,15 @@ class _ClockInPageState extends State { margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( - color: Colors.white, + color: UiColors.white, borderRadius: BorderRadius.circular( 12, ), border: Border.all( color: shift.id == selectedShift?.id - ? AppColors.krowBlue - : const Color(0xFFE2E8F0), + ? UiColors.primary + : UiColors.border, width: shift.id == selectedShift?.id ? 2 @@ -164,34 +161,25 @@ class _ClockInPageState extends State { selectedShift?.id ? "SELECTED SHIFT" : "TODAY'S SHIFT", - style: TextStyle( - fontSize: 10, - fontWeight: - FontWeight.w600, + style: UiTypography + .titleUppercase4b + .copyWith( color: shift.id == selectedShift?.id - ? AppColors.krowBlue - : AppColors - .krowCharcoal, - letterSpacing: 0.5, + ? UiColors.primary + : UiColors + .textSecondary, ), ), const SizedBox(height: 2), Text( shift.title, - style: const TextStyle( - fontSize: 14, - fontWeight: - FontWeight.w600, - color: Color(0xFF1E293B), - ), + style: UiTypography.body2b, ), Text( "${shift.clientName} • ${shift.location}", - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), + style: UiTypography.body3r + .textSecondary, ), ], ), @@ -202,18 +190,14 @@ class _ClockInPageState extends State { children: [ Text( "${_formatTime(shift.startTime)} - ${_formatTime(shift.endTime)}", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), - ), + style: UiTypography.body3m + .textSecondary, ), Text( "\$${shift.hourlyRate}/hr", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowBlue, + style: UiTypography.body3m + .copyWith( + color: UiColors.primary, ), ), ], @@ -234,7 +218,7 @@ class _ClockInPageState extends State { width: double.infinity, padding: const EdgeInsets.all(24), decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 + color: UiColors.bgSecondary, borderRadius: BorderRadius.circular(16), ), child: Column( @@ -242,24 +226,17 @@ class _ClockInPageState extends State { const Icon( LucideIcons.clock, size: 48, - color: Color(0xFF94A3B8), // slate-400 + color: UiColors.iconThird, ), const SizedBox(height: 16), - const Text( + Text( "You're early!", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF475569), // slate-600 - ), + style: UiTypography.body1m.textSecondary, ), const SizedBox(height: 4), Text( "Check-in available at ${_getCheckInAvailabilityTime(selectedShift)}", - style: const TextStyle( - fontSize: 14, - color: Color(0xFF64748B), // slate-500 - ), + style: UiTypography.body2r.textSecondary, textAlign: TextAlign.center, ), ], @@ -304,11 +281,11 @@ class _ClockInPageState extends State { Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( - color: const Color(0xFFECFDF5), // emerald-50 + color: UiColors.tagSuccess, borderRadius: BorderRadius.circular(16), border: Border.all( - color: const Color(0xFFA7F3D0), - ), // emerald-200 + color: UiColors.success.withValues(alpha: 0.3), + ), ), child: Column( children: [ @@ -316,31 +293,24 @@ class _ClockInPageState extends State { width: 48, height: 48, decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), // emerald-100 + color: UiColors.tagActive, shape: BoxShape.circle, ), child: const Icon( LucideIcons.check, - color: Color(0xFF059669), // emerald-600 + color: UiColors.textSuccess, size: 24, ), ), const SizedBox(height: 12), - const Text( + Text( "Shift Completed!", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF065F46), // emerald-800 - ), + style: UiTypography.body1b.textSuccess, ), const SizedBox(height: 4), - const Text( + Text( "Great work today", - style: TextStyle( - fontSize: 14, - color: Color(0xFF059669), // emerald-600 - ), + style: UiTypography.body2r.textSuccess, ), ], ), @@ -351,27 +321,20 @@ class _ClockInPageState extends State { width: double.infinity, padding: const EdgeInsets.all(24), decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 + color: UiColors.bgSecondary, borderRadius: BorderRadius.circular(16), ), - child: const Column( + child: Column( children: [ Text( "No confirmed shifts for today", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), // slate-600 - ), + style: UiTypography.body1m.textSecondary, textAlign: TextAlign.center, ), - SizedBox(height: 4), + const SizedBox(height: 4), Text( "Accept a shift to clock in", - style: TextStyle( - fontSize: 14, - color: Color(0xFF64748B), // slate-500 - ), + style: UiTypography.body2r.textSecondary, textAlign: TextAlign.center, ), ], @@ -385,11 +348,11 @@ class _ClockInPageState extends State { Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: const Color(0xFFECFDF5), // emerald-50 + color: UiColors.tagSuccess, borderRadius: BorderRadius.circular(12), border: Border.all( - color: const Color(0xFFA7F3D0), - ), // emerald-200 + color: UiColors.success.withValues(alpha: 0.3), + ), ), child: Row( mainAxisAlignment: @@ -399,23 +362,15 @@ class _ClockInPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( "Checked in at", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF059669), - ), + style: UiTypography.body3m.textSuccess, ), Text( DateFormat( 'h:mm a', ).format(checkInTime), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Color(0xFF065F46), - ), + style: UiTypography.body1b.textSuccess, ), ], ), @@ -423,12 +378,12 @@ class _ClockInPageState extends State { width: 40, height: 40, decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), + color: UiColors.tagActive, shape: BoxShape.circle, ), child: const Icon( LucideIcons.check, - color: Color(0xFF059669), + color: UiColors.textSuccess, ), ), ], @@ -466,12 +421,12 @@ class _ClockInPageState extends State { child: Container( padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( - color: isSelected ? Colors.white : Colors.transparent, + color: isSelected ? UiColors.white : UiColors.transparent, borderRadius: BorderRadius.circular(8), boxShadow: isSelected ? [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: UiColors.black.withValues(alpha: 0.05), blurRadius: 2, offset: const Offset(0, 1), ), @@ -484,15 +439,15 @@ class _ClockInPageState extends State { Icon( icon, size: 16, - color: isSelected ? Colors.black : Colors.grey, + color: isSelected ? UiColors.foreground : UiColors.iconThird, ), const SizedBox(width: 6), Text( label, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isSelected ? Colors.black : Colors.grey, + style: UiTypography.body2m.copyWith( + color: isSelected + ? UiColors.foreground + : UiColors.textSecondary, ), ), ], @@ -521,26 +476,19 @@ class _ClockInPageState extends State { width: 96, height: 96, decoration: BoxDecoration( - color: scanned - ? Colors.green.shade50 - : Colors.blue.shade50, + color: scanned ? UiColors.tagSuccess : UiColors.tagInProgress, shape: BoxShape.circle, ), child: Icon( scanned ? LucideIcons.check : LucideIcons.nfc, size: 48, - color: scanned - ? Colors.green.shade600 - : Colors.blue.shade600, + color: scanned ? UiColors.textSuccess : UiColors.primary, ), ), const SizedBox(height: 24), Text( scanned ? 'Processing check-in...' : 'Ready to scan', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - ), + style: UiTypography.headline4m, ), const SizedBox(height: 8), Text( @@ -548,7 +496,7 @@ class _ClockInPageState extends State { ? 'Please wait...' : 'Hold your phone near the NFC tag at the clock-in station', textAlign: TextAlign.center, - style: TextStyle(fontSize: 14, color: Colors.grey.shade600), + style: UiTypography.body2r.textSecondary, ), if (!scanned) ...[ const SizedBox(height: 24), @@ -573,16 +521,13 @@ class _ClockInPageState extends State { // It's safer to just return a result }, icon: const Icon(LucideIcons.nfc, size: 24), - label: const Text( + label: Text( 'Tap to Scan', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - ), + style: UiTypography.headline4m.white, ), style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, + backgroundColor: UiColors.primary, + foregroundColor: UiColors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/theme/app_colors.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/theme/app_colors.dart deleted file mode 100644 index a41fe11f..00000000 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/theme/app_colors.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter/material.dart'; - -class AppColors { - static const Color krowBlue = Color(0xFF0A39DF); - static const Color krowYellow = Color(0xFFFFED4A); - static const Color krowCharcoal = Color(0xFF121826); - static const Color krowMuted = Color(0xFF6A7382); - static const Color krowBorder = Color(0xFFE3E6E9); - static const Color krowBackground = Color(0xFFFAFBFC); - - static const Color white = Colors.white; - static const Color black = Colors.black; -} diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/attendance_card.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/attendance_card.dart index 9f5f07dd..adc955bb 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/attendance_card.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/attendance_card.dart @@ -1,10 +1,10 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:lucide_icons/lucide_icons.dart'; enum AttendanceType { checkin, checkout, breaks, days } class AttendanceCard extends StatelessWidget { - const AttendanceCard({ super.key, required this.type, @@ -26,12 +26,12 @@ class AttendanceCard extends StatelessWidget { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.white, + color: UiColors.white, borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), + border: Border.all(color: UiColors.bgSecondary), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: UiColors.black.withValues(alpha: 0.05), blurRadius: 2, offset: const Offset(0, 1), ), @@ -53,10 +53,7 @@ class AttendanceCard extends StatelessWidget { const SizedBox(height: 8), Text( title, - style: const TextStyle( - fontSize: 11, - color: Color(0xFF64748B), // slate-500 - ), + style: UiTypography.titleUppercase4m.textSecondary, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -65,27 +62,20 @@ class AttendanceCard extends StatelessWidget { fit: BoxFit.scaleDown, child: Text( value, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), + style: UiTypography.headline4m, ), ), if (scheduledTime != null) ...[ const SizedBox(height: 2), Text( "Scheduled: $scheduledTime", - style: const TextStyle( - fontSize: 10, - color: Color(0xFF94A3B8), // slate-400 - ), + style: UiTypography.footnote2r.textInactive, ), ], const SizedBox(height: 2), Text( subtitle, - style: const TextStyle(fontSize: 12, color: Color(0xFF0032A0)), + style: UiTypography.footnote1r.copyWith(color: UiColors.primary), ), ], ), @@ -97,26 +87,26 @@ class AttendanceCard extends StatelessWidget { case AttendanceType.checkin: return _AttendanceStyle( icon: LucideIcons.logIn, - bgColor: const Color(0xFF0032A0).withOpacity(0.1), - iconColor: const Color(0xFF0032A0), + bgColor: UiColors.primary.withValues(alpha: 0.1), + iconColor: UiColors.primary, ); case AttendanceType.checkout: return _AttendanceStyle( icon: LucideIcons.logOut, - bgColor: const Color(0xFF333F48).withOpacity(0.1), - iconColor: const Color(0xFF333F48), + bgColor: UiColors.foreground.withValues(alpha: 0.1), + iconColor: UiColors.foreground, ); case AttendanceType.breaks: return _AttendanceStyle( icon: LucideIcons.coffee, - bgColor: const Color(0xFFF9E547).withOpacity(0.2), - iconColor: const Color(0xFF4C460D), + bgColor: UiColors.accent.withValues(alpha: 0.2), + iconColor: UiColors.accentForeground, ); case AttendanceType.days: return _AttendanceStyle( icon: LucideIcons.calendar, - bgColor: Colors.green.withOpacity(0.1), - iconColor: Colors.green, + bgColor: UiColors.success.withValues(alpha: 0.1), + iconColor: UiColors.textSuccess, ); } } diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/commute_tracker.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/commute_tracker.dart index 8f3726eb..65474125 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/commute_tracker.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/commute_tracker.dart @@ -1,7 +1,7 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../theme/app_colors.dart'; import 'package:krow_domain/krow_domain.dart'; +import 'package:lucide_icons/lucide_icons.dart'; enum CommuteMode { lockedNoShift, @@ -161,18 +161,18 @@ class _CommuteTrackerState extends State { margin: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.all(12), decoration: BoxDecoration( - gradient: const LinearGradient( + gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - Color(0xFFEFF6FF), // blue-50 - Color(0xFFECFEFF), // cyan-50 + UiColors.primary.withValues(alpha: 0.05), + UiColors.primary.withValues(alpha: 0.1), ], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: UiColors.black.withValues(alpha: 0.05), blurRadius: 2, offset: const Offset(0, 1), ), @@ -188,35 +188,28 @@ class _CommuteTrackerState extends State { width: 32, height: 32, decoration: const BoxDecoration( - color: Color(0xFF2563EB), // blue-600 + color: UiColors.primary, shape: BoxShape.circle, ), child: const Icon( LucideIcons.mapPin, size: 16, - color: Colors.white, + color: UiColors.white, ), ), const SizedBox(width: 12), - const Expanded( + Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Enable Commute Tracking?', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), + style: UiTypography.body2m.textPrimary, ), - SizedBox(height: 4), + const SizedBox(height: 4), Text( 'Share location 1hr before shift so your manager can see you\'re on the way.', - style: TextStyle( - fontSize: 12, - color: Color(0xFF475569), // slate-600 - ), + style: UiTypography.body4r.textSecondary, ), ], ), @@ -233,9 +226,9 @@ class _CommuteTrackerState extends State { }, style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 8), - side: const BorderSide(color: Color(0xFFE2E8F0)), + side: const BorderSide(color: UiColors.border), ), - child: const Text('Not Now', style: TextStyle(fontSize: 12)), + child: Text('Not Now', style: UiTypography.footnote1m), ), ), const SizedBox(width: 8), @@ -245,12 +238,12 @@ class _CommuteTrackerState extends State { setState(() => _localHasConsent = true); }, style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF2563EB), // blue-600 + backgroundColor: UiColors.primary, padding: const EdgeInsets.symmetric(vertical: 8), ), - child: const Text( + child: Text( 'Enable', - style: TextStyle(fontSize: 12, color: Colors.white), + style: UiTypography.footnote1m.white, ), ), ), @@ -266,11 +259,11 @@ class _CommuteTrackerState extends State { margin: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.white, + color: UiColors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.05), + color: UiColors.black.withValues(alpha: 0.05), blurRadius: 2, offset: const Offset(0, 1), ), @@ -282,13 +275,13 @@ class _CommuteTrackerState extends State { width: 32, height: 32, decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), // slate-100 + color: UiColors.bgSecondary, shape: BoxShape.circle, ), child: const Icon( LucideIcons.navigation, size: 16, - color: Color(0xFF475569), // slate-600 + color: UiColors.textSecondary, ), ), const SizedBox(width: 8), @@ -298,13 +291,9 @@ class _CommuteTrackerState extends State { children: [ Row( children: [ - const Text( + Text( 'On My Way', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), + style: UiTypography.body2m.textPrimary, ), const SizedBox(width: 8), Row( @@ -312,26 +301,20 @@ class _CommuteTrackerState extends State { const Icon( LucideIcons.clock, size: 12, - color: Color(0xFF64748B), // slate-500 + color: UiColors.textInactive, ), const SizedBox(width: 2), Text( 'Shift starts in ${_getMinutesUntilShift()} min', - style: const TextStyle( - fontSize: 11, - color: Color(0xFF64748B), // slate-500 - ), + style: UiTypography.titleUppercase4m.textSecondary, ), ], ), ], ), - const Text( + Text( 'Track arrival', - style: TextStyle( - fontSize: 10, - color: Color(0xFF64748B), // slate-500 - ), + style: UiTypography.titleUppercase4m.textSecondary, ), ], ), @@ -342,7 +325,7 @@ class _CommuteTrackerState extends State { setState(() => _localIsCommuteOn = value); widget.onCommuteToggled?.call(value); }, - activeThumbColor: AppColors.krowBlue, + activeThumbColor: UiColors.primary, ), ], ), @@ -357,8 +340,8 @@ class _CommuteTrackerState extends State { begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - Color(0xFF2563EB), // blue-600 - Color(0xFF0891B2), // cyan-600 + UiColors.primary, + UiColors.iconActive, ], ), ), @@ -383,13 +366,13 @@ class _CommuteTrackerState extends State { width: 96, height: 96, decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), + color: UiColors.white.withValues(alpha: 0.2), shape: BoxShape.circle, ), child: const Icon( LucideIcons.navigation, size: 48, - color: Colors.white, + color: UiColors.white, ), ), ); @@ -400,20 +383,15 @@ class _CommuteTrackerState extends State { }, ), const SizedBox(height: 24), - const Text( + Text( 'On My Way', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + style: UiTypography.displayMb.white, ), const SizedBox(height: 8), Text( 'Your manager can see you\'re heading to the site', - style: TextStyle( - fontSize: 14, - color: Colors.blue.shade100, + style: UiTypography.body2r.copyWith( + color: UiColors.primaryForeground.withValues(alpha: 0.8), ), textAlign: TextAlign.center, ), @@ -424,29 +402,24 @@ class _CommuteTrackerState extends State { constraints: const BoxConstraints(maxWidth: 300), padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), + color: UiColors.white.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(16), border: Border.all( - color: Colors.white.withOpacity(0.2), + color: UiColors.white.withValues(alpha: 0.2), ), ), child: Column( children: [ Text( 'Distance to Site', - style: TextStyle( - fontSize: 14, - color: Colors.blue.shade100, + style: UiTypography.body2r.copyWith( + color: UiColors.primaryForeground.withValues(alpha: 0.8), ), ), const SizedBox(height: 4), Text( _formatDistance(widget.distanceMeters!), - style: const TextStyle( - fontSize: 36, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + style: UiTypography.displayM.white, ), ], ), @@ -458,29 +431,24 @@ class _CommuteTrackerState extends State { constraints: const BoxConstraints(maxWidth: 300), padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), + color: UiColors.white.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(16), border: Border.all( - color: Colors.white.withOpacity(0.2), + color: UiColors.white.withValues(alpha: 0.2), ), ), child: Column( children: [ Text( 'Estimated Arrival', - style: TextStyle( - fontSize: 14, - color: Colors.blue.shade100, + style: UiTypography.body2r.copyWith( + color: UiColors.primaryForeground.withValues(alpha: 0.8), ), ), const SizedBox(height: 4), Text( '${widget.etaMinutes} min', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + style: UiTypography.headline1m.white, ), ], ), @@ -490,9 +458,8 @@ class _CommuteTrackerState extends State { const SizedBox(height: 32), Text( 'Most app features are locked while commute mode is on. You\'ll be able to clock in once you arrive.', - style: TextStyle( - fontSize: 12, - color: Colors.blue.shade100, + style: UiTypography.footnote1r.copyWith( + color: UiColors.primaryForeground.withValues(alpha: 0.8), ), textAlign: TextAlign.center, ), @@ -508,12 +475,12 @@ class _CommuteTrackerState extends State { setState(() => _localIsCommuteOn = false); }, style: OutlinedButton.styleFrom( - foregroundColor: Colors.white, - side: BorderSide(color: Colors.white.withOpacity(0.3)), + foregroundColor: UiColors.white, + side: BorderSide(color: UiColors.white.withValues(alpha: 0.3)), padding: const EdgeInsets.symmetric(vertical: 16), minimumSize: const Size(double.infinity, 48), ), - child: const Text('Turn Off Commute Mode'), + child: Text('Turn Off Commute Mode', style: UiTypography.buttonL), ), ), ], @@ -527,18 +494,18 @@ class _CommuteTrackerState extends State { margin: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.all(20), decoration: BoxDecoration( - gradient: const LinearGradient( + gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - Color(0xFFECFDF5), // emerald-50 - Color(0xFFD1FAE5), // green-50 + UiColors.tagSuccess, + UiColors.tagActive, ], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: UiColors.black.withValues(alpha: 0.1), blurRadius: 8, offset: const Offset(0, 2), ), @@ -550,31 +517,24 @@ class _CommuteTrackerState extends State { width: 64, height: 64, decoration: const BoxDecoration( - color: Color(0xFF10B981), // emerald-500 + color: UiColors.success, shape: BoxShape.circle, ), child: const Icon( LucideIcons.checkCircle, size: 32, - color: Colors.white, + color: UiColors.white, ), ), const SizedBox(height: 16), - const Text( + Text( 'You\'ve Arrived! 🎉', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), + style: UiTypography.headline3m.textPrimary, ), const SizedBox(height: 8), - const Text( + Text( 'You\'re at the shift location. Ready to clock in?', - style: TextStyle( - fontSize: 14, - color: Color(0xFF475569), // slate-600 - ), + style: UiTypography.body2r.textSecondary, textAlign: TextAlign.center, ), ], diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/date_selector.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/date_selector.dart index 3b732041..1e39eecf 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/date_selector.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/date_selector.dart @@ -1,8 +1,8 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class DateSelector extends StatelessWidget { - const DateSelector({ super.key, required this.selectedDate, @@ -36,12 +36,12 @@ class DateSelector extends StatelessWidget { duration: const Duration(milliseconds: 200), margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( - color: isSelected ? const Color(0xFF0032A0) : Colors.white, + color: isSelected ? UiColors.primary : UiColors.white, borderRadius: BorderRadius.circular(16), boxShadow: isSelected ? [ BoxShadow( - color: const Color(0xFF0032A0).withOpacity(0.3), + color: UiColors.primary.withValues(alpha: 0.3), blurRadius: 10, offset: const Offset(0, 4), ), @@ -53,22 +53,18 @@ class DateSelector extends StatelessWidget { children: [ Text( DateFormat('d').format(date), - style: TextStyle( - fontSize: 18, + style: UiTypography.title1m.copyWith( fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : const Color(0xFF0F172A), + color: isSelected ? UiColors.white : UiColors.foreground, ), ), const SizedBox(height: 2), Text( DateFormat('E').format(date), - style: TextStyle( - fontSize: 12, + style: UiTypography.footnote2r.copyWith( color: isSelected - ? Colors.white.withOpacity(0.8) - : const Color(0xFF94A3B8), + ? UiColors.white.withValues(alpha: 0.8) + : UiColors.textInactive, ), ), const SizedBox(height: 4), @@ -77,9 +73,7 @@ class DateSelector extends StatelessWidget { width: 6, height: 6, decoration: BoxDecoration( - color: isSelected - ? Colors.white - : const Color(0xFF0032A0), + color: isSelected ? UiColors.white : UiColors.primary, shape: BoxShape.circle, ), ) @@ -87,8 +81,8 @@ class DateSelector extends StatelessWidget { Container( width: 6, height: 6, - decoration: BoxDecoration( - color: Colors.grey.shade300, + decoration: const BoxDecoration( + color: UiColors.border, shape: BoxShape.circle, ), ) diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/location_map_placeholder.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/location_map_placeholder.dart index 9f3d594d..4ce26d6d 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/location_map_placeholder.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/location_map_placeholder.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; import 'package:lucide_icons/lucide_icons.dart'; class LocationMapPlaceholder extends StatelessWidget { @@ -18,7 +18,7 @@ class LocationMapPlaceholder extends StatelessWidget { height: 200, width: double.infinity, decoration: BoxDecoration( - color: const Color(0xFFE2E8F0), + color: UiColors.border, borderRadius: BorderRadius.circular(16), image: DecorationImage( image: const NetworkImage( @@ -33,17 +33,18 @@ class LocationMapPlaceholder extends StatelessWidget { child: Stack( children: [ // Fallback UI if image fails (which it will without key) - const Center( + Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(LucideIcons.mapPin, size: 48, color: UiColors.iconSecondary), - SizedBox(height: 8), - Text('Map View (GPS)', style: TextStyle(color: UiColors.textSecondary)), + const Icon(LucideIcons.mapPin, + size: 48, color: UiColors.iconSecondary), + const SizedBox(height: 8), + Text('Map View (GPS)', style: UiTypography.body2r.textSecondary), ], ), ), - + // Status Overlay Positioned( bottom: 16, @@ -52,11 +53,11 @@ class LocationMapPlaceholder extends StatelessWidget { child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( - color: Colors.white, + color: UiColors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: UiColors.black.withValues(alpha: 0.1), blurRadius: 8, offset: const Offset(0, 4), ), @@ -65,8 +66,12 @@ class LocationMapPlaceholder extends StatelessWidget { child: Row( children: [ Icon( - isVerified ? LucideIcons.checkCircle : LucideIcons.alertCircle, - color: isVerified ? UiColors.textSuccess : UiColors.destructive, + isVerified + ? LucideIcons.checkCircle + : LucideIcons.alertCircle, + color: isVerified + ? UiColors.textSuccess + : UiColors.destructive, size: 20, ), const SizedBox(width: 12), @@ -76,12 +81,12 @@ class LocationMapPlaceholder extends StatelessWidget { children: [ Text( isVerified ? 'Location Verified' : 'Location Check', - style: UiTypography.body1b.copyWith(color: UiColors.textPrimary), + style: UiTypography.body1b.textPrimary, ), if (distance != null) Text( '${distance!.toStringAsFixed(0)}m from venue', - style: UiTypography.body2r.copyWith(color: UiColors.textSecondary), + style: UiTypography.body2r.textSecondary, ), ], ), diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/lunch_break_modal.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/lunch_break_modal.dart index f095f6a4..524cad92 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/lunch_break_modal.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/lunch_break_modal.dart @@ -1,8 +1,8 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:lucide_icons/lucide_icons.dart'; class LunchBreakDialog extends StatefulWidget { - const LunchBreakDialog({super.key, required this.onComplete}); final VoidCallback onComplete; @@ -47,7 +47,7 @@ class _LunchBreakDialogState extends State { @override Widget build(BuildContext context) { return Dialog( - backgroundColor: Colors.white, + backgroundColor: UiColors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), child: AnimatedSwitcher( duration: const Duration(milliseconds: 300), @@ -82,25 +82,21 @@ class _LunchBreakDialogState extends State { Container( width: 80, height: 80, - decoration: BoxDecoration( - color: Colors.grey.shade100, + decoration: const BoxDecoration( + color: UiColors.bgSecondary, shape: BoxShape.circle, ), child: const Icon( LucideIcons.coffee, size: 40, - color: Color(0xFF6A7382), + color: UiColors.iconSecondary, ), ), const SizedBox(height: 24), - const Text( + Text( "Did You Take\na Lunch?", textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), + style: UiTypography.headline1m.textPrimary, ), const SizedBox(height: 24), Row( @@ -116,18 +112,14 @@ class _LunchBreakDialogState extends State { child: Container( padding: const EdgeInsets.symmetric(vertical: 16), decoration: BoxDecoration( - border: Border.all(color: Colors.grey.shade300), + border: Border.all(color: UiColors.border), borderRadius: BorderRadius.circular(12), - color: Colors.transparent, + color: UiColors.transparent, ), alignment: Alignment.center, - child: const Text( + child: Text( "No", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF121826), - ), + style: UiTypography.body1m.textPrimary, ), ), ), @@ -142,19 +134,15 @@ class _LunchBreakDialogState extends State { }); }, style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), + backgroundColor: UiColors.primary, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), - child: const Text( + child: Text( "Yes", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - ), + style: UiTypography.body1m.white, ), ), ), @@ -172,76 +160,51 @@ class _LunchBreakDialogState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - const Text( + Text( "When did you take lunch?", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + style: UiTypography.headline4m, ), - const SizedBox(height: 24), - // Mock Inputs - Row( - children: [ - Expanded( - child: DropdownButtonFormField( - isExpanded: true, - initialValue: _breakStart, - items: _timeOptions.map((String t) => DropdownMenuItem(value: t, child: Text(t, style: const TextStyle(fontSize: 13)))).toList(), - onChanged: (String? v) => setState(() => _breakStart = v), - decoration: const InputDecoration( - labelText: 'Start', - contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), - ), - ), - ), - const SizedBox(width: 10), - Expanded( - child: DropdownButtonFormField( - isExpanded: true, - initialValue: _breakEnd, - items: _timeOptions.map((String t) => DropdownMenuItem(value: t, child: Text(t, style: const TextStyle(fontSize: 13)))).toList(), - onChanged: (String? v) => setState(() => _breakEnd = v), - decoration: const InputDecoration( - labelText: 'End', - contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), - ), - ), - ), - ], - ), - const SizedBox(height: 24), - ElevatedButton( - onPressed: () { - setState(() => _step = 3); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), - minimumSize: const Size(double.infinity, 48), + // Mock Inputs + Row( + children: [ + Expanded( + child: DropdownButtonFormField( + isExpanded: true, + value: _breakStart, + items: _timeOptions + .map((String t) => DropdownMenuItem( + value: t, + child: Text(t, style: UiTypography.body3r))) + .toList(), + onChanged: (String? v) => setState(() => _breakStart = v), + decoration: const InputDecoration( + labelText: 'Start', + contentPadding: + EdgeInsets.symmetric(horizontal: 10, vertical: 8), + ), + ), ), - child: const Text("Next", style: TextStyle(color: Colors.white)), + const SizedBox(width: 10), + Expanded( + child: DropdownButtonFormField( + isExpanded: true, + value: _breakEnd, + items: _timeOptions + .map((String t) => DropdownMenuItem( + value: t, + child: Text(t, style: UiTypography.body3r))) + .toList(), + onChanged: (String? v) => setState(() => _breakEnd = v), + decoration: const InputDecoration( + labelText: 'End', + contentPadding: + EdgeInsets.symmetric(horizontal: 10, vertical: 8), + ), + ), + ), + ], ), - ], - )); - } - - Widget _buildStep2b() { - // No lunch reason - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Text( - "Why didn't you take lunch?", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - ..._noLunchReasons.map((String reason) => RadioListTile( - title: Text(reason), - value: reason, - groupValue: _noLunchReason, - onChanged: (String? val) => setState(() => _noLunchReason = val), - )), const SizedBox(height: 24), ElevatedButton( @@ -249,10 +212,47 @@ class _LunchBreakDialogState extends State { setState(() => _step = 3); }, style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), - minimumSize: const Size(double.infinity, 48), - ), - child: const Text("Next", style: TextStyle(color: Colors.white)), + backgroundColor: UiColors.primary, + minimumSize: const Size(double.infinity, 48), + ), + child: Text("Next", style: UiTypography.body1m.white), + ), + ], + )); + } + + Widget _buildStep2b() { + // No lunch reason + return Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Why didn't you take lunch?", + style: UiTypography.headline4m, + ), + const SizedBox(height: 16), + ..._noLunchReasons.map((String reason) => RadioListTile( + title: Text(reason, style: UiTypography.body2r), + value: reason, + groupValue: _noLunchReason, + onChanged: (String? val) => + setState(() => _noLunchReason = val), + activeColor: UiColors.primary, + )), + + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + setState(() => _step = 3); + }, + style: ElevatedButton.styleFrom( + backgroundColor: UiColors.primary, + minimumSize: const Size(double.infinity, 48), + ), + child: Text("Next", style: UiTypography.body1m.white), ), ], )); @@ -260,35 +260,36 @@ class _LunchBreakDialogState extends State { Widget _buildStep3() { // Additional Notes - return Padding( + return Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ - const Text( + Text( "Additional Notes", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + style: UiTypography.headline4m, + ), + const SizedBox(height: 16), + TextField( + onChanged: (String v) => _additionalNotes = v, + style: UiTypography.body2r, + decoration: const InputDecoration( + hintText: 'Add any details...', + border: OutlineInputBorder(), + ), + maxLines: 3, ), - const SizedBox(height: 16), - TextField( - onChanged: (String v) => _additionalNotes = v, - decoration: const InputDecoration( - hintText: 'Add any details...', - border: OutlineInputBorder(), - ), - maxLines: 3, - ), const SizedBox(height: 24), ElevatedButton( onPressed: () { setState(() => _step = 4); }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), - minimumSize: const Size(double.infinity, 48), - ), - child: const Text("Submit", style: TextStyle(color: Colors.white)), + style: ElevatedButton.styleFrom( + backgroundColor: UiColors.primary, + minimumSize: const Size(double.infinity, 48), + ), + child: Text("Submit", style: UiTypography.body1m.white), ), ], )); @@ -296,25 +297,26 @@ class _LunchBreakDialogState extends State { Widget _buildStep4() { // Success - return Padding( + return Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ - const Icon(LucideIcons.checkCircle, size: 64, color: Colors.green), + const Icon(LucideIcons.checkCircle, + size: 64, color: UiColors.success), const SizedBox(height: 24), - const Text( + Text( "Break Logged!", - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + style: UiTypography.headline1m, ), const SizedBox(height: 24), ElevatedButton( onPressed: widget.onComplete, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), - minimumSize: const Size(double.infinity, 48), - ), - child: const Text("Close", style: TextStyle(color: Colors.white)), + style: ElevatedButton.styleFrom( + backgroundColor: UiColors.primary, + minimumSize: const Size(double.infinity, 48), + ), + child: Text("Close", style: UiTypography.body1m.white), ), ], )); diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/swipe_to_check_in.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/swipe_to_check_in.dart index 10315dd8..23987440 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/swipe_to_check_in.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/presentation/widgets/swipe_to_check_in.dart @@ -1,3 +1,4 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:lucide_icons/lucide_icons.dart'; @@ -72,9 +73,8 @@ class _SwipeToCheckInState extends State @override Widget build(BuildContext context) { - final Color baseColor = widget.isCheckedIn - ? const Color(0xFF10B981) - : const Color(0xFF0032A0); + final Color baseColor = + widget.isCheckedIn ? UiColors.success : UiColors.primary; if (widget.mode == 'nfc') { return GestureDetector( @@ -96,7 +96,7 @@ class _SwipeToCheckInState extends State borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: baseColor.withOpacity(0.4), + color: baseColor.withValues(alpha: 0.4), blurRadius: 25, offset: const Offset(0, 10), spreadRadius: -5, @@ -106,7 +106,7 @@ class _SwipeToCheckInState extends State child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(LucideIcons.wifi, color: Colors.white), + const Icon(LucideIcons.wifi, color: UiColors.white), const SizedBox(width: 12), Text( widget.isLoading @@ -114,11 +114,7 @@ class _SwipeToCheckInState extends State ? "Checking out..." : "Checking in...") : (widget.isCheckedIn ? "NFC Check Out" : "NFC Check In"), - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18, - ), + style: UiTypography.body1b.white, ), ], ), @@ -133,12 +129,10 @@ class _SwipeToCheckInState extends State // Calculate background color based on drag final double progress = _dragValue / maxDrag; - final Color startColor = widget.isCheckedIn - ? const Color(0xFF10B981) - : const Color(0xFF0032A0); - final Color endColor = widget.isCheckedIn - ? const Color(0xFF0032A0) - : const Color(0xFF10B981); + final Color startColor = + widget.isCheckedIn ? UiColors.success : UiColors.primary; + final Color endColor = + widget.isCheckedIn ? UiColors.primary : UiColors.success; final Color currentColor = Color.lerp(startColor, endColor, progress) ?? startColor; @@ -149,7 +143,7 @@ class _SwipeToCheckInState extends State borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: UiColors.black.withValues(alpha: 0.1), blurRadius: 4, offset: const Offset(0, 2), ), @@ -164,11 +158,7 @@ class _SwipeToCheckInState extends State widget.isCheckedIn ? "Swipe to Check Out" : "Swipe to Check In", - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontWeight: FontWeight.w600, - fontSize: 18, - ), + style: UiTypography.body1b, ), ), ), @@ -176,11 +166,7 @@ class _SwipeToCheckInState extends State Center( child: Text( widget.isCheckedIn ? "Check Out!" : "Check In!", - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w600, - fontSize: 18, - ), + style: UiTypography.body1b, ), ), Positioned( @@ -193,11 +179,11 @@ class _SwipeToCheckInState extends State width: _handleSize, height: _handleSize, decoration: BoxDecoration( - color: Colors.white, + color: UiColors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.1), + color: UiColors.black.withValues(alpha: 0.1), blurRadius: 2, offset: const Offset(0, 1), ),