From e6b512ee84679e93a85ffb44c042dcfc9a90c0b6 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Mon, 16 Feb 2026 12:58:05 -0500 Subject: [PATCH] feat: Add Headline 1 Bold style and refactor ShiftDetailsPage and FindShiftsTab layout --- .../design_system/lib/src/ui_typography.dart | 8 + .../src/presentation/widgets/shift_card.dart | 7 - .../pages/shift_details_page.dart | 223 +++++++++--------- .../src/presentation/pages/shifts_page.dart | 3 - .../presentation/styles/shifts_styles.dart | 13 - .../widgets/shared/empty_state_view.dart | 1 - .../widgets/tabs/find_shifts_tab.dart | 40 ++-- .../features/staff/shifts/pubspec.yaml | 2 + 8 files changed, 151 insertions(+), 146 deletions(-) delete mode 100644 apps/mobile/packages/features/staff/shifts/lib/src/presentation/styles/shifts_styles.dart diff --git a/apps/mobile/packages/design_system/lib/src/ui_typography.dart b/apps/mobile/packages/design_system/lib/src/ui_typography.dart index 6d33312b..b2224b11 100644 --- a/apps/mobile/packages/design_system/lib/src/ui_typography.dart +++ b/apps/mobile/packages/design_system/lib/src/ui_typography.dart @@ -173,6 +173,14 @@ class UiTypography { color: UiColors.textPrimary, ); + /// Headline 1 Bold - Font: Instrument Sans, Size: 26, Height: 1.5 (#121826) + static final TextStyle headline1b = _primaryBase.copyWith( + fontWeight: FontWeight.w600, + fontSize: 26, + height: 1.5, + color: UiColors.textPrimary, + ); + /// Headline 2 Medium - Font: Instrument Sans, Size: 20, Height: 1.5 (#121826) static final TextStyle headline2m = _primaryBase.copyWith( fontWeight: FontWeight.w500, diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/shift_card.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/shift_card.dart index f8bf4992..f35d97ae 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/shift_card.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/shift_card.dart @@ -84,13 +84,6 @@ class _ShiftCardState extends State { color: UiColors.white, borderRadius: BorderRadius.circular(UiConstants.radiusBase), border: Border.all(color: UiColors.border), - boxShadow: [ - BoxShadow( - color: UiColors.black.withValues(alpha: 0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], ), child: Row( children: [ diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shift_details_page.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shift_details_page.dart index 48cca943..dc408d94 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shift_details_page.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shift_details_page.dart @@ -14,9 +14,13 @@ import '../widgets/shift_location_map.dart'; class ShiftDetailsPage extends StatefulWidget { final String shiftId; - final Shift? shift; + final Shift shift; - const ShiftDetailsPage({super.key, required this.shiftId, this.shift}); + const ShiftDetailsPage({ + super.key, + required this.shiftId, + required this.shift, + }); @override State createState() => _ShiftDetailsPageState(); @@ -86,12 +90,11 @@ class _ShiftDetailsPageState extends State { const SizedBox(height: UiConstants.space2), Text( value, - style: UiTypography.title1m.copyWith(fontWeight: FontWeight.w700).textPrimary, - ), - Text( - label, - style: UiTypography.footnote2r.textSecondary, + style: UiTypography.title1m + .copyWith(fontWeight: FontWeight.w700) + .textPrimary, ), + Text(label, style: UiTypography.footnote2r.textSecondary), ], ), ); @@ -109,12 +112,16 @@ class _ShiftDetailsPageState extends State { Text( label, style: UiTypography.footnote2b.copyWith( - color: UiColors.textSecondary, letterSpacing: 0.5), + color: UiColors.textSecondary, + letterSpacing: 0.5, + ), ), const SizedBox(height: UiConstants.space1), Text( _formatTime(time), - style: UiTypography.title1m.copyWith(fontWeight: FontWeight.w700).textPrimary, + style: UiTypography.title1m + .copyWith(fontWeight: FontWeight.w700) + .textPrimary, ), ], ), @@ -124,14 +131,10 @@ class _ShiftDetailsPageState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (_) => - Modular.get() - ..add( - LoadShiftDetailsEvent( - widget.shiftId, - roleId: widget.shift?.roleId, - ), - ), + create: (_) => Modular.get() + ..add( + LoadShiftDetailsEvent(widget.shiftId, roleId: widget.shift?.roleId), + ), child: BlocListener( listener: (context, state) { if (state is ShiftActionSuccess || state is ShiftDetailsError) { @@ -164,30 +167,16 @@ class _ShiftDetailsPageState extends State { ); } - Shift? displayShift; - if (state is ShiftDetailsLoaded) { - displayShift = state.shift; - } else { - displayShift = widget.shift; - } + Shift? displayShift = widget.shift; final i18n = Translations.of(context).staff_shifts.shift_details; - if (displayShift == null) { - return Scaffold( - body: Center(child: Text(Translations.of(context).staff_shifts.list.no_shifts)), - ); - } final duration = _calculateDuration(displayShift); final estimatedTotal = displayShift.totalValue ?? (displayShift.hourlyRate * duration); - final openSlots = - (displayShift.requiredSlots ?? 0) - - (displayShift.filledSlots ?? 0); return Scaffold( appBar: UiAppBar( - title: displayShift.title, centerTitle: false, onLeadingPressed: () => Modular.to.toShifts(), ), @@ -199,44 +188,49 @@ class _ShiftDetailsPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Vendor Section - Column( + // Role & Client Section + Row( crossAxisAlignment: CrossAxisAlignment.start, + spacing: UiConstants.space4, children: [ - Text( - i18n.vendor, - style: UiTypography.titleUppercase4b.textSecondary, + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + color: UiColors.background, + borderRadius: BorderRadius.circular( + UiConstants.radiusBase, + ), + border: Border.all(color: UiColors.border), + ), + child: const Center( + child: Icon( + UiIcons.briefcase, + color: UiColors.primary, + size: 24, + ), + ), ), - const SizedBox(height: UiConstants.space2), - Row( - children: [ - SizedBox( - width: 24, - height: 24, - child: displayShift.logoUrl != null - ? ClipRRect( - borderRadius: BorderRadius.circular( - UiConstants.radiusMdValue, - ), - child: Image.network( - displayShift.logoUrl!, - fit: BoxFit.cover, - ), - ) - : const Center( - child: Icon( - UiIcons.briefcase, - color: UiColors.primary, - size: 20, - ), - ), - ), - const SizedBox(width: UiConstants.space2), - Text( - displayShift.clientName, - style: UiTypography.headline5m.textPrimary, - ), - ], + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + displayShift.title, + style: + UiTypography.headline1b.textPrimary, + ), + Text( + displayShift.clientName, + style: UiTypography.body1m.textSecondary, + ), + Text( + displayShift.locationAddress, + style: UiTypography.body2r.textSecondary, + ), + ], + ), ), ], ), @@ -248,7 +242,8 @@ class _ShiftDetailsPageState extends State { children: [ Text( i18n.shift_date, - style: UiTypography.titleUppercase4b.textSecondary, + style: + UiTypography.titleUppercase4b.textSecondary, ), const SizedBox(height: UiConstants.space2), Row( @@ -276,7 +271,7 @@ class _ShiftDetailsPageState extends State { child: _buildStatCard( UiIcons.dollar, "\$${estimatedTotal.toStringAsFixed(0)}", - "Total", + "Total", ), ), const SizedBox(width: UiConstants.space4), @@ -291,7 +286,7 @@ class _ShiftDetailsPageState extends State { Expanded( child: _buildStatCard( UiIcons.clock, - "${duration.toStringAsFixed(1)}", + "${duration.toStringAsFixed(1)}", "Hours", ), ), @@ -319,14 +314,14 @@ class _ShiftDetailsPageState extends State { ), const SizedBox(height: UiConstants.space6), - // Location Section (New with Map) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "LOCATION", - style: UiTypography.titleUppercase4b.textSecondary, + style: + UiTypography.titleUppercase4b.textSecondary, ), const SizedBox(height: UiConstants.space3), Row( @@ -350,13 +345,13 @@ class _ShiftDetailsPageState extends State { ).showSnackBar( SnackBar( content: Text( - displayShift!.locationAddress.isNotEmpty - ? displayShift!.locationAddress - : displayShift!.location, - ), - duration: const Duration( - seconds: 3, + displayShift! + .locationAddress + .isNotEmpty + ? displayShift!.locationAddress + : displayShift!.location, ), + duration: const Duration(seconds: 3), ), ); }, @@ -364,12 +359,9 @@ class _ShiftDetailsPageState extends State { UiIcons.navigation, size: UiConstants.iconXs, ), - label: const Text( - "Get direction", - ), + label: const Text("Get direction"), style: OutlinedButton.styleFrom( - foregroundColor: - UiColors.textPrimary, + foregroundColor: UiColors.textPrimary, side: const BorderSide( color: UiColors.border, ), @@ -401,7 +393,8 @@ class _ShiftDetailsPageState extends State { if ((displayShift.description ?? '').isNotEmpty) ...[ Text( i18n.job_description, - style: UiTypography.titleUppercase4b.textSecondary, + style: + UiTypography.titleUppercase4b.textSecondary, ), const SizedBox(height: UiConstants.space2), Text( @@ -420,7 +413,8 @@ class _ShiftDetailsPageState extends State { UiConstants.space5, UiConstants.space4, UiConstants.space5, - MediaQuery.of(context).padding.bottom + UiConstants.space4, + MediaQuery.of(context).padding.bottom + + UiConstants.space4, ), decoration: BoxDecoration( color: UiColors.white, @@ -444,11 +438,10 @@ class _ShiftDetailsPageState extends State { ); } - void _bookShift( - BuildContext context, - Shift shift, - ) { - final i18n = Translations.of(context).staff_shifts.shift_details.book_dialog; + void _bookShift(BuildContext context, Shift shift) { + final i18n = Translations.of( + context, + ).staff_shifts.shift_details.book_dialog; showDialog( context: context, builder: (ctx) => AlertDialog( @@ -471,10 +464,10 @@ class _ShiftDetailsPageState extends State { ), ); }, - style: TextButton.styleFrom( - foregroundColor: UiColors.success, + style: TextButton.styleFrom(foregroundColor: UiColors.success), + child: Text( + Translations.of(context).staff_shifts.shift_details.apply_now, ), - child: Text(Translations.of(context).staff_shifts.shift_details.apply_now), ), ], ), @@ -482,7 +475,9 @@ class _ShiftDetailsPageState extends State { } void _declineShift(BuildContext context, String id) { - final i18n = Translations.of(context).staff_shifts.shift_details.decline_dialog; + final i18n = Translations.of( + context, + ).staff_shifts.shift_details.decline_dialog; showDialog( context: context, builder: (ctx) => AlertDialog( @@ -499,10 +494,10 @@ class _ShiftDetailsPageState extends State { context, ).add(DeclineShiftDetailsEvent(id)); }, - style: TextButton.styleFrom( - foregroundColor: UiColors.destructive, + style: TextButton.styleFrom(foregroundColor: UiColors.destructive), + child: Text( + Translations.of(context).staff_shifts.shift_details.decline, ), - child: Text(Translations.of(context).staff_shifts.shift_details.decline), ), ], ), @@ -513,7 +508,9 @@ class _ShiftDetailsPageState extends State { if (_actionDialogOpen) return; _actionDialogOpen = true; _isApplying = true; - final i18n = Translations.of(context).staff_shifts.shift_details.applying_dialog; + final i18n = Translations.of( + context, + ).staff_shifts.shift_details.applying_dialog; showDialog( context: context, useRootNavigator: true, @@ -590,10 +587,14 @@ class _ShiftDetailsPageState extends State { children: [ Expanded( child: OutlinedButton( - onPressed: () => BlocProvider.of(context).add(DeclineShiftDetailsEvent(shift.id)), + onPressed: () => BlocProvider.of( + context, + ).add(DeclineShiftDetailsEvent(shift.id)), style: OutlinedButton.styleFrom( foregroundColor: UiColors.destructive, - padding: const EdgeInsets.symmetric(vertical: UiConstants.space4), + padding: const EdgeInsets.symmetric( + vertical: UiConstants.space4, + ), side: const BorderSide(color: UiColors.destructive), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(UiConstants.radiusBase), @@ -605,11 +606,15 @@ class _ShiftDetailsPageState extends State { const SizedBox(width: UiConstants.space4), Expanded( child: ElevatedButton( - onPressed: () => BlocProvider.of(context).add(BookShiftDetailsEvent(shift.id, roleId: shift.roleId)), + onPressed: () => BlocProvider.of( + context, + ).add(BookShiftDetailsEvent(shift.id, roleId: shift.roleId)), style: ElevatedButton.styleFrom( backgroundColor: UiColors.primary, foregroundColor: UiColors.white, - padding: const EdgeInsets.symmetric(vertical: UiConstants.space4), + padding: const EdgeInsets.symmetric( + vertical: UiConstants.space4, + ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(UiConstants.radiusBase), ), @@ -630,13 +635,18 @@ class _ShiftDetailsPageState extends State { onPressed: () => _declineShift(context, shift.id), style: OutlinedButton.styleFrom( foregroundColor: UiColors.textSecondary, - padding: const EdgeInsets.symmetric(vertical: UiConstants.space4), + padding: const EdgeInsets.symmetric( + vertical: UiConstants.space4, + ), side: const BorderSide(color: UiColors.border), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(UiConstants.radiusBase), ), ), - child: Text(i18n.decline, style: UiTypography.body2b.textSecondary), + child: Text( + i18n.decline, + style: UiTypography.body2b.textSecondary, + ), ), ), const SizedBox(width: UiConstants.space4), @@ -646,7 +656,9 @@ class _ShiftDetailsPageState extends State { style: ElevatedButton.styleFrom( backgroundColor: UiColors.primary, foregroundColor: UiColors.white, - padding: const EdgeInsets.symmetric(vertical: UiConstants.space4), + padding: const EdgeInsets.symmetric( + vertical: UiConstants.space4, + ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(UiConstants.radiusBase), ), @@ -661,5 +673,4 @@ class _ShiftDetailsPageState extends State { return const SizedBox(); } - } diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart index 3f360efd..1b6e1592 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart @@ -29,7 +29,6 @@ class _ShiftsPageState extends State { super.initState(); _activeTab = widget.initialTab ?? 'myshifts'; _selectedDate = widget.selectedDate; - print('ShiftsPage init: initialTab=$_activeTab'); _prioritizeFind = widget.initialTab == 'find'; if (_prioritizeFind) { _bloc.add(LoadFindFirstEvent()); @@ -37,11 +36,9 @@ class _ShiftsPageState extends State { _bloc.add(LoadShiftsEvent()); } if (_activeTab == 'history') { - print('ShiftsPage init: loading history tab'); _bloc.add(LoadHistoryShiftsEvent()); } if (_activeTab == 'find') { - print('ShiftsPage init: entering find tab (not loaded yet)'); if (!_prioritizeFind) { _bloc.add(LoadAvailableShiftsEvent()); } diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/styles/shifts_styles.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/styles/shifts_styles.dart deleted file mode 100644 index 0a9a3675..00000000 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/styles/shifts_styles.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:design_system/design_system.dart'; - -class AppColors { - static const Color krowBlue = UiColors.primary; - static const Color krowYellow = UiColors.accent; - static const Color krowCharcoal = UiColors.textPrimary; - static const Color krowMuted = UiColors.textSecondary; - static const Color krowBorder = UiColors.border; - static const Color krowBackground = UiColors.background; - static const Color white = UiColors.white; - static const Color black = UiColors.black; -} diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/shared/empty_state_view.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/shared/empty_state_view.dart index 63569050..42b506cf 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/shared/empty_state_view.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/shared/empty_state_view.dart @@ -1,6 +1,5 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import '../../styles/shifts_styles.dart'; class EmptyStateView extends StatelessWidget { final IconData icon; diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart index 95d1f7db..bb426fd7 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart @@ -10,10 +10,7 @@ import '../shared/empty_state_view.dart'; class FindShiftsTab extends StatefulWidget { final List availableJobs; - const FindShiftsTab({ - super.key, - required this.availableJobs, - }); + const FindShiftsTab({super.key, required this.availableJobs}); @override State createState() => _FindShiftsTabState(); @@ -42,7 +39,9 @@ class _FindShiftsTabState extends State { child: Text( label, textAlign: TextAlign.center, - style: (isSelected ? UiTypography.footnote2m.white : UiTypography.footnote2m.textSecondary), + style: (isSelected + ? UiTypography.footnote2m.white + : UiTypography.footnote2m.textSecondary), ), ), ); @@ -86,13 +85,15 @@ class _FindShiftsTabState extends State { Expanded( child: Container( height: 48, - padding: const EdgeInsets.symmetric(horizontal: UiConstants.space3), + padding: const EdgeInsets.symmetric( + horizontal: UiConstants.space3, + ), decoration: BoxDecoration( color: UiColors.background, - borderRadius: BorderRadius.circular(UiConstants.radiusBase), - border: Border.all( - color: UiColors.border, + borderRadius: BorderRadius.circular( + UiConstants.radiusBase, ), + border: Border.all(color: UiColors.border), ), child: Row( children: [ @@ -123,10 +124,10 @@ class _FindShiftsTabState extends State { width: 48, decoration: BoxDecoration( color: UiColors.white, - borderRadius: BorderRadius.circular(UiConstants.radiusBase), - border: Border.all( - color: UiColors.border, + borderRadius: BorderRadius.circular( + UiConstants.radiusBase, ), + border: Border.all(color: UiColors.border), ), child: const Icon( UiIcons.filter, @@ -164,20 +165,27 @@ class _FindShiftsTabState extends State { subtitle: "Check back later", ) : SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: UiConstants.space5), + padding: const EdgeInsets.symmetric( + horizontal: UiConstants.space5, + ), child: Column( children: [ const SizedBox(height: UiConstants.space5), ...filteredJobs.map( (shift) => Padding( - padding: const EdgeInsets.only(bottom: UiConstants.space3), + padding: const EdgeInsets.only( + bottom: UiConstants.space3, + ), child: MyShiftCard( shift: shift, onAccept: () { - context.read().add(AcceptShiftEvent(shift.id)); + context.read().add( + AcceptShiftEvent(shift.id), + ); UiSnackbar.show( context, - message: "Shift application submitted!", // Todo: Localization + message: + "Shift application submitted!", // Todo: Localization type: UiSnackbarType.success, ); }, diff --git a/apps/mobile/packages/features/staff/shifts/pubspec.yaml b/apps/mobile/packages/features/staff/shifts/pubspec.yaml index 99360d7a..4a6d7070 100644 --- a/apps/mobile/packages/features/staff/shifts/pubspec.yaml +++ b/apps/mobile/packages/features/staff/shifts/pubspec.yaml @@ -27,6 +27,8 @@ dependencies: path: ../../../data_connect core_localization: path: ../../../core_localization + firebase_auth: ^6.1.4 + firebase_data_connect: ^0.2.2+2 dev_dependencies: flutter_test: