From 4474a732c200b4c3fc5df4392116927d1a023385 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 3 Mar 2026 20:47:15 -0500 Subject: [PATCH] feat: Enhance benefits section and layout for improved user experience --- .../widgets/home_page/benefits_section.dart | 4 ++ .../widgets/home_page/full_width_divider.dart | 2 +- .../home_page/recommended_shift_card.dart | 9 ++-- .../home_page/recommended_shifts_section.dart | 11 ++-- .../widgets/home_page/section_header.dart | 7 ++- .../widgets/home_page/section_layout.dart | 5 ++ .../worker/worker_benefits/benefit_item.dart | 26 +++------ .../worker_benefits/benefits_widget.dart | 53 ++++++------------- 8 files changed, 47 insertions(+), 70 deletions(-) diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/benefits_section.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/benefits_section.dart index 8f6d9fc2..cb8baedb 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/benefits_section.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/benefits_section.dart @@ -1,6 +1,8 @@ import 'package:core_localization/core_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:krow_core/core.dart'; import 'package:staff_home/src/presentation/blocs/home_cubit.dart'; import 'package:staff_home/src/presentation/widgets/home_page/section_layout.dart'; @@ -28,6 +30,8 @@ class BenefitsSection extends StatelessWidget { return SectionLayout( title: i18n.title, + action: i18n.view_all, + onAction: () => Modular.to.toBenefits(), child: BenefitsWidget(benefits: state.benefits), ); }, diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/full_width_divider.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/full_width_divider.dart index 46ca3ece..3ffaf542 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/full_width_divider.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/full_width_divider.dart @@ -17,7 +17,7 @@ class FullWidthDivider extends StatelessWidget { children: [ const SizedBox(height: UiConstants.space10), Transform.translate( - offset: const Offset(UiConstants.space4, 0), + offset: const Offset(-UiConstants.space4, 0), child: SizedBox(width: screenWidth, child: const Divider()), ), const SizedBox(height: UiConstants.space10), diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shift_card.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shift_card.dart index 0f85ce9d..d3016ba5 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shift_card.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shift_card.dart @@ -13,13 +13,14 @@ class RecommendedShiftCard extends StatelessWidget { @override Widget build(BuildContext context) { final recI18n = t.staff.home.recommended_card; + final size = MediaQuery.sizeOf(context); return GestureDetector( onTap: () { Modular.to.toShiftDetails(shift); }, child: Container( - width: 300, + width: size.width * 0.8, padding: const EdgeInsets.all(UiConstants.space4), decoration: BoxDecoration( color: UiColors.white, @@ -28,11 +29,11 @@ class RecommendedShiftCard extends StatelessWidget { ), child: SingleChildScrollView( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: UiConstants.space10, @@ -50,7 +51,7 @@ class RecommendedShiftCard extends StatelessWidget { const SizedBox(width: UiConstants.space3), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shifts_section.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shifts_section.dart index 5929df8b..2dc63e0c 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shifts_section.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/recommended_shifts_section.dart @@ -21,26 +21,23 @@ class RecommendedShiftsSection extends StatelessWidget { final t = Translations.of(context); final sectionsI18n = t.staff.home.sections; final emptyI18n = t.staff.home.empty_states; + final size = MediaQuery.sizeOf(context); return SectionLayout( title: sectionsI18n.recommended_for_you, child: BlocBuilder( builder: (context, state) { if (state.recommendedShifts.isEmpty) { - return EmptyStateWidget( - message: emptyI18n.no_recommended_shifts, - ); + return EmptyStateWidget(message: emptyI18n.no_recommended_shifts); } return SizedBox( - height: 160, + height: size.height * 0.15, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: state.recommendedShifts.length, clipBehavior: Clip.none, itemBuilder: (context, index) => Padding( - padding: const EdgeInsets.only( - right: UiConstants.space3, - ), + padding: const EdgeInsets.only(right: UiConstants.space3), child: RecommendedShiftCard( shift: state.recommendedShifts[index], ), diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_header.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_header.dart index c5e7f4fa..8bf10f5f 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_header.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_header.dart @@ -39,11 +39,14 @@ class SectionHeader extends StatelessWidget { onTap: onAction, child: Row( children: [ - Text(action ?? '', style: UiTypography.body3r), + Text( + action ?? '', + style: UiTypography.body3r.textSecondary, + ), const Icon( UiIcons.chevronRight, size: UiConstants.space4, - color: UiColors.primary, + color: UiColors.iconSecondary, ), ], ), diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_layout.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_layout.dart index 0654ffaf..4d21c539 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_layout.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/home_page/section_layout.dart @@ -14,6 +14,9 @@ class SectionLayout extends StatelessWidget { /// Optional action text/widget to display on the right side of the header. final String? action; + /// Optional callback when action is tapped. + final VoidCallback? onAction; + /// The main content of the section. final Widget child; @@ -25,6 +28,7 @@ class SectionLayout extends StatelessWidget { const SectionLayout({ this.title, this.action, + this.onAction, required this.child, this.contentPadding, super.key, @@ -41,6 +45,7 @@ class SectionLayout extends StatelessWidget { child: SectionHeader( title: title!, action: action, + onAction: onAction, ), ), const SizedBox(height: UiConstants.space2), diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefit_item.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefit_item.dart index 7e3bcaa3..9fa913fa 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefit_item.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefit_item.dart @@ -1,7 +1,6 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; - -import 'circular_progress_painter.dart'; +import 'package:staff_home/src/presentation/widgets/worker/worker_benefits/circular_progress_painter.dart'; /// A widget that displays a single benefit item with circular progress. /// @@ -19,16 +18,12 @@ class BenefitItem extends StatelessWidget { /// The hours already used. final double used; - /// The color for the progress indicator. - final Color color; - /// Creates a [BenefitItem]. const BenefitItem({ required this.label, required this.remaining, required this.total, required this.used, - required this.color, super.key, }); @@ -44,8 +39,8 @@ class BenefitItem extends StatelessWidget { child: CustomPaint( painter: CircularProgressPainter( progress: progress, - color: color, - backgroundColor: const Color(0xFFE2E8F0), + color: UiColors.primary, + backgroundColor: UiColors.primaryInverse, strokeWidth: 5, ), child: Center( @@ -54,28 +49,21 @@ class BenefitItem extends StatelessWidget { children: [ Text( '${remaining.toInt()}/${total.toInt()}', - style: UiTypography.body2b.textPrimary.copyWith( - fontSize: 12, - letterSpacing: -0.5, - ), + style: UiTypography.body2b ), Text( 'hours', - style: UiTypography.footnote2r.textTertiary.copyWith( - fontSize: 8, - ), + style: UiTypography.footnote2r.textSecondary, ), ], ), ), ), ), - const SizedBox(height: UiConstants.space3), + const SizedBox(height: UiConstants.space2), Text( label, - style: UiTypography.footnote2r.textSecondary.copyWith( - fontWeight: FontWeight.w500, - ), + style: UiTypography.body2r.textSecondary, textAlign: TextAlign.center, ), ], diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefits_widget.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefits_widget.dart index af6f4076..a66bd82b 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefits_widget.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/widgets/worker/worker_benefits/benefits_widget.dart @@ -1,14 +1,10 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:krow_domain/krow_domain.dart'; - -import 'benefit_item.dart'; -import 'benefits_view_all_link.dart'; - +import 'package:staff_home/src/presentation/widgets/worker/worker_benefits/benefit_item.dart'; /// Widget for displaying staff benefits, using design system tokens. /// -/// Shows a list of benefits with circular progress indicators -/// and a link to view all benefits. +/// Shows a list of benefits with circular progress indicators. class BenefitsWidget extends StatelessWidget { /// The list of benefits to display. final List benefits; @@ -22,37 +18,20 @@ class BenefitsWidget extends StatelessWidget { return const SizedBox.shrink(); } - return Container( - padding: const EdgeInsets.all(UiConstants.space5), - decoration: BoxDecoration( - color: UiColors.white, - borderRadius: UiConstants.radiusLg, - border: Border.all(color: UiColors.border, width: 0.5), - ), - child: Column( - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - BenefitsViewAllLink(), - ], - ), - const SizedBox(height: UiConstants.space6), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: benefits.map((Benefit benefit) { - return Expanded( - child: BenefitItem( - label: benefit.title, - remaining: benefit.remainingHours, - total: benefit.entitlementHours, - used: benefit.usedHours, - color: const Color(0xFF2563EB), - ), - ); - }).toList(), - ), - ], + return Padding( + padding: const EdgeInsets.only(top: UiConstants.space4), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: benefits.map((Benefit benefit) { + return Expanded( + child: BenefitItem( + label: benefit.title, + remaining: benefit.remainingHours, + total: benefit.entitlementHours, + used: benefit.usedHours, + ), + ); + }).toList(), ), ); }