From c041796b382b44190d58c9daebdc6b39df882032 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 27 Jan 2026 00:36:24 -0500 Subject: [PATCH] Refactor updateStaffProfile method to accept staff ID and data map, and update PersonalInfoBloc to handle form values --- .../personal_info_repository_impl.dart | 30 +++++--- .../personal_info_repository_interface.dart | 4 +- .../update_personal_info_usecase.dart | 26 ++++++- .../blocs/personal_info_bloc.dart | 72 ++++++++----------- .../blocs/personal_info_state.dart | 8 ++- 5 files changed, 82 insertions(+), 58 deletions(-) diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart index 5e00ed64..b761c87c 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/data/repositories/personal_info_repository_impl.dart @@ -48,16 +48,28 @@ class PersonalInfoRepositoryImpl implements PersonalInfoRepositoryInterface { } @override - Future updateStaffProfile(Staff staff) async { - // Update staff data through Firebase Data Connect + Future updateStaffProfile({required String staffId, required Map data}) async { + // Start building the update mutation + var updateBuilder = _dataConnect.updateStaff(id: staffId); + + // Apply updates from map if present + if (data.containsKey('name')) { + updateBuilder = updateBuilder.fullName(data['name'] as String); + } + if (data.containsKey('email')) { + updateBuilder = updateBuilder.email(data['email'] as String); + } + if (data.containsKey('phone')) { + updateBuilder = updateBuilder.phone(data['phone'] as String?); + } + if (data.containsKey('avatar')) { + updateBuilder = updateBuilder.photoUrl(data['avatar'] as String?); + } + // Add other fields as they become available in the schema and map + + // Execute the update final OperationResult result = - await _dataConnect - .updateStaff(id: staff.id) - .fullName(staff.name) - .email(staff.email) - .phone(staff.phone) - .photoUrl(staff.avatar) - .execute(); + await updateBuilder.execute(); if (result.data.staff_update == null) { throw Exception('Failed to update staff profile'); diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/repositories/personal_info_repository_interface.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/repositories/personal_info_repository_interface.dart index 44ee5747..da0d595d 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/repositories/personal_info_repository_interface.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/repositories/personal_info_repository_interface.dart @@ -15,9 +15,9 @@ abstract interface class PersonalInfoRepositoryInterface { /// Updates the staff profile information. /// - /// Takes a [Staff] entity with updated fields and persists changes + /// Takes a [Staff] entity ID and updated fields map and persists changes /// through the data layer. Returns the updated [Staff] entity. - Future updateStaffProfile(Staff staff); + Future updateStaffProfile({required String staffId, required Map data}); /// Uploads a profile photo and returns the URL. /// diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/usecases/update_personal_info_usecase.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/usecases/update_personal_info_usecase.dart index ad30452e..5c5e5b27 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/usecases/update_personal_info_usecase.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/domain/usecases/update_personal_info_usecase.dart @@ -2,12 +2,29 @@ import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; import '../repositories/personal_info_repository_interface.dart'; +/// Arguments for updating staff profile information. +class UpdatePersonalInfoParams extends UseCaseArgument { + /// The staff member's ID. + final String staffId; + + /// The fields to update. + final Map data; + + const UpdatePersonalInfoParams({ + required this.staffId, + required this.data, + }); + + @override + List get props => [staffId, data]; +} + /// Use case for updating staff profile information. /// /// This use case updates the staff profile information /// through the repository, which delegates to the data_connect layer. class UpdatePersonalInfoUseCase - implements UseCase { + implements UseCase { final PersonalInfoRepositoryInterface _repository; /// Creates an [UpdatePersonalInfoUseCase]. @@ -16,7 +33,10 @@ class UpdatePersonalInfoUseCase UpdatePersonalInfoUseCase(this._repository); @override - Future call(Staff arguments) { - return _repository.updateStaffProfile(arguments); + Future call(UpdatePersonalInfoParams params) { + return _repository.updateStaffProfile( + staffId: params.staffId, + data: params.data, + ); } } diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_bloc.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_bloc.dart index c666dee5..582e6d92 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_bloc.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_bloc.dart @@ -1,6 +1,5 @@ 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'; import '../../domain/usecases/get_personal_info_usecase.dart'; @@ -41,9 +40,20 @@ class PersonalInfoBloc extends Bloc emit(state.copyWith(status: PersonalInfoStatus.loading)); try { final Staff staff = await _getPersonalInfoUseCase(); + + // Initialize form values from staff entity + final Map initialValues = { + 'name': staff.name, + 'email': staff.email, + 'phone': staff.phone, + 'address': staff.address, + 'avatar': staff.avatar, + }; + emit(state.copyWith( status: PersonalInfoStatus.loaded, staff: staff, + formValues: initialValues, )); } catch (e) { emit(state.copyWith( @@ -58,47 +68,9 @@ class PersonalInfoBloc extends Bloc PersonalInfoFieldUpdated event, Emitter emit, ) { - if (state.staff == null) return; - - final Staff updatedStaff = _updateField(state.staff!, event.field, event.value); - emit(state.copyWith(staff: updatedStaff)); - } - - /// Updates a specific field in the Staff entity. - /// - /// Returns a new Staff instance with the updated field. - Staff _updateField(Staff staff, String field, String value) { - // Note: Staff entity doesn't have a copyWith method or bio/languages/locations fields - // These fields would need to be added to the Staff entity or handled differently - // For now, we're just returning the same staff - // TODO: Add support for bio, languages, preferred locations to Staff entity - switch (field) { - case 'phone': - // Since Staff is immutable and doesn't have copyWith, we'd need to create a new instance - return Staff( - id: staff.id, - authProviderId: staff.authProviderId, - name: staff.name, - email: staff.email, - phone: value, - status: staff.status, - address: staff.address, - avatar: staff.avatar, - ); - case 'address': - return Staff( - id: staff.id, - authProviderId: staff.authProviderId, - name: staff.name, - email: staff.email, - phone: staff.phone, - status: staff.status, - address: value, - avatar: staff.avatar, - ); - default: - return staff; - } + final Map updatedValues = Map.from(state.formValues); + updatedValues[event.field] = event.value; + emit(state.copyWith(formValues: updatedValues)); } /// Handles saving staff profile information. @@ -111,11 +83,25 @@ class PersonalInfoBloc extends Bloc emit(state.copyWith(status: PersonalInfoStatus.saving)); try { final Staff updatedStaff = await _updatePersonalInfoUseCase( - state.staff!, + UpdatePersonalInfoParams( + staffId: state.staff!.id, + data: state.formValues, + ), ); + + // Update local state with the returned staff and keep form values in sync + final Map newValues = { + 'name': updatedStaff.name, + 'email': updatedStaff.email, + 'phone': updatedStaff.phone, + 'address': updatedStaff.address, + 'avatar': updatedStaff.avatar, + }; + emit(state.copyWith( status: PersonalInfoStatus.saved, staff: updatedStaff, + formValues: newValues, )); } catch (e) { emit(state.copyWith( diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_state.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_state.dart index 5641a4ed..c97a0931 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_state.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/presentation/blocs/personal_info_state.dart @@ -35,6 +35,9 @@ class PersonalInfoState extends Equatable { /// The staff profile information. final Staff? staff; + /// The form values being edited. + final Map formValues; + /// Error message if an error occurred. final String? errorMessage; @@ -42,6 +45,7 @@ class PersonalInfoState extends Equatable { const PersonalInfoState({ this.status = PersonalInfoStatus.initial, this.staff, + this.formValues = const {}, this.errorMessage, }); @@ -49,15 +53,17 @@ class PersonalInfoState extends Equatable { PersonalInfoState copyWith({ PersonalInfoStatus? status, Staff? staff, + Map? formValues, String? errorMessage, }) { return PersonalInfoState( status: status ?? this.status, staff: staff ?? this.staff, + formValues: formValues ?? this.formValues, errorMessage: errorMessage, ); } @override - List get props => [status, staff, errorMessage]; + List get props => [status, staff, formValues, errorMessage]; }