From 8e83e6dcbfe52ad4ef4cac93e840ff0e10dedfbb Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 3 Mar 2026 23:44:17 -0500 Subject: [PATCH 01/20] fix: Remove unnecessary background color setting in report pages --- .../lib/src/presentation/pages/coverage_report_page.dart | 6 ++---- .../lib/src/presentation/pages/daily_ops_report_page.dart | 6 ++---- .../lib/src/presentation/pages/forecast_report_page.dart | 1 - .../lib/src/presentation/pages/no_show_report_page.dart | 1 - .../src/presentation/pages/performance_report_page.dart | 6 ++---- .../reports/lib/src/presentation/pages/reports_page.dart | 7 ++----- .../lib/src/presentation/pages/spend_report_page.dart | 4 +--- 7 files changed, 9 insertions(+), 22 deletions(-) diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart index ca7c9f5e..f3557298 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart @@ -1,14 +1,13 @@ -// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs -import 'package:client_reports/src/presentation/blocs/coverage/coverage_bloc.dart'; +import 'package:client_reports/src/presentation/blocs/coverage/coverage_bloc.dart'; import 'package:client_reports/src/presentation/blocs/coverage/coverage_event.dart'; import 'package:client_reports/src/presentation/blocs/coverage/coverage_state.dart'; -import 'package:krow_domain/krow_domain.dart'; import 'package:core_localization/core_localization.dart'; 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:intl/intl.dart'; +import 'package:krow_domain/krow_domain.dart'; class CoverageReportPage extends StatefulWidget { const CoverageReportPage({super.key}); @@ -27,7 +26,6 @@ class _CoverageReportPageState extends State { create: (BuildContext context) => Modular.get() ..add(LoadCoverageReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( - backgroundColor: UiColors.bgMenu, body: BlocBuilder( builder: (BuildContext context, CoverageState state) { if (state is CoverageLoading) { diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart index 07ede38c..e381fb45 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart @@ -1,5 +1,4 @@ -// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs, implementation_imports -import 'package:client_reports/src/presentation/blocs/daily_ops/daily_ops_bloc.dart'; +import 'package:client_reports/src/presentation/blocs/daily_ops/daily_ops_bloc.dart'; import 'package:client_reports/src/presentation/blocs/daily_ops/daily_ops_event.dart'; import 'package:client_reports/src/presentation/blocs/daily_ops/daily_ops_state.dart'; import 'package:core_localization/core_localization.dart'; @@ -8,7 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:intl/intl.dart'; -import 'package:krow_domain/src/entities/reports/daily_ops_report.dart'; +import 'package:krow_domain/krow_domain.dart'; class DailyOpsReportPage extends StatefulWidget { const DailyOpsReportPage({super.key}); @@ -54,7 +53,6 @@ class _DailyOpsReportPageState extends State { create: (BuildContext context) => Modular.get() ..add(LoadDailyOpsReport(date: _selectedDate)), child: Scaffold( - backgroundColor: UiColors.bgMenu, body: BlocBuilder( builder: (BuildContext context, DailyOpsState state) { if (state is DailyOpsLoading) { diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart index 553ca240..e0495d80 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart @@ -28,7 +28,6 @@ class _ForecastReportPageState extends State { create: (BuildContext context) => Modular.get() ..add(LoadForecastReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( - backgroundColor: UiColors.bgMenu, body: BlocBuilder( builder: (BuildContext context, ForecastState state) { if (state is ForecastLoading) { diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart index 17410784..91ec15c2 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart @@ -27,7 +27,6 @@ class _NoShowReportPageState extends State { create: (BuildContext context) => Modular.get() ..add(LoadNoShowReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( - backgroundColor: UiColors.bgMenu, body: BlocBuilder( builder: (BuildContext context, NoShowState state) { if (state is NoShowLoading) { diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart index 3593b5fa..2f7c8dd5 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart @@ -1,5 +1,4 @@ -// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs, implementation_imports -import 'package:client_reports/src/presentation/blocs/performance/performance_bloc.dart'; +import 'package:client_reports/src/presentation/blocs/performance/performance_bloc.dart'; import 'package:client_reports/src/presentation/blocs/performance/performance_event.dart'; import 'package:client_reports/src/presentation/blocs/performance/performance_state.dart'; import 'package:core_localization/core_localization.dart'; @@ -7,7 +6,7 @@ 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:krow_domain/src/entities/reports/performance_report.dart'; +import 'package:krow_domain/krow_domain.dart'; class PerformanceReportPage extends StatefulWidget { const PerformanceReportPage({super.key}); @@ -26,7 +25,6 @@ class _PerformanceReportPageState extends State { create: (BuildContext context) => Modular.get() ..add(LoadPerformanceReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( - backgroundColor: UiColors.bgMenu, body: BlocBuilder( builder: (BuildContext context, PerformanceState state) { if (state is PerformanceLoading) { diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/reports_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/reports_page.dart index 10a6c620..79212649 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/reports_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/reports_page.dart @@ -1,7 +1,5 @@ -// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs, implementation_imports -import 'package:client_reports/src/presentation/blocs/summary/reports_summary_bloc.dart'; +import 'package:client_reports/src/presentation/blocs/summary/reports_summary_bloc.dart'; import 'package:client_reports/src/presentation/blocs/summary/reports_summary_event.dart'; -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'; @@ -80,10 +78,9 @@ class _ReportsPageState extends State @override Widget build(BuildContext context) { - return BlocProvider.value( + return BlocProvider.value( value: _summaryBloc, child: Scaffold( - backgroundColor: UiColors.bgMenu, body: SingleChildScrollView( child: Column( children: [ diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart index 9b6becd6..db5d39ba 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart @@ -1,5 +1,4 @@ -// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs -import 'package:client_reports/src/presentation/blocs/spend/spend_bloc.dart'; +import 'package:client_reports/src/presentation/blocs/spend/spend_bloc.dart'; import 'package:client_reports/src/presentation/blocs/spend/spend_event.dart'; import 'package:client_reports/src/presentation/blocs/spend/spend_state.dart'; import 'package:core_localization/core_localization.dart'; @@ -39,7 +38,6 @@ class _SpendReportPageState extends State { create: (BuildContext context) => Modular.get() ..add(LoadSpendReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( - backgroundColor: UiColors.bgMenu, body: BlocBuilder( builder: (BuildContext context, SpendState state) { if (state is SpendLoading) { From 26663d4e022df2a75247b9eb22e0ec88513a8d5e Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 3 Mar 2026 23:45:43 -0500 Subject: [PATCH 02/20] fix: Specify type for BlocProvider in CoverageReportPage --- .../lib/src/presentation/pages/coverage_report_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart index f3557298..a307da37 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart @@ -22,7 +22,7 @@ class _CoverageReportPageState extends State { @override Widget build(BuildContext context) { - return BlocProvider( + return BlocProvider( create: (BuildContext context) => Modular.get() ..add(LoadCoverageReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( From 138cb9a82e8d6fffdd79677148fcb86ec53a7db5 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 12:09:08 -0500 Subject: [PATCH 03/20] refactor: Update navigation configuration and improve order dialog hub handling --- apps/web/pnpm-lock.yaml | 3 - apps/web/pnpm-workspace.yaml | 3 + apps/web/src/common/config/navigation.ts | 75 ------------------- .../orders/components/CreateOrderDialog.tsx | 8 +- 4 files changed, 7 insertions(+), 82 deletions(-) diff --git a/apps/web/pnpm-lock.yaml b/apps/web/pnpm-lock.yaml index 6f3eca62..bd577ae8 100644 --- a/apps/web/pnpm-lock.yaml +++ b/apps/web/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - '@dataconnect/generated': link:src/dataconnect-generated - importers: .: diff --git a/apps/web/pnpm-workspace.yaml b/apps/web/pnpm-workspace.yaml index 117a15bd..9410b45d 100644 --- a/apps/web/pnpm-workspace.yaml +++ b/apps/web/pnpm-workspace.yaml @@ -1,2 +1,5 @@ +packages: + - '.' + overrides: '@dataconnect/generated': link:src/dataconnect-generated diff --git a/apps/web/src/common/config/navigation.ts b/apps/web/src/common/config/navigation.ts index ede3d92a..7de926c6 100644 --- a/apps/web/src/common/config/navigation.ts +++ b/apps/web/src/common/config/navigation.ts @@ -62,12 +62,6 @@ export const NAV_CONFIG: NavGroup[] = [ icon: LayoutDashboard, allowedRoles: ['Vendor'], }, - { - label: 'Savings Engine', - path: '/savings', - icon: PiggyBank, - allowedRoles: ALL_ROLES, - }, { label: 'Vendor Performance', path: '/performance', @@ -117,23 +111,6 @@ export const NAV_CONFIG: NavGroup[] = [ }, ], }, - { - title: 'Marketplace', - items: [ - { - label: 'Discovery', - path: '/marketplace', - icon: ShoppingBag, - allowedRoles: ['Client', 'Admin'], - }, - { - label: 'Compare Rates', - path: '/marketplace/compare', - icon: Scale, - allowedRoles: ['Client', 'Admin'], - }, - ], - }, { title: 'Workforce', items: [ @@ -143,18 +120,6 @@ export const NAV_CONFIG: NavGroup[] = [ icon: Users, allowedRoles: ALL_ROLES, }, - { - label: 'Onboarding', - path: '/onboarding', - icon: UserPlus, - allowedRoles: ALL_ROLES, - }, - { - label: 'Teams', - path: '/teams', - icon: Users2, - allowedRoles: ALL_ROLES, - }, { label: 'Compliance', path: '/compliance', @@ -197,44 +162,4 @@ export const NAV_CONFIG: NavGroup[] = [ }, ], }, - { - title: 'Analytics & Comm', - items: [ - { - label: 'Reports', - path: '/reports', - icon: PieChart, - allowedRoles: ALL_ROLES, - }, - { - label: 'Activity Log', - path: '/activity', - icon: History, - allowedRoles: ['Vendor', 'Admin'], - }, - { - label: 'Messages', - path: '/messages', - icon: MessageSquare, - allowedRoles: ALL_ROLES, - }, - { - label: 'Tutorials', - path: '/tutorials', - icon: BookOpen, - allowedRoles: ['Client', 'Admin'], - }, - ], - }, - { - title: 'Support', - items: [ - { - label: 'Help Center', - path: '/support', - icon: HelpCircle, - allowedRoles: ['Client', 'Admin'], - }, - ], - }, ]; diff --git a/apps/web/src/features/operations/orders/components/CreateOrderDialog.tsx b/apps/web/src/features/operations/orders/components/CreateOrderDialog.tsx index 718e6e82..763e1f81 100644 --- a/apps/web/src/features/operations/orders/components/CreateOrderDialog.tsx +++ b/apps/web/src/features/operations/orders/components/CreateOrderDialog.tsx @@ -6,7 +6,7 @@ import { DialogTitle, } from "@/common/components/ui/dialog"; import EventFormWizard from "./EventFormWizard"; -import { useCreateOrder, useListBusinesses, useListHubs } from "@/dataconnect-generated/react"; +import { useCreateOrder, useListBusinesses, useListTeamHubs } from "@/dataconnect-generated/react"; import { OrderType, OrderStatus } from "@/dataconnect-generated"; import { dataConnect } from "@/features/auth/firebase"; import { useToast } from "@/common/components/ui/use-toast"; @@ -26,7 +26,7 @@ export default function CreateOrderDialog({ open, onOpenChange }: CreateOrderDia const [selectedHubId, setSelectedHubId] = React.useState(""); const { data: businessesData } = useListBusinesses(dataConnect); - const { data: hubsData } = useListHubs(dataConnect); + const { data: hubsData } = useListTeamHubs(dataConnect); const createOrderMutation = useCreateOrder(dataConnect, { onSuccess: () => { @@ -109,9 +109,9 @@ export default function CreateOrderDialog({ open, onOpenChange }: CreateOrderDia - {hubsData?.hubs.map((h) => ( + {hubsData?.teamHubs.map((h) => ( - {h.name} + {h.hubName} ))} From d5e796ea8168d9ce08f99d24376f175a06e7ba8f Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 12:13:09 -0500 Subject: [PATCH 04/20] refactor: Simplify getDefaultLocale method by removing device locale check --- .../src/data/repositories_impl/locale_repository_impl.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart b/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart index 861f579f..71965a1a 100644 --- a/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart +++ b/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart @@ -1,4 +1,5 @@ import 'dart:ui'; + import 'package:core_localization/src/l10n/strings.g.dart'; import '../../domain/repositories/locale_repository_interface.dart'; @@ -33,10 +34,6 @@ class LocaleRepositoryImpl implements LocaleRepositoryInterface { @override Locale getDefaultLocale() { - final Locale deviceLocale = AppLocaleUtils.findDeviceLocale().flutterLocale; - if (getSupportedLocales().contains(deviceLocale)) { - return deviceLocale; - } return const Locale('en'); } From 2a11dbc120bd278c993ba5098bb401d101f0c80d Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 12:14:07 -0500 Subject: [PATCH 05/20] docs: Update comment for getDefaultLocale method to clarify locale handling --- .../lib/src/data/repositories_impl/locale_repository_impl.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart b/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart index 71965a1a..be8f1e24 100644 --- a/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart +++ b/apps/mobile/packages/core_localization/lib/src/data/repositories_impl/locale_repository_impl.dart @@ -32,6 +32,8 @@ class LocaleRepositoryImpl implements LocaleRepositoryInterface { return getDefaultLocale(); } + /// We can hardcode this to english based on customer requirements, + /// but in a more dynamic app this should be the device locale or a fallback to english. @override Locale getDefaultLocale() { return const Locale('en'); From 4a5c2be489729929cc120f21120969a6330d9fe1 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 12:56:25 -0500 Subject: [PATCH 06/20] refactor: Clean up view order card layout and improve text overflow handling --- .../features/client/orders/analyze.txt | Bin 3460 -> 0 bytes .../features/client/orders/analyze_output.txt | Bin 2792 -> 0 bytes .../presentation/widgets/view_order_card.dart | 24 ++++++++---------- .../blocs/daily_ops/daily_ops_bloc.dart | 3 ++- 4 files changed, 13 insertions(+), 14 deletions(-) delete mode 100644 apps/mobile/packages/features/client/orders/analyze.txt delete mode 100644 apps/mobile/packages/features/client/orders/analyze_output.txt diff --git a/apps/mobile/packages/features/client/orders/analyze.txt b/apps/mobile/packages/features/client/orders/analyze.txt deleted file mode 100644 index 28d6d1d597978e344651be456b1588799cd9686e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3460 zcmeH~%Wl&^6o$_liFcS?HV|k-OWO@X;st=Pi)7{ErdFM}ik*b;@WA)aWbC-$QmG(S zDjM12nK`#PcmMeQ-j+7D+;;ZOGQQ{LtiK=6?V0IujMP?)g2&lQo(<5cZ7uP8Gk;#% z2uhhvm`fn1%s0#_s}$N5oGQ)>zDM9@HiKWvo-jo_&`H>vaauvWv@2GE>9aQmrm_ng z*c&@$KH@9L^97p1z65XS@g4kgFiM8Ao_(}6`zvnxiMeEzL#qc}XG6a)j4Lptg{X_l z^LOlxZ2_JGr|@sdb+})^+j(qh>njvWU?ZJImKQ(;Jx<}8g3&;YIcp%D*O4R;*W3K= zzL9LS{zWIr0rkge*>gK#$inB`K(`p~Z!X)H&dgtsM2YODlK1*-(A^25M;OoZgnmj$+- z=d$(_-MI0Kv=v_uiLP#%T_;H$bSuIYsj+|p|XkeIkjuv zit-D-ltGj;X3Pur6&K zHFC$8&~28)vm#v>_sw?7P|9*6&so}#&E;kCO=X=?2d(5c7&|l-q{~~`?}*$tK%Z~- z(tUt_^mNI+VSNp^V1p19%5>pY&gbL;{jB%85w^TedqGPvA4*G6%gRkTFmp!SyF}^` zFI!GlaE&@1dnuIR6VFc=Rb5RUyM710y2K3hboAR@t(CC~eB>?A!2U;S5{gg*-XBdH@2d{#@UPDZpO fyDDM)yD5F8Q#YX+qCWxsZ>at|Pd9YteGl~$WyEs? diff --git a/apps/mobile/packages/features/client/orders/analyze_output.txt b/apps/mobile/packages/features/client/orders/analyze_output.txt deleted file mode 100644 index 4c48dc483bb7a8a074236ec4f2d1911266082b92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2792 zcmeH}+e*Vg5QhJ2!FTALSDx{BC!Q!C(N=GSlEx@SO-j492z_?-n@MU_>Jb!$5;oc0 znSXaX-%Qen`%|syNc$?&w$;HvKO<)&73# { decoration: BoxDecoration( color: UiColors.white, borderRadius: UiConstants.radiusLg, - border: Border.all(color: UiColors.border), - boxShadow: [ - BoxShadow( - color: UiColors.black.withValues(alpha: 0.04), - blurRadius: 8, - offset: const Offset(0, 2), - ), - ], + border: Border.all(color: UiColors.border, width: 0.5), ), child: Column( children: [ @@ -249,9 +242,12 @@ class _ViewOrderCardState extends State { size: 14, color: UiColors.iconSecondary, ), - Text( - order.eventName, - style: UiTypography.headline5m.textSecondary, + Expanded( + child: Text( + order.eventName, + style: UiTypography.headline5m.textSecondary, + overflow: TextOverflow.ellipsis, + ), ), ], ), @@ -313,7 +309,8 @@ class _ViewOrderCardState extends State { Expanded( child: Text( order.hubManagerName!, - style: UiTypography.footnote2r.textSecondary, + style: + UiTypography.footnote2r.textSecondary, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -335,7 +332,8 @@ class _ViewOrderCardState extends State { bgColor: UiColors.primary.withValues(alpha: 0.08), onTap: () => _openEditSheet(order: order), ), - if (_canEditOrder(order)) const SizedBox(width: UiConstants.space2), + if (_canEditOrder(order)) + const SizedBox(width: UiConstants.space2), if (order.confirmedApps.isNotEmpty) _buildHeaderIconButton( icon: _expanded diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/blocs/daily_ops/daily_ops_bloc.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/blocs/daily_ops/daily_ops_bloc.dart index 943553bb..06f54dcb 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/blocs/daily_ops/daily_ops_bloc.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/blocs/daily_ops/daily_ops_bloc.dart @@ -1,5 +1,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:krow_domain/src/entities/reports/daily_ops_report.dart'; +import 'package:krow_domain/krow_domain.dart'; + import '../../../domain/repositories/reports_repository.dart'; import 'daily_ops_event.dart'; import 'daily_ops_state.dart'; From b20039ae8474e9d1035a32fc30929c312db8454e Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 12:59:56 -0500 Subject: [PATCH 07/20] refactor: Enhance DailyOpsReportPage layout and improve UI consistency --- .../pages/daily_ops_report_page.dart | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart index e381fb45..736237f7 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart @@ -49,7 +49,7 @@ class _DailyOpsReportPageState extends State { @override Widget build(BuildContext context) { - return BlocProvider( + return BlocProvider( create: (BuildContext context) => Modular.get() ..add(LoadDailyOpsReport(date: _selectedDate)), child: Scaffold( @@ -243,6 +243,7 @@ class _DailyOpsReportPageState extends State { crossAxisCount: 2, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 1.2, @@ -316,7 +317,7 @@ class _DailyOpsReportPageState extends State { ], ), - const SizedBox(height: 8), + const SizedBox(height: UiConstants.space8), Text( context.t.client_reports.daily_ops_report .all_shifts_title @@ -396,14 +397,8 @@ class _OpsStatCard extends StatelessWidget { padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: UiColors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: UiColors.black.withOpacity(0.06), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], + borderRadius: BorderRadius.circular(UiConstants.radiusBase), + border: Border.all(color: UiColors.border, width: 0.5), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -438,7 +433,8 @@ class _OpsStatCard extends StatelessWidget { color: UiColors.textPrimary, ), ), - const SizedBox(height: 6), + + UiChip(label: subValue), // Colored pill badge (matches prototype) Container( padding: const EdgeInsets.symmetric( From 867ff8d61ce8b4da530b5ff9b22b5bce188759f6 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 13:08:39 -0500 Subject: [PATCH 08/20] refactor: Replace Navigator.pop with Modular.to.popSafe for consistent navigation handling --- .../apps/client/lib/src/widgets/session_listener.dart | 4 ++-- .../apps/staff/lib/src/widgets/session_listener.dart | 4 ++-- .../lib/src/presentation/pages/coverage_report_page.dart | 3 ++- .../src/presentation/pages/daily_ops_report_page.dart | 9 +++++---- .../lib/src/presentation/pages/forecast_report_page.dart | 6 ++++-- .../lib/src/presentation/pages/no_show_report_page.dart | 3 ++- .../src/presentation/pages/performance_report_page.dart | 3 ++- .../lib/src/presentation/pages/spend_report_page.dart | 5 +++-- .../src/presentation/pages/phone_verification_page.dart | 2 +- 9 files changed, 23 insertions(+), 16 deletions(-) diff --git a/apps/mobile/apps/client/lib/src/widgets/session_listener.dart b/apps/mobile/apps/client/lib/src/widgets/session_listener.dart index cbae1627..707d5cf7 100644 --- a/apps/mobile/apps/client/lib/src/widgets/session_listener.dart +++ b/apps/mobile/apps/client/lib/src/widgets/session_listener.dart @@ -104,7 +104,7 @@ class _SessionListenerState extends State { actions: [ TextButton( onPressed: () { - Navigator.of(context).pop(); + Modular.to.popSafe(); _proceedToLogin(); }, child: const Text('Log In'), @@ -134,7 +134,7 @@ class _SessionListenerState extends State { ), TextButton( onPressed: () { - Navigator.of(context).pop(); + Modular.to.popSafe();; _proceedToLogin(); }, child: const Text('Log Out'), diff --git a/apps/mobile/apps/staff/lib/src/widgets/session_listener.dart b/apps/mobile/apps/staff/lib/src/widgets/session_listener.dart index fa830a35..47d9fdd0 100644 --- a/apps/mobile/apps/staff/lib/src/widgets/session_listener.dart +++ b/apps/mobile/apps/staff/lib/src/widgets/session_listener.dart @@ -104,7 +104,7 @@ class _SessionListenerState extends State { actions: [ TextButton( onPressed: () { - Navigator.of(context).pop(); + Modular.to.popSafe();; _proceedToLogin(); }, child: const Text('Log In'), @@ -134,7 +134,7 @@ class _SessionListenerState extends State { ), TextButton( onPressed: () { - Navigator.of(context).pop(); + Modular.to.popSafe();; _proceedToLogin(); }, child: const Text('Log Out'), diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart index a307da37..54ba368b 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/coverage_report_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:intl/intl.dart'; +import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; class CoverageReportPage extends StatefulWidget { @@ -62,7 +63,7 @@ class _CoverageReportPageState extends State { Row( children: [ GestureDetector( - onTap: () => Navigator.of(context).pop(), + onTap: () => Modular.to.popSafe(), child: Container( width: 40, height: 40, diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart index 736237f7..15e4765f 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/daily_ops_report_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:intl/intl.dart'; +import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; class DailyOpsReportPage extends StatefulWidget { @@ -92,7 +93,7 @@ class _DailyOpsReportPageState extends State { Row( children: [ GestureDetector( - onTap: () => Navigator.of(context).pop(), + onTap: () => Modular.to.popSafe(), child: Container( width: 40, height: 40, @@ -434,7 +435,7 @@ class _OpsStatCard extends StatelessWidget { ), ), - UiChip(label: subValue), + //UiChip(label: subValue), // Colored pill badge (matches prototype) Container( padding: const EdgeInsets.symmetric( @@ -443,12 +444,12 @@ class _OpsStatCard extends StatelessWidget { ), decoration: BoxDecoration( color: color.withOpacity(0.12), - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(4), ), child: Text( subValue, style: TextStyle( - fontSize: 10, + fontSize: 12, fontWeight: FontWeight.bold, color: color, ), diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart index e0495d80..a0479a67 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/forecast_report_page.dart @@ -2,6 +2,7 @@ import 'package:client_reports/src/presentation/blocs/forecast/forecast_bloc.dart'; import 'package:client_reports/src/presentation/blocs/forecast/forecast_event.dart'; import 'package:client_reports/src/presentation/blocs/forecast/forecast_state.dart'; +import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; @@ -85,7 +86,7 @@ class _ForecastReportPageState extends State { (ForecastWeek week) => _WeeklyBreakdownItem(week: week), ), - const SizedBox(height: 40), + const SizedBox(height: UiConstants.space24), ], ), ), @@ -123,7 +124,7 @@ class _ForecastReportPageState extends State { Row( children: [ GestureDetector( - onTap: () => Navigator.of(context).pop(), + onTap: () => Modular.to.popSafe(), child: Container( width: 40, height: 40, @@ -183,6 +184,7 @@ class _ForecastReportPageState extends State { final TranslationsClientReportsForecastReportEn t = context.t.client_reports.forecast_report; return GridView.count( crossAxisCount: 2, + padding: EdgeInsets.zero, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), mainAxisSpacing: 12, diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart index 91ec15c2..7cf962d2 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/no_show_report_page.dart @@ -1,4 +1,5 @@ // ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs +import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; import 'package:client_reports/src/presentation/blocs/no_show/no_show_bloc.dart'; import 'package:client_reports/src/presentation/blocs/no_show/no_show_event.dart'; @@ -66,7 +67,7 @@ class _NoShowReportPageState extends State { Row( children: [ GestureDetector( - onTap: () => Navigator.of(context).pop(), + onTap: () => Modular.to.popSafe(), child: Container( width: 40, height: 40, diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart index 2f7c8dd5..ccfd5169 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/performance_report_page.dart @@ -6,6 +6,7 @@ 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:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; class PerformanceReportPage extends StatefulWidget { @@ -141,7 +142,7 @@ class _PerformanceReportPageState extends State { Row( children: [ GestureDetector( - onTap: () => Navigator.of(context).pop(), + onTap: () => Modular.to.popSafe(), child: Container( width: 40, height: 40, diff --git a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart index db5d39ba..7ba1eeb9 100644 --- a/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart +++ b/apps/mobile/packages/features/client/reports/lib/src/presentation/pages/spend_report_page.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:intl/intl.dart'; +import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; class SpendReportPage extends StatefulWidget { @@ -34,7 +35,7 @@ class _SpendReportPageState extends State { @override Widget build(BuildContext context) { - return BlocProvider( + return BlocProvider( create: (BuildContext context) => Modular.get() ..add(LoadSpendReport(startDate: _startDate, endDate: _endDate)), child: Scaffold( @@ -70,7 +71,7 @@ class _SpendReportPageState extends State { Row( children: [ GestureDetector( - onTap: () => Navigator.of(context).pop(), + onTap: () => Modular.to.popSafe(), child: Container( width: 40, height: 40, diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/phone_verification_page.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/phone_verification_page.dart index d70eb8ad..d4c3b652 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/phone_verification_page.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/phone_verification_page.dart @@ -155,7 +155,7 @@ class _PhoneVerificationPageState extends State { BlocProvider.of( context, ).add(AuthResetRequested(mode: widget.mode)); - Navigator.of(context).pop(); + Modular.to.popSafe();; }, ), body: SafeArea( From 76ffeb9667ba6d4c19d43ad06d3add13543c948e Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 13:19:43 -0500 Subject: [PATCH 09/20] refactor: Clean up imports and comment out unused button in CoverageShiftList widget --- .../src/presentation/pages/coverage_page.dart | 20 ++----------- .../widgets/coverage_shift_list.dart | 30 +++++++++---------- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/pages/coverage_page.dart b/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/pages/coverage_page.dart index 697fc13d..7d3bf602 100644 --- a/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/pages/coverage_page.dart +++ b/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/pages/coverage_page.dart @@ -1,14 +1,13 @@ +import 'package:core_localization/core_localization.dart'; 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:intl/intl.dart'; -import 'package:krow_core/core.dart'; -import 'package:core_localization/core_localization.dart'; + import '../blocs/coverage_bloc.dart'; import '../blocs/coverage_event.dart'; import '../blocs/coverage_state.dart'; - import '../widgets/coverage_calendar_selector.dart'; import '../widgets/coverage_quick_stats.dart'; import '../widgets/coverage_shift_list.dart'; @@ -78,21 +77,6 @@ class _CoveragePageState extends State { pinned: true, expandedHeight: 300.0, backgroundColor: UiColors.primary, - leading: IconButton( - onPressed: () => Modular.to.toClientHome(), - icon: Container( - padding: const EdgeInsets.all(UiConstants.space2), - decoration: BoxDecoration( - color: UiColors.primaryForeground.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - UiIcons.arrowLeft, - color: UiColors.primaryForeground, - size: UiConstants.space4, - ), - ), - ), title: AnimatedSwitcher( duration: const Duration(milliseconds: 200), child: Text( diff --git a/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/widgets/coverage_shift_list.dart b/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/widgets/coverage_shift_list.dart index e675719b..c1bedeed 100644 --- a/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/widgets/coverage_shift_list.dart +++ b/apps/mobile/packages/features/client/client_coverage/lib/src/presentation/widgets/coverage_shift_list.dart @@ -506,21 +506,21 @@ class _WorkerRow extends StatelessWidget { ), ), ), - if (worker.status == CoverageWorkerStatus.checkedIn) - UiButton.primary( - text: context.t.client_coverage.worker_row.verify, - size: UiButtonSize.small, - onPressed: () { - UiSnackbar.show( - context, - message: - context.t.client_coverage.worker_row.verified_message( - name: worker.name, - ), - type: UiSnackbarType.success, - ); - }, - ), + // if (worker.status == CoverageWorkerStatus.checkedIn) + // UiButton.primary( + // text: context.t.client_coverage.worker_row.verify, + // size: UiButtonSize.small, + // onPressed: () { + // UiSnackbar.show( + // context, + // message: + // context.t.client_coverage.worker_row.verified_message( + // name: worker.name, + // ), + // type: UiSnackbarType.success, + // ); + // }, + // ), ], ), ], From 256f9fd678f4d313dad49d9441a71c1de917d8c0 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 13:27:14 -0500 Subject: [PATCH 10/20] refactor: Remove unused code and improve PaymentHistoryItem widget styling --- .../widgets/home_page/full_width_divider.dart | 12 ++++++------ .../lib/src/presentation/pages/payments_page.dart | 14 ++------------ .../presentation/widgets/payment_history_item.dart | 8 +------- 3 files changed, 9 insertions(+), 25 deletions(-) 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 3ffaf542..9712bfac 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 @@ -11,16 +11,16 @@ class FullWidthDivider extends StatelessWidget { @override Widget build(BuildContext context) { - final screenWidth = MediaQuery.of(context).size.width; + //final screenWidth = MediaQuery.of(context).size.width; return Column( children: [ const SizedBox(height: UiConstants.space10), - Transform.translate( - offset: const Offset(-UiConstants.space4, 0), - child: SizedBox(width: screenWidth, child: const Divider()), - ), - const SizedBox(height: UiConstants.space10), + // Transform.translate( + // 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/payments/lib/src/presentation/pages/payments_page.dart b/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart index b1ce9e4e..3de923e0 100644 --- a/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart +++ b/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart @@ -172,17 +172,7 @@ class _PaymentsPageState extends State { ), ], ), - const SizedBox(height: UiConstants.space4), - - // Pending Pay - if (state.summary.pendingEarnings > 0) - PendingPayCard( - amount: state.summary.pendingEarnings, - onCashOut: () { - Modular.to.pushNamed('${StaffPaths.payments}early-pay'); - }, - ), - const SizedBox(height: UiConstants.space6), + const SizedBox(height: UiConstants.space8), // Recent Payments if (state.history.isNotEmpty) @@ -191,7 +181,7 @@ class _PaymentsPageState extends State { children: [ Text( "Recent Payments", - style: UiTypography.body2m.textPrimary, + style: UiTypography.body1b, ), const SizedBox(height: UiConstants.space3), Column( diff --git a/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart b/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart index e068caee..99dba385 100644 --- a/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart +++ b/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart @@ -32,13 +32,7 @@ class PaymentHistoryItem extends StatelessWidget { decoration: BoxDecoration( color: UiColors.white, borderRadius: BorderRadius.circular(UiConstants.radiusBase), - boxShadow: [ - BoxShadow( - color: UiColors.black.withValues(alpha: 0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], + border: Border.all(color: UiColors.border, width: 0.5), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, From 38007d32bcf758052a86d65ccd8b406760b874ff Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 13:37:42 -0500 Subject: [PATCH 11/20] refactor: Enhance StaffPayment model and PaymentHistoryItem widget with shift details --- .../src/entities/financial/staff_payment.dart | 26 ++++++++++++++++++- .../payments_repository_impl.dart | 16 ++++++++++++ .../src/presentation/pages/payments_page.dart | 14 +++++----- .../widgets/payment_history_item.dart | 6 ++--- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/apps/mobile/packages/domain/lib/src/entities/financial/staff_payment.dart b/apps/mobile/packages/domain/lib/src/entities/financial/staff_payment.dart index d6126de8..75cd8d8e 100644 --- a/apps/mobile/packages/domain/lib/src/entities/financial/staff_payment.dart +++ b/apps/mobile/packages/domain/lib/src/entities/financial/staff_payment.dart @@ -28,6 +28,12 @@ class StaffPayment extends Equatable { required this.amount, required this.status, this.paidAt, + this.shiftTitle, + this.shiftLocation, + this.locationAddress, + this.hoursWorked, + this.hourlyRate, + this.workedTime, }); /// Unique identifier. final String id; @@ -47,6 +53,24 @@ class StaffPayment extends Equatable { /// When the payment was successfully processed. final DateTime? paidAt; + /// Title of the shift worked. + final String? shiftTitle; + + /// Location/hub name of the shift. + final String? shiftLocation; + + /// Address of the shift location. + final String? locationAddress; + + /// Number of hours worked. + final double? hoursWorked; + + /// Hourly rate for the shift. + final double? hourlyRate; + + /// Work session duration or status. + final String? workedTime; + @override - List get props => [id, staffId, assignmentId, amount, status, paidAt]; + List get props => [id, staffId, assignmentId, amount, status, paidAt, shiftTitle, shiftLocation, locationAddress, hoursWorked, hourlyRate, workedTime]; } \ No newline at end of file diff --git a/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart b/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart index 726a84b1..3c701b36 100644 --- a/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart +++ b/apps/mobile/packages/features/staff/payments/lib/src/data/repositories/payments_repository_impl.dart @@ -67,6 +67,16 @@ class PaymentsRepositoryImpl .execute(); return response.data.recentPayments.map((dc.ListRecentPaymentsByStaffIdRecentPayments payment) { + // Extract shift details from nested application structure + final String? shiftTitle = payment.application.shiftRole.shift.title; + final String? locationAddress = payment.application.shiftRole.shift.locationAddress; + final double? hoursWorked = payment.application.shiftRole.hours; + final double? hourlyRate = payment.application.shiftRole.role.costPerHour; + // Extract hub details from order + final String? locationHub = payment.invoice.order.teamHub.hubName; + final String? hubAddress = payment.invoice.order.teamHub.address; + final String? shiftLocation = locationAddress ?? hubAddress; + return StaffPayment( id: payment.id, staffId: payment.staffId, @@ -74,6 +84,12 @@ class PaymentsRepositoryImpl amount: payment.invoice.amount, status: PaymentAdapter.toPaymentStatus(payment.status?.stringValue ?? 'UNKNOWN'), paidAt: _service.toDateTime(payment.invoice.issueDate), + shiftTitle: shiftTitle, + shiftLocation: locationHub, + locationAddress: shiftLocation, + hoursWorked: hoursWorked, + hourlyRate: hourlyRate, + workedTime: payment.workedTime, ); }).toList(); }); diff --git a/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart b/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart index 3de923e0..b1ff94f3 100644 --- a/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart +++ b/apps/mobile/packages/features/staff/payments/lib/src/presentation/pages/payments_page.dart @@ -1,5 +1,4 @@ import 'package:design_system/design_system.dart'; -import 'package:krow_core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; @@ -10,7 +9,6 @@ import '../blocs/payments/payments_bloc.dart'; import '../blocs/payments/payments_event.dart'; import '../blocs/payments/payments_state.dart'; import '../widgets/payment_stats_card.dart'; -import '../widgets/pending_pay_card.dart'; import '../widgets/payment_history_item.dart'; import '../widgets/earnings_graph.dart'; @@ -191,16 +189,16 @@ class _PaymentsPageState extends State { bottom: UiConstants.space2), child: PaymentHistoryItem( amount: payment.amount, - title: "Shift Payment", - location: "Varies", - address: "Payment ID: ${payment.id}", + title: payment.shiftTitle ?? "Shift Payment", + location: payment.shiftLocation ?? "Varies", + address: payment.locationAddress ?? payment.id, date: payment.paidAt != null ? DateFormat('E, MMM d') .format(payment.paidAt!) : 'Pending', - workedTime: "Completed", - hours: 0, - rate: 0.0, + workedTime: payment.workedTime ?? "Completed", + hours: (payment.hoursWorked ?? 0).toInt(), + rate: payment.hourlyRate ?? 0.0, status: payment.status.name.toUpperCase(), ), ); diff --git a/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart b/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart index 99dba385..44fe3304 100644 --- a/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart +++ b/apps/mobile/packages/features/staff/payments/lib/src/presentation/widgets/payment_history_item.dart @@ -71,7 +71,7 @@ class PaymentHistoryItem extends StatelessWidget { borderRadius: BorderRadius.circular(UiConstants.radiusBase), ), child: const Icon( - UiIcons.chart, + UiIcons.dollar, color: UiColors.mutedForeground, size: 24, ), @@ -92,7 +92,7 @@ class PaymentHistoryItem extends StatelessWidget { children: [ Text( title, - style: UiTypography.body2b.textPrimary, + style: UiTypography.body2m, ), Text( location, @@ -106,7 +106,7 @@ class PaymentHistoryItem extends StatelessWidget { children: [ Text( "\$${amount.toStringAsFixed(0)}", - style: UiTypography.headline4m.textPrimary, + style: UiTypography.headline4b, ), Text( "\$${rate.toStringAsFixed(0)}/hr · ${hours}h", From e386c34b86abab2d9f782326b98cba16b10d4b00 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 13:58:21 -0500 Subject: [PATCH 12/20] Use shared CI keystore env vars; remove backup Standardize CI signing config and clean up Android build files: - Replace app-specific CodeMagic keystore env vars (CM_KEYSTORE_PATH_CLIENT/STAFF, CM_KEYSTORE_PASSWORD_CLIENT/STAFF, CM_KEY_ALIAS_CLIENT/STAFF, CM_KEY_PASSWORD_CLIENT/STAFF) with shared variables (CM_KEYSTORE_PATH, CM_KEYSTORE_PASSWORD, CM_KEY_ALIAS, CM_KEY_PASSWORD) in client and staff build.gradle.kts to unify CI configuration. - Remove stray TODO comment about applicationId in both build files (cleanup). - Adjust manifestPlaceholders placement in the client build file. - Delete a backup google-services.json_back from the staff app to remove an unnecessary/sensitive artifact. --- .../apps/client/android/app/build.gradle.kts | 12 +- .../apps/staff/android/app/build.gradle.kts | 9 +- .../android/app/google-services.json_back | 162 ------------------ codemagic.yaml | 12 +- 4 files changed, 15 insertions(+), 180 deletions(-) delete mode 100644 apps/mobile/apps/staff/android/app/google-services.json_back diff --git a/apps/mobile/apps/client/android/app/build.gradle.kts b/apps/mobile/apps/client/android/app/build.gradle.kts index f169e26c..323e6fd0 100644 --- a/apps/mobile/apps/client/android/app/build.gradle.kts +++ b/apps/mobile/apps/client/android/app/build.gradle.kts @@ -43,7 +43,6 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId = "com.krowwithus.client" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. @@ -51,18 +50,17 @@ android { targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName - - manifestPlaceholders["GOOGLE_MAPS_API_KEY"] = dartEnvironmentVariables["GOOGLE_MAPS_API_KEY"] ?: "" + manifestPlaceholders["GOOGLE_MAPS_API_KEY"] = dartEnvironmentVariables["GOOGLE_MAPS_API_KEY"] ?: "" } signingConfigs { create("release") { if (System.getenv()["CI"] == "true") { // CodeMagic CI environment - storeFile = file(System.getenv()["CM_KEYSTORE_PATH_CLIENT"] ?: "") - storePassword = System.getenv()["CM_KEYSTORE_PASSWORD_CLIENT"] - keyAlias = System.getenv()["CM_KEY_ALIAS_CLIENT"] - keyPassword = System.getenv()["CM_KEY_PASSWORD_CLIENT"] + storeFile = file(System.getenv()["CM_KEYSTORE_PATH"] ?: "") + storePassword = System.getenv()["CM_KEYSTORE_PASSWORD"] + keyAlias = System.getenv()["CM_KEY_ALIAS"] + keyPassword = System.getenv()["CM_KEY_PASSWORD"] } else { // Local development environment keyAlias = keystoreProperties["keyAlias"] as String? diff --git a/apps/mobile/apps/staff/android/app/build.gradle.kts b/apps/mobile/apps/staff/android/app/build.gradle.kts index 9e3968be..0f7dd24a 100644 --- a/apps/mobile/apps/staff/android/app/build.gradle.kts +++ b/apps/mobile/apps/staff/android/app/build.gradle.kts @@ -43,7 +43,6 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId = "com.krowwithus.staff" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. @@ -59,10 +58,10 @@ android { create("release") { if (System.getenv()["CI"] == "true") { // CodeMagic CI environment - storeFile = file(System.getenv()["CM_KEYSTORE_PATH_STAFF"] ?: "") - storePassword = System.getenv()["CM_KEYSTORE_PASSWORD_STAFF"] - keyAlias = System.getenv()["CM_KEY_ALIAS_STAFF"] - keyPassword = System.getenv()["CM_KEY_PASSWORD_STAFF"] + storeFile = file(System.getenv()["CM_KEYSTORE_PATH"] ?: "") + storePassword = System.getenv()["CM_KEYSTORE_PASSWORD"] + keyAlias = System.getenv()["CM_KEY_ALIAS"] + keyPassword = System.getenv()["CM_KEY_PASSWORD"] } else { // Local development environment keyAlias = keystoreProperties["keyAlias"] as String? diff --git a/apps/mobile/apps/staff/android/app/google-services.json_back b/apps/mobile/apps/staff/android/app/google-services.json_back deleted file mode 100644 index f4d57e10..00000000 --- a/apps/mobile/apps/staff/android/app/google-services.json_back +++ /dev/null @@ -1,162 +0,0 @@ -{ - "project_info": { - "project_number": "933560802882", - "project_id": "krow-workforce-dev", - "storage_bucket": "krow-workforce-dev.firebasestorage.app" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db", - "android_client_info": { - "package_name": "com.krow.app.business.dev" - } - }, - "oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "com.krow.app.staff.dev" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:933560802882:android:d49b8c0f4d19e95e7757db", - "android_client_info": { - "package_name": "com.krow.app.staff.dev" - } - }, - "oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "com.krow.app.staff.dev" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:933560802882:android:da13569105659ead7757db", - "android_client_info": { - "package_name": "com.krowwithus.client" - } - }, - "oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "com.krow.app.staff.dev" - } - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:933560802882:android:1ae05d85c865f77c7757db", - "android_client_info": { - "package_name": "com.krowwithus.staff" - } - }, - "oauth_client": [ - { - "client_id": "933560802882-ikdfv3o5f47g36qqgvfq55o4m19n7gk4.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.krowwithus.staff", - "certificate_hash": "ac917ae8470ab29f1107c773c6017ff5ea5d102d" - } - }, - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "com.krow.app.staff.dev" - } - } - ] - } - } - } - ], - "configuration_version": "1" -} \ No newline at end of file diff --git a/codemagic.yaml b/codemagic.yaml index d853fbba..ad48ef42 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -175,7 +175,7 @@ workflows: groups: - client_app_dev_credentials android_signing: - - keystore: krow_client_dev + - keystore: KROW_CLIENT_DEV keystore_environment_variable: CM_KEYSTORE_PATH_CLIENT keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_CLIENT key_alias_environment_variable: CM_KEY_ALIAS_CLIENT @@ -196,7 +196,7 @@ workflows: groups: - client_app_staging_credentials android_signing: - - keystore: krow_client_staging + - keystore: KROW_CLIENT_STAGING keystore_environment_variable: CM_KEYSTORE_PATH_CLIENT keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_CLIENT key_alias_environment_variable: CM_KEY_ALIAS_CLIENT @@ -214,7 +214,7 @@ workflows: groups: - client_app_prod_credentials android_signing: - - keystore: krow_client_prod + - keystore: KROW_CLIENT_PROD keystore_environment_variable: CM_KEYSTORE_PATH_CLIENT keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_CLIENT key_alias_environment_variable: CM_KEY_ALIAS_CLIENT @@ -277,7 +277,7 @@ workflows: groups: - staff_app_dev_credentials android_signing: - - keystore: krow_staff_dev + - keystore: KROW_STAFF_DEV keystore_environment_variable: CM_KEYSTORE_PATH_STAFF keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_STAFF key_alias_environment_variable: CM_KEY_ALIAS_STAFF @@ -298,7 +298,7 @@ workflows: groups: - staff_app_staging_credentials android_signing: - - keystore: krow_staff_staging + - keystore: KROW_STAFF_STAGING keystore_environment_variable: CM_KEYSTORE_PATH_STAFF keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_STAFF key_alias_environment_variable: CM_KEY_ALIAS_STAFF @@ -319,7 +319,7 @@ workflows: groups: - staff_app_prod_credentials android_signing: - - keystore: krow_staff_prod + - keystore: KROW_STAFF_PROD keystore_environment_variable: CM_KEYSTORE_PATH_STAFF keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_STAFF key_alias_environment_variable: CM_KEY_ALIAS_STAFF From 7442030e46e3c427a4b4c6562914497e0a1e2cd4 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 13:58:57 -0500 Subject: [PATCH 13/20] Update codemagic.yaml --- codemagic.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/codemagic.yaml b/codemagic.yaml index ad48ef42..1905ad2d 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -176,10 +176,6 @@ workflows: - client_app_dev_credentials android_signing: - keystore: KROW_CLIENT_DEV - keystore_environment_variable: CM_KEYSTORE_PATH_CLIENT - keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_CLIENT - key_alias_environment_variable: CM_KEY_ALIAS_CLIENT - key_password_environment_variable: CM_KEY_PASSWORD_CLIENT vars: ENV: dev scripts: @@ -197,10 +193,6 @@ workflows: - client_app_staging_credentials android_signing: - keystore: KROW_CLIENT_STAGING - keystore_environment_variable: CM_KEYSTORE_PATH_CLIENT - keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_CLIENT - key_alias_environment_variable: CM_KEY_ALIAS_CLIENT - key_password_environment_variable: CM_KEY_PASSWORD_CLIENT vars: ENV: staging scripts: From a56d8e5fd601f88d69bf150b36d64523e747d3dc Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 14:10:25 -0500 Subject: [PATCH 14/20] Update pubspec.yaml --- apps/mobile/apps/client/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mobile/apps/client/pubspec.yaml b/apps/mobile/apps/client/pubspec.yaml index f9e3d656..7a71eecc 100644 --- a/apps/mobile/apps/client/pubspec.yaml +++ b/apps/mobile/apps/client/pubspec.yaml @@ -1,7 +1,7 @@ name: krowwithus_client description: "KROW Client Application" publish_to: "none" -version: 0.0.1-IlianaClientM3 +version: 0.0.1-IlianaClientM4 resolution: workspace environment: From da3bbb7056934cf45a2802fb6297bffd374482e4 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 14:27:20 -0500 Subject: [PATCH 15/20] Update Codemagic scripts and add M4 demo guide Normalize spacing in Codemagic job names (add space after emoji) and remove duplicated android_signing environment variable mappings for staff keystores across dev, staging, and prod workflows in codemagic.yaml. Add docs/MILESTONES/M4/demos/m4-client-note.md with the M4 demo guide (deliverables, test accounts, core improvements, and key deliverables). --- codemagic.yaml | 22 ++------ docs/MILESTONES/M4/demos/m4-client-note.md | 66 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 docs/MILESTONES/M4/demos/m4-client-note.md diff --git a/codemagic.yaml b/codemagic.yaml index 1905ad2d..3cfe50af 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -4,7 +4,7 @@ # Reusable script for building the Flutter app client-app-android-apk-build-script: &client-app-android-apk-build-script - name: 👷🤖 Build Client App APK (Android) + name: 👷 🤖 Build Client App APK (Android) script: | dart pub global activate melos export PATH="$PATH":"$HOME/.pub-cache/bin" @@ -12,7 +12,7 @@ client-app-android-apk-build-script: &client-app-android-apk-build-script make mobile-client-build PLATFORM=apk MODE=release client-app-ios-build-script: &client-app-ios-build-script - name: 👷🍎 Build Client App (iOS) + name: 👷 🍎 Build Client App (iOS) script: | dart pub global activate melos export PATH="$PATH":"$HOME/.pub-cache/bin" @@ -20,7 +20,7 @@ client-app-ios-build-script: &client-app-ios-build-script make mobile-client-build PLATFORM=ios MODE=release staff-app-android-apk-build-script: &staff-app-android-apk-build-script - name: 👷🤖 Build Staff App APK (Android) + name: 👷 🤖 Build Staff App APK (Android) script: | dart pub global activate melos export PATH="$PATH":"$HOME/.pub-cache/bin" @@ -28,7 +28,7 @@ staff-app-android-apk-build-script: &staff-app-android-apk-build-script make mobile-staff-build PLATFORM=apk MODE=release staff-app-ios-build-script: &staff-app-ios-build-script - name: 👷🍎 Build Staff App (iOS) + name: 👷 🍎 Build Staff App (iOS) script: | dart pub global activate melos export PATH="$PATH":"$HOME/.pub-cache/bin" @@ -37,7 +37,7 @@ staff-app-ios-build-script: &staff-app-ios-build-script # Reusable script for distributing Android to Firebase distribute-android-script: &distribute-android-script - name: 🚛🤖 Distribute Android to Firebase App Distribution + name: 🚛 🤖 Distribute Android to Firebase App Distribution script: | # Distribute Android APK # Note: Using wildcards to catch app-release.apk @@ -270,10 +270,6 @@ workflows: - staff_app_dev_credentials android_signing: - keystore: KROW_STAFF_DEV - keystore_environment_variable: CM_KEYSTORE_PATH_STAFF - keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_STAFF - key_alias_environment_variable: CM_KEY_ALIAS_STAFF - key_password_environment_variable: CM_KEY_PASSWORD_STAFF vars: ENV: dev scripts: @@ -291,10 +287,6 @@ workflows: - staff_app_staging_credentials android_signing: - keystore: KROW_STAFF_STAGING - keystore_environment_variable: CM_KEYSTORE_PATH_STAFF - keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_STAFF - key_alias_environment_variable: CM_KEY_ALIAS_STAFF - key_password_environment_variable: CM_KEY_PASSWORD_STAFF vars: ENV: staging scripts: @@ -312,10 +304,6 @@ workflows: - staff_app_prod_credentials android_signing: - keystore: KROW_STAFF_PROD - keystore_environment_variable: CM_KEYSTORE_PATH_STAFF - keystore_password_environment_variable: CM_KEYSTORE_PASSWORD_STAFF - key_alias_environment_variable: CM_KEY_ALIAS_STAFF - key_password_environment_variable: CM_KEY_PASSWORD_STAFF vars: ENV: prod scripts: diff --git a/docs/MILESTONES/M4/demos/m4-client-note.md b/docs/MILESTONES/M4/demos/m4-client-note.md new file mode 100644 index 00000000..4f8c668d --- /dev/null +++ b/docs/MILESTONES/M4/demos/m4-client-note.md @@ -0,0 +1,66 @@ +# KROW Workforce Platform — M4 Demo Guide + +**Version:** Milestone 4 (0.0.1-IlianaStaffM4 and 0.0.1-IlianaClientM4) +**Estimated Duration:** 25-30 minutes + +--- + +## 📦 Deliverables + +- **Client Mobile Application** (v0.0.1-IlianaClientM4) +- **Staff Mobile Application** (v0.0.1-IlianaStaffM4) +- **Full Demo Video** - Comprehensive walkthrough of all (M1 - M4) completed features of the mobile applications. + +--- + +## 1. Demo Overview + +### Core Improvements +M4 delivers three key areas of improvement: + +1. **Overall Application Improvements** + - Auth session persistence: Users stay signed in after reopening the app + - Stability fixes from M3 client feedback and dev team discoveries + - UI/UX improvements across key screens for clarity and speed + +2. **Client App Updates** + - Complete order creation flow (Rapid, Permanent, Recurring orders) + - Shift manager assignment support + - Paid/unpaid break handling in orders + - Complete Reports section (Daily Ops, Spend, Coverage, No-show, Performance) + - Cost centres in hubs for location/business unit tracking + - Billing approval workflow for pending bills + +3. **Staff App Updates** + - Profile completion requirements gating payments and clockings + - Worker benefits integration + - Enhanced shift discovery with filtering by location + - Spanish localization support + - AI-verified document uploads (Attire, Documents, Certificates) + - FAQ and Privacy Policy + - Worker profile visibility controls + +--- + +## 2. Required Test Accounts + +**Client Account (Business User):** +- Email: `legendary@krowd.com` +- Password: `Demo2026!` +- Client Name: "KROW" + +**Staff Account (Worker):** +- Phone: `+15557654321` +- OTP Code: `123456` (testing mode) +- Name: "Mariana Torres" + +--- + +## 3. M4 Key Deliverables + +✅ Stronger reliability and stability +✅ Completed client ordering and reporting workflows +✅ Better profile and shift tooling for staff +✅ AI-assisted document verification +✅ Localization support (Spanish) +✅ Improved billing and cost tracking controls From 01f4990e33cfd87114a94499b1e778fb94433b49 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 14:29:28 -0500 Subject: [PATCH 16/20] Update codemagic.yaml --- codemagic.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/codemagic.yaml b/codemagic.yaml index 3cfe50af..d90d8463 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -167,7 +167,7 @@ workflows: # ================================================================================= client-app-dev-android: <<: *client-app-base - name: 🚛🤖 Client App Dev (Android App Distribution) + name: 🚛 🤖 Client App Dev (Android App Distribution) environment: flutter: stable xcode: latest @@ -201,7 +201,7 @@ workflows: client-app-prod-android: <<: *client-app-base - name: 🚛🤖 Client App Prod (Android App Distribution) + name: 🚛 🤖 Client App Prod (Android App Distribution) environment: groups: - client_app_prod_credentials @@ -222,7 +222,7 @@ workflows: # ================================================================================= client-app-dev-ios: <<: *client-app-base - name: 🚛🍎 Client App Dev (iOS App Distribution) + name: 🚛 🍎 Client App Dev (iOS App Distribution) environment: groups: - client_app_dev_credentials @@ -234,7 +234,7 @@ workflows: client-app-staging-ios: <<: *client-app-base - name: 🚛🍎 Client App Staging (iOS App Distribution) + name: 🚛 🍎 Client App Staging (iOS App Distribution) environment: groups: - client_app_staging_credentials @@ -246,7 +246,7 @@ workflows: client-app-prod-ios: <<: *client-app-base - name: 🚛🍎 Client App Prod (iOS App Distribution) + name: 🚛 🍎 Client App Prod (iOS App Distribution) environment: groups: - client_app_prod_credentials @@ -261,7 +261,7 @@ workflows: # ================================================================================= staff-app-dev-android: <<: *staff-app-base - name: 🚛🤖👨‍🍳 Staff App Dev (Android App Distribution) + name: 🚛 🤖 👨‍🍳 Staff App Dev (Android App Distribution) environment: flutter: stable xcode: latest @@ -278,7 +278,7 @@ workflows: staff-app-staging-android: <<: *staff-app-base - name: 🚛🤖👨‍🍳 Staff App Staging (Android App Distribution) + name: 🚛 🤖 👨‍🍳 Staff App Staging (Android App Distribution) environment: flutter: stable xcode: latest @@ -295,7 +295,7 @@ workflows: staff-app-prod-android: <<: *staff-app-base - name: 🚛🤖👨‍🍳 Staff App Prod (Android App Distribution) + name: 🚛 🤖 👨‍🍳 Staff App Prod (Android App Distribution) environment: flutter: stable xcode: latest @@ -315,7 +315,7 @@ workflows: # ================================================================================= staff-app-dev-ios: <<: *staff-app-base - name: 🚛🍎👨‍🍳 Staff App Dev (iOS App Distribution) + name: 🚛 🍎 👨‍🍳 Staff App Dev (iOS App Distribution) environment: groups: - staff_app_dev_credentials @@ -327,7 +327,7 @@ workflows: staff-app-staging-ios: <<: *staff-app-base - name: 🚛🍎👨‍🍳 Staff App Staging (iOS App Distribution) + name: 🚛 🍎 👨‍🍳 Staff App Staging (iOS App Distribution) environment: groups: - staff_app_staging_credentials @@ -339,7 +339,7 @@ workflows: staff-app-prod-ios: <<: *staff-app-base - name: 🚛🍎👨‍🍳 Staff App Prod (iOS App Distribution) + name: 🚛 🍎 👨‍🍳 Staff App Prod (iOS App Distribution) environment: groups: - staff_app_prod_credentials From 020b541ed120c2c19efac779fa4e6db3407a44b5 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 14:34:47 -0500 Subject: [PATCH 17/20] Bump staff app version to IlianaStaffM4 Update apps/mobile/apps/staff/pubspec.yaml version from 0.0.1-IlianaStaffM3 to 0.0.1-IlianaStaffM4 to reflect the new staff app build/release. --- apps/mobile/apps/staff/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mobile/apps/staff/pubspec.yaml b/apps/mobile/apps/staff/pubspec.yaml index 457446fd..3f8491e4 100644 --- a/apps/mobile/apps/staff/pubspec.yaml +++ b/apps/mobile/apps/staff/pubspec.yaml @@ -1,7 +1,7 @@ name: krowwithus_staff description: "KROW Staff Application" publish_to: 'none' -version: 0.0.1-IlianaStaffM3 +version: 0.0.1-IlianaStaffM4 resolution: workspace environment: From 856e7545f6978001c56ab42c858ae74655203336 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 16:48:49 -0500 Subject: [PATCH 18/20] Implement profile completion checks in shift details flow and update UI accordingly --- .../staff_connector_repository_impl.dart | 1 - .../shift_details/shift_details_bloc.dart | 6 ++- .../shift_details/shift_details_state.dart | 5 ++- .../pages/shift_details_page.dart | 40 +++++++++++++------ .../shifts/lib/src/shift_details_module.dart | 11 +++++ .../shifts/lib/src/staff_shifts_module.dart | 20 +++++----- docs/MILESTONES/M4/demos/m4-client-note.md | 16 ++++++++ 7 files changed, 72 insertions(+), 27 deletions(-) diff --git a/apps/mobile/packages/data_connect/lib/src/connectors/staff/data/repositories/staff_connector_repository_impl.dart b/apps/mobile/packages/data_connect/lib/src/connectors/staff/data/repositories/staff_connector_repository_impl.dart index e5f0f4d5..770f1d68 100644 --- a/apps/mobile/packages/data_connect/lib/src/connectors/staff/data/repositories/staff_connector_repository_impl.dart +++ b/apps/mobile/packages/data_connect/lib/src/connectors/staff/data/repositories/staff_connector_repository_impl.dart @@ -20,7 +20,6 @@ class StaffConnectorRepositoryImpl implements StaffConnectorRepository { @override Future getProfileCompletion() async { - return true; return _service.run(() async { final String staffId = await _service.getStaffId(); diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_bloc.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_bloc.dart index 5d46c536..3f5357b3 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_bloc.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_bloc.dart @@ -1,5 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:krow_core/core.dart'; +import 'package:krow_data_connect/krow_data_connect.dart'; import '../../../domain/usecases/apply_for_shift_usecase.dart'; import '../../../domain/usecases/decline_shift_usecase.dart'; import '../../../domain/usecases/get_shift_details_usecase.dart'; @@ -12,11 +13,13 @@ class ShiftDetailsBloc extends Bloc final GetShiftDetailsUseCase getShiftDetails; final ApplyForShiftUseCase applyForShift; final DeclineShiftUseCase declineShift; + final GetProfileCompletionUseCase getProfileCompletion; ShiftDetailsBloc({ required this.getShiftDetails, required this.applyForShift, required this.declineShift, + required this.getProfileCompletion, }) : super(ShiftDetailsInitial()) { on(_onLoadDetails); on(_onBookShift); @@ -34,8 +37,9 @@ class ShiftDetailsBloc extends Bloc final shift = await getShiftDetails( GetShiftDetailsArguments(shiftId: event.shiftId, roleId: event.roleId), ); + final isProfileComplete = await getProfileCompletion(); if (shift != null) { - emit(ShiftDetailsLoaded(shift)); + emit(ShiftDetailsLoaded(shift, isProfileComplete: isProfileComplete)); } else { emit(const ShiftDetailsError("Shift not found")); } diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_state.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_state.dart index cf6cda49..b9a0fbeb 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_state.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shift_details/shift_details_state.dart @@ -14,10 +14,11 @@ class ShiftDetailsLoading extends ShiftDetailsState {} class ShiftDetailsLoaded extends ShiftDetailsState { final Shift shift; - const ShiftDetailsLoaded(this.shift); + final bool isProfileComplete; + const ShiftDetailsLoaded(this.shift, {this.isProfileComplete = false}); @override - List get props => [shift]; + List get props => [shift, isProfileComplete]; } class ShiftDetailsError extends ShiftDetailsState { 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 05449f48..06fd236f 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 @@ -125,6 +125,9 @@ class _ShiftDetailsPageState extends State { final Shift displayShift = widget.shift; final i18n = Translations.of(context).staff_shifts.shift_details; + final isProfileComplete = state is ShiftDetailsLoaded + ? state.isProfileComplete + : false; final duration = _calculateDuration(displayShift); final estimatedTotal = @@ -142,6 +145,16 @@ class _ShiftDetailsPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + if (!isProfileComplete) + Padding( + padding: const EdgeInsets.all(UiConstants.space6), + child: UiNoticeBanner( + title: 'Complete Your Account', + description: + 'Complete your account to book this shift and start earning', + icon: UiIcons.sparkles, + ), + ), ShiftDetailsHeader(shift: displayShift), const Divider(height: 1, thickness: 0.5), ShiftStatsRow( @@ -194,20 +207,21 @@ class _ShiftDetailsPageState extends State { ), ), ), - ShiftDetailsBottomBar( - shift: displayShift, - onApply: () => _bookShift(context, displayShift), - onDecline: () => BlocProvider.of( - context, - ).add(DeclineShiftDetailsEvent(displayShift.id)), - onAccept: () => - BlocProvider.of(context).add( - BookShiftDetailsEvent( - displayShift.id, - roleId: displayShift.roleId, + if (isProfileComplete) + ShiftDetailsBottomBar( + shift: displayShift, + onApply: () => _bookShift(context, displayShift), + onDecline: () => BlocProvider.of( + context, + ).add(DeclineShiftDetailsEvent(displayShift.id)), + onAccept: () => + BlocProvider.of(context).add( + BookShiftDetailsEvent( + displayShift.id, + roleId: displayShift.roleId, + ), ), - ), - ), + ), ], ), ); diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/shift_details_module.dart b/apps/mobile/packages/features/staff/shifts/lib/src/shift_details_module.dart index f22fc524..fba55262 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/shift_details_module.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/shift_details_module.dart @@ -1,4 +1,5 @@ import 'package:flutter_modular/flutter_modular.dart'; +import 'package:krow_data_connect/krow_data_connect.dart'; import 'domain/repositories/shifts_repository_interface.dart'; import 'data/repositories_impl/shifts_repository_impl.dart'; import 'domain/usecases/get_shift_details_usecase.dart'; @@ -14,11 +15,21 @@ class ShiftDetailsModule extends Module { // Repository i.add(ShiftsRepositoryImpl.new); + // StaffConnectorRepository for profile completion + i.addLazySingleton( + () => StaffConnectorRepositoryImpl(), + ); + // UseCases i.add(GetShiftDetailsUseCase.new); i.add(AcceptShiftUseCase.new); i.add(DeclineShiftUseCase.new); i.add(ApplyForShiftUseCase.new); + i.addLazySingleton( + () => GetProfileCompletionUseCase( + repository: i.get(), + ), + ); // Bloc i.add(ShiftDetailsBloc.new); diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/staff_shifts_module.dart b/apps/mobile/packages/features/staff/shifts/lib/src/staff_shifts_module.dart index 5934588f..09866f32 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/staff_shifts_module.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/staff_shifts_module.dart @@ -32,18 +32,18 @@ class StaffShiftsModule extends Module { ); // Repository - i.add(ShiftsRepositoryImpl.new); + i.addLazySingleton(ShiftsRepositoryImpl.new); // UseCases - i.add(GetMyShiftsUseCase.new); - i.add(GetAvailableShiftsUseCase.new); - i.add(GetPendingAssignmentsUseCase.new); - i.add(GetCancelledShiftsUseCase.new); - i.add(GetHistoryShiftsUseCase.new); - i.add(AcceptShiftUseCase.new); - i.add(DeclineShiftUseCase.new); - i.add(ApplyForShiftUseCase.new); - i.add(GetShiftDetailsUseCase.new); + i.addLazySingleton(GetMyShiftsUseCase.new); + i.addLazySingleton(GetAvailableShiftsUseCase.new); + i.addLazySingleton(GetPendingAssignmentsUseCase.new); + i.addLazySingleton(GetCancelledShiftsUseCase.new); + i.addLazySingleton(GetHistoryShiftsUseCase.new); + i.addLazySingleton(AcceptShiftUseCase.new); + i.addLazySingleton(DeclineShiftUseCase.new); + i.addLazySingleton(ApplyForShiftUseCase.new); + i.addLazySingleton(GetShiftDetailsUseCase.new); // Bloc i.add( diff --git a/docs/MILESTONES/M4/demos/m4-client-note.md b/docs/MILESTONES/M4/demos/m4-client-note.md index 4f8c668d..a12c7ea3 100644 --- a/docs/MILESTONES/M4/demos/m4-client-note.md +++ b/docs/MILESTONES/M4/demos/m4-client-note.md @@ -54,6 +54,22 @@ M4 delivers three key areas of improvement: - OTP Code: `123456` (testing mode) - Name: "Mariana Torres" +**Note on Profile Completion:** +When a staff user hasn't completed their profile, they see an empty/incomplete state on their home screen. Currently tracked sections to mark as complete: +- Profile Information (full name, email, phone, preferred locations) +- Emergency Contact + +Future sections can be added as mandatory, such as Tax Forms, Bank Account, Documents, Certificates, and Attires. + +**Profile Blocking Rules:** +When the profile is incomplete, the following features are blocked to encourage completion: +- Clock-in page is hidden +- Payments are blocked +- "My Shifts" and History sections are hidden +- Users can view available shifts but cannot book them + +This ensures we have all necessary information for compliance and payroll before workers are allowed to work. + --- ## 3. M4 Key Deliverables From 308105a1f99c69db90f68353b801de2f6c316733 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 4 Mar 2026 17:03:16 -0500 Subject: [PATCH 19/20] Update formatting for profile completion notes in M4 demo guide --- docs/MILESTONES/M4/demos/m4-client-note.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/MILESTONES/M4/demos/m4-client-note.md b/docs/MILESTONES/M4/demos/m4-client-note.md index a12c7ea3..effe4db9 100644 --- a/docs/MILESTONES/M4/demos/m4-client-note.md +++ b/docs/MILESTONES/M4/demos/m4-client-note.md @@ -54,14 +54,14 @@ M4 delivers three key areas of improvement: - OTP Code: `123456` (testing mode) - Name: "Mariana Torres" -**Note on Profile Completion:** +***Note on Profile Completion*** When a staff user hasn't completed their profile, they see an empty/incomplete state on their home screen. Currently tracked sections to mark as complete: - Profile Information (full name, email, phone, preferred locations) - Emergency Contact Future sections can be added as mandatory, such as Tax Forms, Bank Account, Documents, Certificates, and Attires. -**Profile Blocking Rules:** +***Profile Blocking Rules*** When the profile is incomplete, the following features are blocked to encourage completion: - Clock-in page is hidden - Payments are blocked From 034f4fa8711d45be4e2f66121137082b1b9207e2 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Thu, 5 Mar 2026 17:05:59 -0500 Subject: [PATCH 20/20] Update M4 demo guide title and section header for consistency --- docs/MILESTONES/M4/demos/m4-client-note.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/MILESTONES/M4/demos/m4-client-note.md b/docs/MILESTONES/M4/demos/m4-client-note.md index effe4db9..550282ca 100644 --- a/docs/MILESTONES/M4/demos/m4-client-note.md +++ b/docs/MILESTONES/M4/demos/m4-client-note.md @@ -1,4 +1,4 @@ -# KROW Workforce Platform — M4 Demo Guide +# KROW Workforce Platform — M4 Guide **Version:** Milestone 4 (0.0.1-IlianaStaffM4 and 0.0.1-IlianaClientM4) **Estimated Duration:** 25-30 minutes @@ -13,7 +13,7 @@ --- -## 1. Demo Overview +## 1. Overview ### Core Improvements M4 delivers three key areas of improvement: