feat: Implement staff profile completion feature with new repository and use case
This commit is contained in:
@@ -17,3 +17,8 @@ export 'src/services/mixins/session_handler_mixin.dart';
|
|||||||
|
|
||||||
export 'src/session/staff_session_store.dart';
|
export 'src/session/staff_session_store.dart';
|
||||||
export 'src/services/mixins/data_error_handler.dart';
|
export 'src/services/mixins/data_error_handler.dart';
|
||||||
|
|
||||||
|
// Export Staff Connector repositories and use cases
|
||||||
|
export 'src/connectors/staff/domain/repositories/staff_connector_repository.dart';
|
||||||
|
export 'src/connectors/staff/domain/usecases/get_profile_completion_usecase.dart';
|
||||||
|
export 'src/connectors/staff/data/repositories/staff_connector_repository_impl.dart';
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||||
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
|
|
||||||
|
import '../../domain/repositories/staff_connector_repository.dart';
|
||||||
|
|
||||||
|
/// Implementation of [StaffConnectorRepository].
|
||||||
|
///
|
||||||
|
/// Fetches staff-related data from the Data Connect backend using
|
||||||
|
/// the staff connector queries.
|
||||||
|
class StaffConnectorRepositoryImpl implements StaffConnectorRepository {
|
||||||
|
/// Creates a new [StaffConnectorRepositoryImpl].
|
||||||
|
///
|
||||||
|
/// Requires a [DataConnectService] instance for backend communication.
|
||||||
|
StaffConnectorRepositoryImpl({
|
||||||
|
DataConnectService? service,
|
||||||
|
}) : _service = service ?? DataConnectService.instance;
|
||||||
|
|
||||||
|
final DataConnectService _service;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> getProfileCompletion() async {
|
||||||
|
return _service.run(() async {
|
||||||
|
final String staffId = await _service.getStaffId();
|
||||||
|
|
||||||
|
final QueryResult<GetStaffProfileCompletionData,
|
||||||
|
GetStaffProfileCompletionVariables> response =
|
||||||
|
await _service.connector
|
||||||
|
.getStaffProfileCompletion(id: staffId)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final GetStaffProfileCompletionStaff? staff = response.data.staff;
|
||||||
|
final List<GetStaffProfileCompletionEmergencyContacts>
|
||||||
|
emergencyContacts = response.data.emergencyContacts;
|
||||||
|
final List<GetStaffProfileCompletionTaxForms> taxForms =
|
||||||
|
response.data.taxForms;
|
||||||
|
|
||||||
|
return _isProfileComplete(staff, emergencyContacts, taxForms);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if staff has experience data (skills or industries).
|
||||||
|
bool _hasExperience(GetStaffProfileCompletionStaff? staff) {
|
||||||
|
if (staff == null) return false;
|
||||||
|
final dynamic skills = staff.skills;
|
||||||
|
final dynamic industries = staff.industries;
|
||||||
|
return (skills is List && skills.isNotEmpty) ||
|
||||||
|
(industries is List && industries.isNotEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determines if the profile is complete based on all sections.
|
||||||
|
bool _isProfileComplete(
|
||||||
|
GetStaffProfileCompletionStaff? staff,
|
||||||
|
List<GetStaffProfileCompletionEmergencyContacts> emergencyContacts,
|
||||||
|
List<GetStaffProfileCompletionTaxForms> taxForms,
|
||||||
|
) {
|
||||||
|
return staff != null &&
|
||||||
|
emergencyContacts.isNotEmpty &&
|
||||||
|
taxForms.isNotEmpty &&
|
||||||
|
_hasExperience(staff);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/// Repository interface for staff connector queries.
|
||||||
|
///
|
||||||
|
/// This interface defines the contract for accessing staff-related data
|
||||||
|
/// from the backend via Data Connect.
|
||||||
|
abstract interface class StaffConnectorRepository {
|
||||||
|
/// Fetches whether the profile is complete for the current staff member.
|
||||||
|
///
|
||||||
|
/// Returns true if all required profile sections have been completed,
|
||||||
|
/// false otherwise.
|
||||||
|
///
|
||||||
|
/// Throws an exception if the query fails.
|
||||||
|
Future<bool> getProfileCompletion();
|
||||||
|
}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import '../repositories/profile_completion_repository.dart';
|
import '../repositories/staff_connector_repository.dart';
|
||||||
|
|
||||||
/// Use case for retrieving profile completion status.
|
/// Use case for retrieving staff profile completion status.
|
||||||
///
|
///
|
||||||
/// This use case encapsulates the business logic for determining whether
|
/// This use case encapsulates the business logic for determining whether
|
||||||
/// a staff member's profile is complete. It delegates to the repository
|
/// a staff member's profile is complete. It delegates to the repository
|
||||||
/// for data access.
|
/// for data access.
|
||||||
class GetProfileCompletionUsecase {
|
class GetProfileCompletionUseCase {
|
||||||
/// Creates a [GetProfileCompletionUsecase].
|
/// Creates a [GetProfileCompletionUseCase].
|
||||||
///
|
///
|
||||||
/// Requires a [ProfileCompletionRepositoryInterface] for data access.
|
/// Requires a [StaffConnectorRepository] for data access.
|
||||||
GetProfileCompletionUsecase({
|
GetProfileCompletionUseCase({
|
||||||
required ProfileCompletionRepositoryInterface repository,
|
required StaffConnectorRepository repository,
|
||||||
}) : _repository = repository;
|
}) : _repository = repository;
|
||||||
|
|
||||||
final ProfileCompletionRepositoryInterface _repository;
|
final StaffConnectorRepository _repository;
|
||||||
|
|
||||||
/// Executes the use case to get profile completion status.
|
/// Executes the use case to get profile completion status.
|
||||||
///
|
///
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
|
||||||
|
|
||||||
import 'package:staff_main/src/domain/repositories/profile_completion_repository.dart';
|
|
||||||
|
|
||||||
/// Implementation of [ProfileCompletionRepositoryInterface].
|
|
||||||
///
|
|
||||||
/// Fetches profile completion status from the Data Connect backend.
|
|
||||||
class ProfileCompletionRepositoryImpl implements ProfileCompletionRepositoryInterface {
|
|
||||||
/// Creates a new [ProfileCompletionRepositoryImpl].
|
|
||||||
///
|
|
||||||
/// Requires a [DataConnectService] instance for backend communication.
|
|
||||||
ProfileCompletionRepositoryImpl({
|
|
||||||
DataConnectService? service,
|
|
||||||
}) : _service = service ?? DataConnectService.instance;
|
|
||||||
|
|
||||||
final DataConnectService _service;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> getProfileCompletion() async {
|
|
||||||
return _service.run(() async {
|
|
||||||
final String staffId = await _service.getStaffId();
|
|
||||||
|
|
||||||
final response = await _service.connector
|
|
||||||
.getStaffProfileCompletion(id: staffId)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
final staff = response.data.staff;
|
|
||||||
final emergencyContacts = response.data.emergencyContacts;
|
|
||||||
final taxForms = response.data.taxForms;
|
|
||||||
|
|
||||||
return _isProfileComplete(staff, emergencyContacts, taxForms);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if staff has experience data (skills or industries).
|
|
||||||
bool _hasExperience(dynamic staff) {
|
|
||||||
if (staff == null) return false;
|
|
||||||
final skills = staff.skills;
|
|
||||||
final industries = staff.industries;
|
|
||||||
return (skills is List && skills.isNotEmpty) ||
|
|
||||||
(industries is List && industries.isNotEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determines if the profile is complete based on all sections.
|
|
||||||
bool _isProfileComplete(
|
|
||||||
dynamic staff,
|
|
||||||
List<dynamic> emergencyContacts,
|
|
||||||
List<dynamic> taxForms,
|
|
||||||
) {
|
|
||||||
return staff != null &&
|
|
||||||
emergencyContacts.isNotEmpty &&
|
|
||||||
taxForms.isNotEmpty &&
|
|
||||||
_hasExperience(staff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/// Repository interface for profile completion status queries.
|
|
||||||
///
|
|
||||||
/// This interface defines the contract for accessing profile completion data.
|
|
||||||
/// Implementations should fetch this data from the backend via Data Connect.
|
|
||||||
abstract interface class ProfileCompletionRepositoryInterface {
|
|
||||||
/// Fetches whether the profile is complete for the current staff member.
|
|
||||||
///
|
|
||||||
/// Returns true if all required profile sections have been completed,
|
|
||||||
/// false otherwise.
|
|
||||||
///
|
|
||||||
/// Throws an exception if the query fails.
|
|
||||||
Future<bool> getProfileCompletion();
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:krow_core/core.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:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:staff_main/src/domain/usecases/get_profile_completion_usecase.dart';
|
|
||||||
import 'package:staff_main/src/presentation/blocs/staff_main_state.dart';
|
import 'package:staff_main/src/presentation/blocs/staff_main_state.dart';
|
||||||
|
|
||||||
class StaffMainCubit extends Cubit<StaffMainState> implements Disposable {
|
class StaffMainCubit extends Cubit<StaffMainState> implements Disposable {
|
||||||
StaffMainCubit({
|
StaffMainCubit({
|
||||||
required GetProfileCompletionUsecase getProfileCompletionUsecase,
|
required GetProfileCompletionUseCase getProfileCompletionUsecase,
|
||||||
}) : _getProfileCompletionUsecase = getProfileCompletionUsecase,
|
}) : _getProfileCompletionUsecase = getProfileCompletionUsecase,
|
||||||
super(const StaffMainState()) {
|
super(const StaffMainState()) {
|
||||||
Modular.to.addListener(_onRouteChanged);
|
Modular.to.addListener(_onRouteChanged);
|
||||||
@@ -15,7 +15,7 @@ class StaffMainCubit extends Cubit<StaffMainState> implements Disposable {
|
|||||||
_loadProfileCompletion();
|
_loadProfileCompletion();
|
||||||
}
|
}
|
||||||
|
|
||||||
final GetProfileCompletionUsecase _getProfileCompletionUsecase;
|
final GetProfileCompletionUseCase _getProfileCompletionUsecase;
|
||||||
|
|
||||||
void _onRouteChanged() {
|
void _onRouteChanged() {
|
||||||
if (isClosed) return;
|
if (isClosed) return;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:krow_core/core.dart';
|
import 'package:krow_core/core.dart';
|
||||||
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
import 'package:staff_attire/staff_attire.dart';
|
import 'package:staff_attire/staff_attire.dart';
|
||||||
import 'package:staff_availability/staff_availability.dart';
|
import 'package:staff_availability/staff_availability.dart';
|
||||||
import 'package:staff_bank_account/staff_bank_account.dart';
|
import 'package:staff_bank_account/staff_bank_account.dart';
|
||||||
@@ -10,9 +11,6 @@ import 'package:staff_documents/staff_documents.dart';
|
|||||||
import 'package:staff_emergency_contact/staff_emergency_contact.dart';
|
import 'package:staff_emergency_contact/staff_emergency_contact.dart';
|
||||||
import 'package:staff_faqs/staff_faqs.dart';
|
import 'package:staff_faqs/staff_faqs.dart';
|
||||||
import 'package:staff_home/staff_home.dart';
|
import 'package:staff_home/staff_home.dart';
|
||||||
import 'package:staff_main/src/data/repositories/profile_completion_repository_impl.dart';
|
|
||||||
import 'package:staff_main/src/domain/repositories/profile_completion_repository.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/blocs/staff_main_cubit.dart';
|
||||||
import 'package:staff_main/src/presentation/pages/staff_main_page.dart';
|
import 'package:staff_main/src/presentation/pages/staff_main_page.dart';
|
||||||
import 'package:staff_payments/staff_payements.dart';
|
import 'package:staff_payments/staff_payements.dart';
|
||||||
@@ -27,17 +25,21 @@ import 'package:staff_time_card/staff_time_card.dart';
|
|||||||
class StaffMainModule extends Module {
|
class StaffMainModule extends Module {
|
||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
i.addSingleton<ProfileCompletionRepositoryInterface>(
|
// Register the StaffConnectorRepository from data_connect
|
||||||
ProfileCompletionRepositoryImpl.new,
|
i.addSingleton<StaffConnectorRepository>(
|
||||||
|
StaffConnectorRepositoryImpl.new,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Register the use case from data_connect
|
||||||
i.addSingleton(
|
i.addSingleton(
|
||||||
() => GetProfileCompletionUsecase(
|
() => GetProfileCompletionUseCase(
|
||||||
repository: i.get<ProfileCompletionRepositoryInterface>(),
|
repository: i.get<StaffConnectorRepository>(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
i.addSingleton(
|
|
||||||
|
i.add(
|
||||||
() => StaffMainCubit(
|
() => StaffMainCubit(
|
||||||
getProfileCompletionUsecase: i.get<GetProfileCompletionUsecase>(),
|
getProfileCompletionUsecase: i.get<GetProfileCompletionUseCase>(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user