From a34cc5b462bde8eb8f68e94cd7a4b7759b62af2b Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 10 Feb 2026 12:15:51 -0500 Subject: [PATCH] feat: Implement staff authentication as a Flutter Modular feature module, centralizing dependency injection and routing while refactoring imports for better modularity. --- .../staff/authentication/feature_manifest.md | 33 ----- .../pages/phone_verification_page.dart | 38 +++--- .../pages/profile_setup_page.dart | 36 +++--- .../widgets/common/auth_trouble_link.dart | 2 +- .../get_started_background.dart | 113 +++++++++--------- .../get_started_page/get_started_header.dart | 10 +- .../otp_verification/otp_resend_section.dart | 2 +- .../otp_verification_actions.dart | 3 +- .../otp_verification_header.dart | 2 +- .../phone_input/phone_input_actions.dart | 2 +- .../phone_input/phone_input_form_field.dart | 2 +- .../phone_input/phone_input_header.dart | 2 +- .../profile_setup_basic_info.dart | 2 +- .../profile_setup_experience.dart | 2 +- .../profile_setup_header.dart | 2 +- .../profile_setup_location.dart | 54 +++++---- .../lib/src/staff_authentication_module.dart | 83 +++++++++++++ .../lib/staff_authentication.dart | 88 +------------- .../staff/authentication/pubspec.yaml | 3 +- 19 files changed, 225 insertions(+), 254 deletions(-) delete mode 100644 apps/mobile/packages/features/staff/authentication/feature_manifest.md create mode 100644 apps/mobile/packages/features/staff/authentication/lib/src/staff_authentication_module.dart diff --git a/apps/mobile/packages/features/staff/authentication/feature_manifest.md b/apps/mobile/packages/features/staff/authentication/feature_manifest.md deleted file mode 100644 index cd530b30..00000000 --- a/apps/mobile/packages/features/staff/authentication/feature_manifest.md +++ /dev/null @@ -1,33 +0,0 @@ -# Feature Manifest: Staff Authentication - -## Overview -**Feature Name:** Staff Authentication & Onboarding -**Package Path:** `packages/features/staff/authentication` - -## Responsibilities -* Handle user sign-up and log-in via Phone Auth. -* Verify OTP codes. -* Manage the Onboarding Wizard for new staff. -* Persist onboarding progress. - -## Architecture -* **Domain**: - * `AuthRepositoryInterface` - * `SignInWithPhoneUseCase` - * `VerifyOtpUseCase` -* **Data**: - * `AuthRepositoryImpl` (uses `AuthRepositoryMock` from `krow_data_connect`) -* **Presentation**: - * `AuthBloc`: Manages auth state (phone, otp, user status). - * `OnboardingBloc`: Manages wizard steps. - * Pages: `GetStartedPage`, `PhoneVerificationPage`, `ProfileSetupPage`. - -## Dependencies -* `krow_domain`: User entities. -* `krow_data_connect`: Auth mocks. -* `design_system`: UI components. - -## Routes -* `/`: Get Started (Welcome) -* `/phone-verification`: OTP Entry -* `/profile-setup`: Onboarding Wizard 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 830ded01..8d8a9db1 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 @@ -1,3 +1,4 @@ +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'; @@ -49,9 +50,7 @@ class _PhoneVerificationPageState extends State { }) { final String normalized = phoneNumber.replaceAll(RegExp(r'\\D'), ''); if (normalized.length == 10) { - BlocProvider.of( - context, - ).add( + BlocProvider.of(context).add( AuthSignInRequested(phoneNumber: '+1$normalized', mode: widget.mode), ); } else { @@ -71,9 +70,7 @@ class _PhoneVerificationPageState extends State { required String otp, required String verificationId, }) { - BlocProvider.of( - context, - ).add( + BlocProvider.of(context).add( AuthOtpSubmitted( verificationId: verificationId, smsCode: otp, @@ -84,9 +81,9 @@ class _PhoneVerificationPageState extends State { /// Handles the request to resend the verification code using the phone number in the state. void _onResend({required BuildContext context}) { - BlocProvider.of(context).add( - AuthSignInRequested(mode: widget.mode), - ); + BlocProvider.of( + context, + ).add(AuthSignInRequested(mode: widget.mode)); } @override @@ -107,8 +104,9 @@ class _PhoneVerificationPageState extends State { state.mode == AuthMode.signup) { final String message = state.errorMessage ?? ''; if (message.contains('staff profile')) { - final ScaffoldMessengerState messenger = - ScaffoldMessenger.of(context); + final ScaffoldMessengerState messenger = ScaffoldMessenger.of( + context, + ); messenger.hideCurrentSnackBar(); messenger.showSnackBar( SnackBar( @@ -147,9 +145,9 @@ class _PhoneVerificationPageState extends State { centerTitle: true, showBackButton: true, onLeadingPressed: () { - BlocProvider.of(context).add( - AuthResetRequested(mode: widget.mode), - ); + BlocProvider.of( + context, + ).add(AuthResetRequested(mode: widget.mode)); Navigator.of(context).pop(); }, ), @@ -169,13 +167,13 @@ class _PhoneVerificationPageState extends State { verificationId: state.verificationId ?? '', ), ) - : PhoneInput( - state: state, - onSendCode: (String phoneNumber) => _onSendCode( - context: context, - phoneNumber: phoneNumber, + : PhoneInput( + state: state, + onSendCode: (String phoneNumber) => _onSendCode( + context: context, + phoneNumber: phoneNumber, + ), ), - ), ), ), ); diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/profile_setup_page.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/profile_setup_page.dart index 2f6a178c..8b0720cc 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/profile_setup_page.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/pages/profile_setup_page.dart @@ -1,15 +1,16 @@ +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' hide ModularWatchExtension; +import 'package:krow_core/core.dart'; + import '../blocs/profile_setup/profile_setup_bloc.dart'; import '../widgets/profile_setup_page/profile_setup_basic_info.dart'; -import '../widgets/profile_setup_page/profile_setup_location.dart'; import '../widgets/profile_setup_page/profile_setup_experience.dart'; import '../widgets/profile_setup_page/profile_setup_header.dart'; -import 'package:staff_authentication/staff_authentication.dart'; -import 'package:krow_core/core.dart'; +import '../widgets/profile_setup_page/profile_setup_location.dart'; /// Page for setting up the user profile after authentication. class ProfileSetupPage extends StatefulWidget { @@ -106,7 +107,8 @@ class _ProfileSetupPageState extends State { } }, builder: (BuildContext context, ProfileSetupState state) { - final bool isCreatingProfile = state.status == ProfileSetupStatus.loading; + final bool isCreatingProfile = + state.status == ProfileSetupStatus.loading; return Scaffold( body: SafeArea( @@ -125,7 +127,10 @@ class _ProfileSetupPageState extends State { // Step Indicators UiStepIndicator( stepIcons: steps - .map((Map step) => step['icon'] as IconData) + .map( + (Map step) => + step['icon'] as IconData, + ) .toList(), currentStep: _currentStep, ), @@ -211,9 +216,10 @@ class _ProfileSetupPageState extends State { return ProfileSetupLocation( preferredLocations: state.preferredLocations, maxDistanceMiles: state.maxDistanceMiles, - onLocationsChanged: (List val) => BlocProvider.of( - context, - ).add(ProfileSetupLocationsChanged(val)), + onLocationsChanged: (List val) => + BlocProvider.of( + context, + ).add(ProfileSetupLocationsChanged(val)), onDistanceChanged: (double val) => BlocProvider.of( context, ).add(ProfileSetupDistanceChanged(val)), @@ -222,12 +228,14 @@ class _ProfileSetupPageState extends State { return ProfileSetupExperience( skills: state.skills, industries: state.industries, - onSkillsChanged: (List val) => BlocProvider.of( - context, - ).add(ProfileSetupSkillsChanged(val)), - onIndustriesChanged: (List val) => BlocProvider.of( - context, - ).add(ProfileSetupIndustriesChanged(val)), + onSkillsChanged: (List val) => + BlocProvider.of( + context, + ).add(ProfileSetupSkillsChanged(val)), + onIndustriesChanged: (List val) => + BlocProvider.of( + context, + ).add(ProfileSetupIndustriesChanged(val)), ); default: return const SizedBox.shrink(); diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/common/auth_trouble_link.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/common/auth_trouble_link.dart index 95b6dff8..13f07feb 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/common/auth_trouble_link.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/common/auth_trouble_link.dart @@ -1,6 +1,6 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A common widget that displays a "Having trouble? Contact Support" link. class AuthTroubleLink extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_background.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_background.dart index a3c0bafa..7c370683 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_background.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_background.dart @@ -1,76 +1,71 @@ -import 'package:flutter/material.dart'; import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; class GetStartedBackground extends StatelessWidget { const GetStartedBackground({super.key}); @override Widget build(BuildContext context) { - return Container( - child: Column( - children: [ - const SizedBox(height: 32), - // Logo - Image.asset( - UiImageAssets.logoBlue, - height: 40, - ), - Expanded( - child: Center( - child: Container( - width: 288, - height: 288, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color(0xFF3A4A5A).withOpacity(0.05), - ), - padding: const EdgeInsets.all(8.0), - child: ClipOval( - child: Image.network( - 'https://images.unsplash.com/photo-1577219491135-ce391730fb2c?w=400&h=400&fit=crop&crop=faces', - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) { - return Image.asset(UiImageAssets.logoBlue); - }, - ), + return Column( + children: [ + const SizedBox(height: 32), + // Logo + Image.asset(UiImageAssets.logoBlue, height: 40), + Expanded( + child: Center( + child: Container( + width: 288, + height: 288, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: const Color(0xFF3A4A5A).withOpacity(0.05), + ), + padding: const EdgeInsets.all(8.0), + child: ClipOval( + child: Image.network( + 'https://images.unsplash.com/photo-1577219491135-ce391730fb2c?w=400&h=400&fit=crop&crop=faces', + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Image.asset(UiImageAssets.logoBlue); + }, ), ), ), ), - // Pagination dots (Visual only) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 24, - height: 8, - decoration: BoxDecoration( - color: UiColors.primary, - borderRadius: BorderRadius.circular(4), - ), + ), + // Pagination dots (Visual only) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 24, + height: 8, + decoration: BoxDecoration( + color: UiColors.primary, + borderRadius: BorderRadius.circular(4), ), - const SizedBox(width: 8), - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: UiColors.primary.withOpacity(0.2), - borderRadius: BorderRadius.circular(4), - ), + ), + const SizedBox(width: 8), + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: UiColors.primary.withOpacity(0.2), + borderRadius: BorderRadius.circular(4), ), - const SizedBox(width: 8), - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: UiColors.primary.withOpacity(0.2), - borderRadius: BorderRadius.circular(4), - ), + ), + const SizedBox(width: 8), + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: UiColors.primary.withOpacity(0.2), + borderRadius: BorderRadius.circular(4), ), - ], - ), - ], - ), + ), + ], + ), + ], ); } } diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_header.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_header.dart index e2b37211..69a11986 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_header.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/get_started_page/get_started_header.dart @@ -1,6 +1,6 @@ -import 'package:flutter/material.dart'; +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; -import 'package:staff_authentication/staff_authentication.dart'; +import 'package:flutter/material.dart'; /// A widget that displays the welcome text and description on the Get Started page. class GetStartedHeader extends StatelessWidget { @@ -20,9 +20,7 @@ class GetStartedHeader extends StatelessWidget { text: TextSpan( style: UiTypography.displayM, children: [ - TextSpan( - text: i18n.title_part1, - ), + TextSpan(text: i18n.title_part1), TextSpan( text: i18n.title_part2, style: UiTypography.displayMb.textLink, @@ -39,4 +37,4 @@ class GetStartedHeader extends StatelessWidget { ], ); } -} \ No newline at end of file +} diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_resend_section.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_resend_section.dart index 12fadb8c..41793f03 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_resend_section.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_resend_section.dart @@ -1,6 +1,6 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget that handles the OTP resend logic and countdown timer. class OtpResendSection extends StatefulWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_actions.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_actions.dart index a307b6df..750a0cff 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_actions.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_actions.dart @@ -1,6 +1,7 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:staff_authentication/staff_authentication.dart'; + import '../../common/auth_trouble_link.dart'; /// A widget that displays the primary action button and trouble link for OTP verification. diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_header.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_header.dart index ec4ff79c..d3bcfa5e 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_header.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/otp_verification/otp_verification_header.dart @@ -1,6 +1,6 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget that displays the title and subtitle for the OTP Verification page. class OtpVerificationHeader extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_actions.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_actions.dart index dcbe0d06..b9ced284 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_actions.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_actions.dart @@ -1,7 +1,7 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:staff_authentication/src/presentation/widgets/common/auth_trouble_link.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget that displays the primary action button and trouble link for Phone Input. class PhoneInputActions extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_form_field.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_form_field.dart index dc29e107..9065f986 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_form_field.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_form_field.dart @@ -1,7 +1,7 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget that displays the phone number input field with country code. /// diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_header.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_header.dart index 5b86b6e3..1b607af4 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_header.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/phone_verification_page/phone_input/phone_input_header.dart @@ -1,6 +1,6 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget that displays the title and subtitle for the Phone Input page. class PhoneInputHeader extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_basic_info.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_basic_info.dart index 4d9ad36c..93adabd5 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_basic_info.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_basic_info.dart @@ -1,7 +1,7 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:staff_authentication/src/presentation/widgets/common/section_title_subtitle.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget for setting up basic profile information (photo, name, bio). class ProfileSetupBasicInfo extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_experience.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_experience.dart index ac4273c1..e834dd1e 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_experience.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_experience.dart @@ -1,8 +1,8 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:krow_domain/krow_domain.dart'; import 'package:staff_authentication/src/presentation/widgets/common/section_title_subtitle.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget for setting up skills and preferred industries. class ProfileSetupExperience extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_header.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_header.dart index 5f727d48..f4168b7d 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_header.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_header.dart @@ -1,6 +1,6 @@ +import 'package:core_localization/core_localization.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A header widget for the profile setup page showing back button and step count. class ProfileSetupHeader extends StatelessWidget { diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_location.dart b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_location.dart index 5ee01419..a9458571 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_location.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/src/presentation/widgets/profile_setup_page/profile_setup_location.dart @@ -1,10 +1,11 @@ import 'dart:async'; + +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:staff_authentication/src/presentation/blocs/profile_setup/profile_setup_bloc.dart'; import 'package:staff_authentication/src/presentation/widgets/common/section_title_subtitle.dart'; -import 'package:staff_authentication/staff_authentication.dart'; /// A widget for setting up preferred work locations and distance. class ProfileSetupLocation extends StatefulWidget { @@ -47,22 +48,23 @@ class _ProfileSetupLocationState extends State { void _onSearchChanged(String query) { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 300), () { - context - .read() - .add(ProfileSetupLocationQueryChanged(query)); + context.read().add( + ProfileSetupLocationQueryChanged(query), + ); }); } /// Adds the selected location. void _addLocation(String location) { if (location.isNotEmpty && !widget.preferredLocations.contains(location)) { - final List updatedList = - List.from(widget.preferredLocations)..add(location); + final List updatedList = List.from( + widget.preferredLocations, + )..add(location); widget.onLocationsChanged(updatedList); _locationController.clear(); - context - .read() - .add(const ProfileSetupClearLocationSuggestions()); + context.read().add( + const ProfileSetupClearLocationSuggestions(), + ); } } @@ -79,10 +81,16 @@ class _ProfileSetupLocationState extends State { // Search Input UiTextField( - label: t.staff_authentication.profile_setup_page.location + label: t + .staff_authentication + .profile_setup_page + .location .add_location_label, controller: _locationController, - hintText: t.staff_authentication.profile_setup_page.location + hintText: t + .staff_authentication + .profile_setup_page + .location .add_location_hint, onChanged: _onSearchChanged, ), @@ -99,15 +107,8 @@ class _ProfileSetupLocationState extends State { constraints: const BoxConstraints(maxHeight: 200), margin: const EdgeInsets.only(top: UiConstants.space2), decoration: BoxDecoration( - color: Theme.of(context).cardColor, + color: UiColors.cardViewBackground, borderRadius: UiConstants.radiusMd, - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], ), child: ListView.separated( shrinkWrap: true, @@ -167,12 +168,18 @@ class _ProfileSetupLocationState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - t.staff_authentication.profile_setup_page.location + t + .staff_authentication + .profile_setup_page + .location .min_dist_label, style: UiTypography.footnote1r.textSecondary, ), Text( - t.staff_authentication.profile_setup_page.location + t + .staff_authentication + .profile_setup_page + .location .max_dist_label, style: UiTypography.footnote1r.textSecondary, ), @@ -185,8 +192,9 @@ class _ProfileSetupLocationState extends State { /// Removes the specified [location] from the list. void _removeLocation({required String location}) { - final List updatedList = - List.from(widget.preferredLocations)..remove(location); + final List updatedList = List.from( + widget.preferredLocations, + )..remove(location); widget.onLocationsChanged(updatedList); } } diff --git a/apps/mobile/packages/features/staff/authentication/lib/src/staff_authentication_module.dart b/apps/mobile/packages/features/staff/authentication/lib/src/staff_authentication_module.dart new file mode 100644 index 00000000..ef1f34da --- /dev/null +++ b/apps/mobile/packages/features/staff/authentication/lib/src/staff_authentication_module.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_modular/flutter_modular.dart'; +import 'package:krow_core/core.dart'; +import 'package:krow_data_connect/krow_data_connect.dart'; +import 'package:firebase_auth/firebase_auth.dart' as firebase; +import 'package:staff_authentication/src/data/repositories_impl/auth_repository_impl.dart'; +import 'package:staff_authentication/src/domain/repositories/auth_repository_interface.dart'; +import 'package:staff_authentication/src/domain/usecases/sign_in_with_phone_usecase.dart'; +import 'package:staff_authentication/src/domain/usecases/verify_otp_usecase.dart'; +import 'package:staff_authentication/src/domain/repositories/profile_setup_repository.dart'; +import 'package:staff_authentication/src/data/repositories_impl/profile_setup_repository_impl.dart'; +import 'package:staff_authentication/src/domain/usecases/submit_profile_setup_usecase.dart'; +import 'package:staff_authentication/src/domain/repositories/place_repository.dart'; +import 'package:staff_authentication/src/data/repositories_impl/place_repository_impl.dart'; +import 'package:staff_authentication/src/domain/usecases/search_cities_usecase.dart'; +import 'package:staff_authentication/src/presentation/blocs/auth_bloc.dart'; +import 'package:staff_authentication/src/presentation/blocs/profile_setup/profile_setup_bloc.dart'; +import 'package:staff_authentication/src/presentation/pages/get_started_page.dart'; +import 'package:staff_authentication/src/presentation/pages/phone_verification_page.dart'; +import 'package:staff_authentication/src/presentation/pages/profile_setup_page.dart'; +import 'package:staff_authentication/src/domain/ui_entities/auth_mode.dart'; + +/// A [Module] for the staff authentication feature. +class StaffAuthenticationModule extends Module { + @override + List get imports => [DataConnectModule()]; + + @override + void binds(Injector i) { + // Repositories + i.addLazySingleton( + () => AuthRepositoryImpl( + firebaseAuth: firebase.FirebaseAuth.instance, + dataConnect: ExampleConnector.instance, + ), + ); + i.addLazySingleton( + () => ProfileSetupRepositoryImpl( + firebaseAuth: firebase.FirebaseAuth.instance, + dataConnect: ExampleConnector.instance, + ), + ); + i.addLazySingleton(PlaceRepositoryImpl.new); + + // UseCases + i.addLazySingleton(SignInWithPhoneUseCase.new); + i.addLazySingleton(VerifyOtpUseCase.new); + i.addLazySingleton(SubmitProfileSetup.new); + i.addLazySingleton(SearchCitiesUseCase.new); + + // BLoCs + i.addLazySingleton( + () => AuthBloc( + signInUseCase: i.get(), + verifyOtpUseCase: i.get(), + ), + ); + i.add( + () => ProfileSetupBloc( + submitProfileSetup: i.get(), + searchCities: i.get(), + ), + ); + } + + @override + void routes(RouteManager r) { + r.child(StaffPaths.root, child: (_) => const GetStartedPage()); + r.child( + StaffPaths.phoneVerification, + child: (BuildContext context) { + final Map? data = r.args.data; + final String? modeName = data?['mode']; + final AuthMode mode = AuthMode.values.firstWhere( + (AuthMode e) => e.name == modeName, + orElse: () => AuthMode.login, + ); + return PhoneVerificationPage(mode: mode); + }, + ); + r.child(StaffPaths.profileSetup, child: (_) => const ProfileSetupPage()); + } +} diff --git a/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart b/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart index f6265aff..6b4d54cc 100644 --- a/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart +++ b/apps/mobile/packages/features/staff/authentication/lib/staff_authentication.dart @@ -1,91 +1,5 @@ -library staff_authentication; - -import 'package:flutter/material.dart'; -import 'package:flutter_modular/flutter_modular.dart'; -import 'package:krow_core/core.dart'; -import 'package:krow_data_connect/krow_data_connect.dart'; -import 'package:firebase_auth/firebase_auth.dart' as firebase; -import 'package:staff_authentication/src/data/repositories_impl/auth_repository_impl.dart'; -import 'package:staff_authentication/src/domain/repositories/auth_repository_interface.dart'; -import 'package:staff_authentication/src/domain/usecases/sign_in_with_phone_usecase.dart'; -import 'package:staff_authentication/src/domain/usecases/verify_otp_usecase.dart'; -import 'package:staff_authentication/src/domain/repositories/profile_setup_repository.dart'; -import 'package:staff_authentication/src/data/repositories_impl/profile_setup_repository_impl.dart'; -import 'package:staff_authentication/src/domain/usecases/submit_profile_setup_usecase.dart'; -import 'package:staff_authentication/src/domain/repositories/place_repository.dart'; -import 'package:staff_authentication/src/data/repositories_impl/place_repository_impl.dart'; -import 'package:staff_authentication/src/domain/usecases/search_cities_usecase.dart'; -import 'package:staff_authentication/src/presentation/blocs/auth_bloc.dart'; -import 'package:staff_authentication/src/presentation/blocs/profile_setup/profile_setup_bloc.dart'; -import 'package:staff_authentication/src/presentation/pages/get_started_page.dart'; -import 'package:staff_authentication/src/presentation/pages/phone_verification_page.dart'; -import 'package:staff_authentication/src/presentation/pages/profile_setup_page.dart'; -import 'package:staff_authentication/src/domain/ui_entities/auth_mode.dart'; - export 'src/domain/ui_entities/auth_mode.dart'; export 'src/presentation/pages/get_started_page.dart'; export 'src/presentation/pages/phone_verification_page.dart'; export 'src/presentation/pages/profile_setup_page.dart'; -export 'package:core_localization/core_localization.dart'; - -/// A [Module] for the staff authentication feature. -class StaffAuthenticationModule extends Module { - @override - List get imports => [DataConnectModule()]; - - @override - void binds(Injector i) { - // Repositories - i.addLazySingleton( - () => AuthRepositoryImpl( - firebaseAuth: firebase.FirebaseAuth.instance, - dataConnect: ExampleConnector.instance, - ), - ); - i.addLazySingleton( - () => ProfileSetupRepositoryImpl( - firebaseAuth: firebase.FirebaseAuth.instance, - dataConnect: ExampleConnector.instance, - ), - ); - i.addLazySingleton(PlaceRepositoryImpl.new); - - // UseCases - i.addLazySingleton(SignInWithPhoneUseCase.new); - i.addLazySingleton(VerifyOtpUseCase.new); - i.addLazySingleton(SubmitProfileSetup.new); - i.addLazySingleton(SearchCitiesUseCase.new); - - // BLoCs - i.addLazySingleton( - () => AuthBloc( - signInUseCase: i.get(), - verifyOtpUseCase: i.get(), - ), - ); - i.add( - () => ProfileSetupBloc( - submitProfileSetup: i.get(), - searchCities: i.get(), - ), - ); - } - - @override - void routes(RouteManager r) { - r.child(StaffPaths.root, child: (_) => const GetStartedPage()); - r.child( - StaffPaths.phoneVerification, - child: (BuildContext context) { - final Map? data = r.args.data; - final String? modeName = data?['mode']; - final AuthMode mode = AuthMode.values.firstWhere( - (AuthMode e) => e.name == modeName, - orElse: () => AuthMode.login, - ); - return PhoneVerificationPage(mode: mode); - }, - ); - r.child(StaffPaths.profileSetup, child: (_) => const ProfileSetupPage()); - } -} +export 'src/staff_authentication_module.dart'; diff --git a/apps/mobile/packages/features/staff/authentication/pubspec.yaml b/apps/mobile/packages/features/staff/authentication/pubspec.yaml index 6a955e2e..966934ef 100644 --- a/apps/mobile/packages/features/staff/authentication/pubspec.yaml +++ b/apps/mobile/packages/features/staff/authentication/pubspec.yaml @@ -14,9 +14,8 @@ dependencies: flutter_bloc: ^8.1.0 flutter_modular: ^6.3.0 equatable: ^2.0.5 - lucide_icons: ^0.257.0 firebase_core: ^4.2.1 - firebase_auth: ^6.1.2 # Updated for compatibility + firebase_auth: ^6.1.2 firebase_data_connect: ^0.2.2+1 http: ^1.2.0