feat: Migrate staff profile features from Data Connect to V2 REST API
- Removed data_connect package from mobile pubspec.yaml. - Added documentation for V2 profile migration status and QA findings. - Implemented new session management with ClientSessionStore and StaffSessionStore. - Created V2SessionService for handling user sessions via the V2 API. - Developed use cases for cancelling late worker assignments and submitting worker reviews. - Added arguments and use cases for payment chart retrieval and profile completion checks. - Implemented repository interfaces and their implementations for staff main and profile features. - Ensured proper error handling and validation in use cases.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
import '../../domain/repositories/staff_main_repository_interface.dart';
|
||||
|
||||
/// V2 API implementation of [StaffMainRepositoryInterface].
|
||||
///
|
||||
/// Calls `GET /staff/profile-completion` and parses the response into a
|
||||
/// [ProfileCompletion] entity to determine completion status.
|
||||
class StaffMainRepositoryImpl implements StaffMainRepositoryInterface {
|
||||
/// Creates a [StaffMainRepositoryImpl].
|
||||
StaffMainRepositoryImpl({required BaseApiService apiService})
|
||||
: _apiService = apiService;
|
||||
|
||||
/// The API service used for network requests.
|
||||
final BaseApiService _apiService;
|
||||
|
||||
/// Fetches profile completion from the V2 API.
|
||||
///
|
||||
/// Returns `true` when all required profile sections are complete.
|
||||
/// Defaults to `true` on error so that navigation is not blocked.
|
||||
@override
|
||||
Future<bool> getProfileCompletion() async {
|
||||
try {
|
||||
final ApiResponse response = await _apiService.get(
|
||||
V2ApiEndpoints.staffProfileCompletion,
|
||||
);
|
||||
|
||||
if (response.data is Map<String, dynamic>) {
|
||||
final ProfileCompletion completion = ProfileCompletion.fromJson(
|
||||
response.data as Map<String, dynamic>,
|
||||
);
|
||||
return completion.completed;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (_) {
|
||||
// Allow full access on error to avoid blocking navigation.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/// Repository interface for staff main shell data access.
|
||||
///
|
||||
/// Provides profile-completion status used to gate bottom-bar tabs.
|
||||
abstract interface class StaffMainRepositoryInterface {
|
||||
/// Returns `true` when all required profile sections are complete.
|
||||
Future<bool> getProfileCompletion();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:staff_main/src/domain/repositories/staff_main_repository_interface.dart';
|
||||
|
||||
/// Use case for retrieving staff profile completion status.
|
||||
///
|
||||
/// Delegates to [StaffMainRepositoryInterface] for backend access and
|
||||
/// returns `true` when all required profile sections are complete.
|
||||
class GetProfileCompletionUseCase extends NoInputUseCase<bool> {
|
||||
/// Creates a [GetProfileCompletionUseCase].
|
||||
GetProfileCompletionUseCase({
|
||||
required StaffMainRepositoryInterface repository,
|
||||
}) : _repository = repository;
|
||||
|
||||
/// The repository used for data access.
|
||||
final StaffMainRepositoryInterface _repository;
|
||||
|
||||
/// Fetches whether the staff profile is complete.
|
||||
@override
|
||||
Future<bool> call() => _repository.getProfileCompletion();
|
||||
}
|
||||
@@ -1,26 +1,36 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:staff_main/src/domain/usecases/get_profile_completion_usecase.dart';
|
||||
import 'package:staff_main/src/presentation/blocs/staff_main_state.dart';
|
||||
|
||||
/// Cubit that manages the staff main shell state.
|
||||
///
|
||||
/// Tracks the active bottom-bar tab index, profile completion status, and
|
||||
/// bottom bar visibility based on the current route.
|
||||
class StaffMainCubit extends Cubit<StaffMainState> implements Disposable {
|
||||
/// Creates a [StaffMainCubit].
|
||||
StaffMainCubit({
|
||||
required GetProfileCompletionUseCase getProfileCompletionUsecase,
|
||||
}) : _getProfileCompletionUsecase = getProfileCompletionUsecase,
|
||||
super(const StaffMainState()) {
|
||||
}) : _getProfileCompletionUsecase = getProfileCompletionUsecase,
|
||||
super(const StaffMainState()) {
|
||||
Modular.to.addListener(_onRouteChanged);
|
||||
_onRouteChanged();
|
||||
}
|
||||
|
||||
/// The use case for checking profile completion.
|
||||
final GetProfileCompletionUseCase _getProfileCompletionUsecase;
|
||||
|
||||
/// Guard flag to prevent concurrent profile-completion fetches.
|
||||
bool _isLoadingCompletion = false;
|
||||
|
||||
/// Routes that should hide the bottom navigation bar.
|
||||
static const List<String> _hideBottomPaths = <String>[
|
||||
StaffPaths.benefits,
|
||||
];
|
||||
|
||||
/// Listener invoked whenever the Modular route changes.
|
||||
void _onRouteChanged() {
|
||||
if (isClosed) return;
|
||||
|
||||
@@ -46,18 +56,19 @@ class StaffMainCubit extends Cubit<StaffMainState> implements Disposable {
|
||||
|
||||
final bool showBottomBar = !_hideBottomPaths.any(path.contains);
|
||||
|
||||
if (newIndex != state.currentIndex || showBottomBar != state.showBottomBar) {
|
||||
if (newIndex != state.currentIndex ||
|
||||
showBottomBar != state.showBottomBar) {
|
||||
emit(state.copyWith(currentIndex: newIndex, showBottomBar: showBottomBar));
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads the profile completion status.
|
||||
/// Loads the profile completion status from the V2 API.
|
||||
Future<void> refreshProfileCompletion() async {
|
||||
if (_isLoadingCompletion || isClosed) return;
|
||||
|
||||
_isLoadingCompletion = true;
|
||||
try {
|
||||
final isComplete = await _getProfileCompletionUsecase();
|
||||
final bool isComplete = await _getProfileCompletionUsecase();
|
||||
if (!isClosed) {
|
||||
emit(state.copyWith(isProfileComplete: isComplete));
|
||||
}
|
||||
@@ -72,6 +83,7 @@ class StaffMainCubit extends Cubit<StaffMainState> implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Navigates to the tab at [index].
|
||||
void navigateToTab(int index) {
|
||||
if (index == state.currentIndex) return;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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:krow_domain/krow_domain.dart' show BaseApiService;
|
||||
import 'package:staff_attire/staff_attire.dart';
|
||||
import 'package:staff_availability/staff_availability.dart';
|
||||
import 'package:staff_bank_account/staff_bank_account.dart';
|
||||
@@ -11,6 +11,9 @@ import 'package:staff_documents/staff_documents.dart';
|
||||
import 'package:staff_emergency_contact/staff_emergency_contact.dart';
|
||||
import 'package:staff_faqs/staff_faqs.dart';
|
||||
import 'package:staff_home/staff_home.dart';
|
||||
import 'package:staff_main/src/data/repositories/staff_main_repository_impl.dart';
|
||||
import 'package:staff_main/src/domain/repositories/staff_main_repository_interface.dart';
|
||||
import 'package:staff_main/src/domain/usecases/get_profile_completion_usecase.dart';
|
||||
import 'package:staff_main/src/presentation/blocs/staff_main_cubit.dart';
|
||||
import 'package:staff_main/src/presentation/pages/staff_main_page.dart';
|
||||
import 'package:staff_payments/staff_payements.dart';
|
||||
@@ -22,22 +25,32 @@ import 'package:staff_shifts/staff_shifts.dart';
|
||||
import 'package:staff_tax_forms/staff_tax_forms.dart';
|
||||
import 'package:staff_time_card/staff_time_card.dart';
|
||||
|
||||
/// The main module for the staff app shell.
|
||||
///
|
||||
/// Registers navigation routes for all staff features and provides
|
||||
/// profile-completion gating via [StaffMainCubit].
|
||||
class StaffMainModule extends Module {
|
||||
@override
|
||||
List<Module> get imports => <Module>[CoreModule()];
|
||||
|
||||
@override
|
||||
void binds(Injector i) {
|
||||
// Register the StaffConnectorRepository from data_connect
|
||||
i.addLazySingleton<StaffConnectorRepository>(
|
||||
StaffConnectorRepositoryImpl.new,
|
||||
);
|
||||
|
||||
// Register the use case from data_connect
|
||||
i.addLazySingleton(
|
||||
() => GetProfileCompletionUseCase(
|
||||
repository: i.get<StaffConnectorRepository>(),
|
||||
// Repository backed by V2 REST API
|
||||
i.addLazySingleton<StaffMainRepositoryInterface>(
|
||||
() => StaffMainRepositoryImpl(
|
||||
apiService: i.get<BaseApiService>(),
|
||||
),
|
||||
);
|
||||
|
||||
i.add(
|
||||
|
||||
// Use case for profile completion check
|
||||
i.addLazySingleton<GetProfileCompletionUseCase>(
|
||||
() => GetProfileCompletionUseCase(
|
||||
repository: i.get<StaffMainRepositoryInterface>(),
|
||||
),
|
||||
);
|
||||
|
||||
// Main shell cubit
|
||||
i.add<StaffMainCubit>(
|
||||
() => StaffMainCubit(
|
||||
getProfileCompletionUsecase: i.get<GetProfileCompletionUseCase>(),
|
||||
),
|
||||
|
||||
@@ -22,8 +22,8 @@ dependencies:
|
||||
path: ../../../core_localization
|
||||
krow_core:
|
||||
path: ../../../core
|
||||
krow_data_connect:
|
||||
path: ../../../data_connect
|
||||
krow_domain:
|
||||
path: ../../../domain
|
||||
|
||||
# Features
|
||||
staff_home:
|
||||
|
||||
Reference in New Issue
Block a user