From 17423c5d66c05faf4e3a220976be37e7b6533072 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Mon, 16 Feb 2026 16:54:20 -0500 Subject: [PATCH] feat: Refactor repositories to utilize DataConnectService and remove FirebaseAuth dependency --- .../attire/lib/src/attire_module.dart | 7 +-- .../attire_repository_impl.dart | 30 +++++++------ .../emergency_contact_repository_impl.dart | 42 +++++------------- .../src/staff_emergency_contact_module.dart | 8 +--- .../experience_repository_impl.dart | 43 +++++++------------ .../lib/staff_profile_experience.dart | 6 +-- .../personal_info_repository_impl.dart | 41 ++++++++---------- .../lib/src/staff_profile_info_module.dart | 8 +--- 8 files changed, 69 insertions(+), 116 deletions(-) diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/attire_module.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/attire_module.dart index 7da0bc6a..7937e0c1 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/attire_module.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/attire_module.dart @@ -1,6 +1,5 @@ import 'package:flutter_modular/flutter_modular.dart'; import 'package:krow_core/core.dart'; -import 'package:krow_data_connect/krow_data_connect.dart'; import 'data/repositories_impl/attire_repository_impl.dart'; import 'domain/repositories/attire_repository.dart'; @@ -14,10 +13,8 @@ class StaffAttireModule extends Module { @override void binds(Injector i) { // Repository - i.addLazySingleton( - () => AttireRepositoryImpl(ExampleConnector.instance), - ); - + i.addLazySingleton(AttireRepositoryImpl.new); + // Use Cases i.addLazySingleton(GetAttireOptionsUseCase.new); i.addLazySingleton(SaveAttireUseCase.new); diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart index aec7ee03..cff32f53 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart @@ -6,24 +6,30 @@ import '../../domain/repositories/attire_repository.dart'; /// Implementation of [AttireRepository]. /// -/// Delegates data access to [ExampleConnector] from `data_connect`. +/// Delegates data access to [DataConnectService]. class AttireRepositoryImpl implements AttireRepository { - /// The Data Connect connector instance. - final ExampleConnector _connector; + /// The Data Connect service. + final DataConnectService _service; /// Creates an [AttireRepositoryImpl]. - AttireRepositoryImpl(this._connector); + AttireRepositoryImpl({DataConnectService? service}) + : _service = service ?? DataConnectService.instance; @override Future> getAttireOptions() async { - final QueryResult result = await _connector.listAttireOptions().execute(); - return result.data.attireOptions.map((ListAttireOptionsAttireOptions e) => AttireItem( - id: e.itemId, - label: e.label, - iconName: e.icon, - imageUrl: e.imageUrl, - isMandatory: e.isMandatory ?? false, - )).toList(); + return _service.run(() async { + final QueryResult result = + await _service.connector.listAttireOptions().execute(); + return result.data.attireOptions + .map((ListAttireOptionsAttireOptions e) => AttireItem( + id: e.itemId, + label: e.label, + iconName: e.icon, + imageUrl: e.imageUrl, + isMandatory: e.isMandatory ?? false, + )) + .toList(); + }); } @override diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart index c3ec4792..afea63f9 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/data/repositories/emergency_contact_repository_impl.dart @@ -1,4 +1,3 @@ -import 'package:firebase_auth/firebase_auth.dart'; import 'package:krow_data_connect/krow_data_connect.dart' as dc; import 'package:krow_domain/krow_domain.dart'; import '../../domain/repositories/emergency_contact_repository_interface.dart'; @@ -7,38 +6,19 @@ import '../../domain/repositories/emergency_contact_repository_interface.dart'; /// /// This repository delegates data operations to Firebase Data Connect. class EmergencyContactRepositoryImpl - with dc.DataErrorHandler implements EmergencyContactRepositoryInterface { - final dc.ExampleConnector _dataConnect; - final FirebaseAuth _firebaseAuth; + final dc.DataConnectService _service; /// Creates an [EmergencyContactRepositoryImpl]. EmergencyContactRepositoryImpl({ - required dc.ExampleConnector dataConnect, - required FirebaseAuth firebaseAuth, - }) : _dataConnect = dataConnect, - _firebaseAuth = firebaseAuth; - - Future _getStaffId() async { - final user = _firebaseAuth.currentUser; - if (user == null) { - throw const NotAuthenticatedException( - technicalMessage: 'User not authenticated'); - } - - final result = - await _dataConnect.getStaffByUserId(userId: user.uid).execute(); - if (result.data.staffs.isEmpty) { - throw const ServerException(technicalMessage: 'Staff profile not found'); - } - return result.data.staffs.first.id; - } + dc.DataConnectService? service, + }) : _service = service ?? dc.DataConnectService.instance; @override Future> getContacts() async { - return executeProtected(() async { - final staffId = await _getStaffId(); - final result = await _dataConnect + return _service.run(() async { + final staffId = await _service.getStaffId(); + final result = await _service.connector .getEmergencyContactsByStaffId(staffId: staffId) .execute(); @@ -55,11 +35,11 @@ class EmergencyContactRepositoryImpl @override Future saveContacts(List contacts) async { - return executeProtected(() async { - final staffId = await _getStaffId(); + return _service.run(() async { + final staffId = await _service.getStaffId(); // 1. Get existing to delete - final existingResult = await _dataConnect + final existingResult = await _service.connector .getEmergencyContactsByStaffId(staffId: staffId) .execute(); final existingIds = @@ -67,7 +47,7 @@ class EmergencyContactRepositoryImpl // 2. Delete all existing await Future.wait(existingIds.map( - (id) => _dataConnect.deleteEmergencyContact(id: id).execute())); + (id) => _service.connector.deleteEmergencyContact(id: id).execute())); // 3. Create new await Future.wait(contacts.map((contact) { @@ -87,7 +67,7 @@ class EmergencyContactRepositoryImpl break; } - return _dataConnect + return _service.connector .createEmergencyContact( name: contact.name, phone: contact.phone, diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/staff_emergency_contact_module.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/staff_emergency_contact_module.dart index 5dfb7a30..3f7bea36 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/staff_emergency_contact_module.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/emergency_contact/lib/src/staff_emergency_contact_module.dart @@ -1,6 +1,5 @@ -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_modular/flutter_modular.dart'; -import 'package:krow_data_connect/krow_data_connect.dart'; + import 'data/repositories/emergency_contact_repository_impl.dart'; import 'domain/repositories/emergency_contact_repository_interface.dart'; import 'domain/usecases/get_emergency_contacts_usecase.dart'; @@ -13,10 +12,7 @@ class StaffEmergencyContactModule extends Module { void binds(Injector i) { // Repository i.addLazySingleton( - () => EmergencyContactRepositoryImpl( - dataConnect: ExampleConnector.instance, - firebaseAuth: FirebaseAuth.instance, - ), + EmergencyContactRepositoryImpl.new, ); // UseCases diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart index 159dd31f..4b104d82 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/src/data/repositories/experience_repository_impl.dart @@ -1,42 +1,31 @@ -import 'package:firebase_auth/firebase_auth.dart'; import 'package:krow_data_connect/krow_data_connect.dart' as dc; -import '../../domain/repositories/experience_repository_interface.dart'; - import 'package:krow_domain/krow_domain.dart'; +import '../../domain/repositories/experience_repository_interface.dart'; + /// Implementation of [ExperienceRepositoryInterface] that delegates to Data Connect. -class ExperienceRepositoryImpl - with dc.DataErrorHandler - implements ExperienceRepositoryInterface { - final dc.ExampleConnector _dataConnect; - // ignore: unused_field - final FirebaseAuth _firebaseAuth; +class ExperienceRepositoryImpl implements ExperienceRepositoryInterface { + final dc.DataConnectService _service; - /// Creates a [ExperienceRepositoryImpl] using Data Connect and Auth. + /// Creates a [ExperienceRepositoryImpl] using Data Connect Service. ExperienceRepositoryImpl({ - required dc.ExampleConnector dataConnect, - required FirebaseAuth firebaseAuth, - }) : _dataConnect = dataConnect, - _firebaseAuth = firebaseAuth; + dc.DataConnectService? service, + }) : _service = service ?? dc.DataConnectService.instance; - Future _getStaff() async { - final user = _firebaseAuth.currentUser; - if (user == null) { - throw const NotAuthenticatedException( - technicalMessage: 'User not authenticated'); - } + Future _getStaff() async { + final staffId = await _service.getStaffId(); final result = - await _dataConnect.getStaffByUserId(userId: user.uid).execute(); - if (result.data.staffs.isEmpty) { + await _service.connector.getStaffById(id: staffId).execute(); + if (result.data.staff == null) { throw const ServerException(technicalMessage: 'Staff profile not found'); } - return result.data.staffs.first; + return result.data.staff!; } @override Future> getIndustries() async { - return executeProtected(() async { + return _service.run(() async { final staff = await _getStaff(); return staff.industries ?? []; }); @@ -44,7 +33,7 @@ class ExperienceRepositoryImpl @override Future> getSkills() async { - return executeProtected(() async { + return _service.run(() async { final staff = await _getStaff(); return staff.skills ?? []; }); @@ -55,9 +44,9 @@ class ExperienceRepositoryImpl List industries, List skills, ) async { - return executeProtected(() async { + return _service.run(() async { final staff = await _getStaff(); - await _dataConnect + await _service.connector .updateStaff(id: staff.id) .industries(industries) .skills(skills) diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/staff_profile_experience.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/staff_profile_experience.dart index ab4c83e9..db83d59f 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/staff_profile_experience.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/experience/lib/staff_profile_experience.dart @@ -1,6 +1,5 @@ library staff_profile_experience; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:krow_data_connect/krow_data_connect.dart'; @@ -22,10 +21,7 @@ class StaffProfileExperienceModule extends Module { void binds(Injector i) { // Repository i.addLazySingleton( - () => ExperienceRepositoryImpl( - dataConnect: ExampleConnector.instance, - firebaseAuth: FirebaseAuth.instance, - ), + ExperienceRepositoryImpl.new, ); // UseCases 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 e2e4b5ba..439a3ba2 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 @@ -1,4 +1,3 @@ -import 'package:firebase_auth/firebase_auth.dart' as firebase_auth; import 'package:firebase_data_connect/firebase_data_connect.dart'; import 'package:krow_data_connect/krow_data_connect.dart'; import 'package:krow_domain/krow_domain.dart'; @@ -14,32 +13,24 @@ import '../../domain/repositories/personal_info_repository_interface.dart'; /// - Mapping between data_connect DTOs and domain entities /// - Containing no business logic class PersonalInfoRepositoryImpl - with DataErrorHandler implements PersonalInfoRepositoryInterface { - /// Creates a [PersonalInfoRepositoryImpl]. /// - /// Requires the Firebase Data Connect connector instance and Firebase Auth. + /// Requires the Firebase Data Connect service. PersonalInfoRepositoryImpl({ - required ExampleConnector dataConnect, - required firebase_auth.FirebaseAuth firebaseAuth, - }) : _dataConnect = dataConnect, - _firebaseAuth = firebaseAuth; - final ExampleConnector _dataConnect; - final firebase_auth.FirebaseAuth _firebaseAuth; + DataConnectService? service, + }) : _service = service ?? DataConnectService.instance; + + final DataConnectService _service; @override Future getStaffProfile() async { - return executeProtected(() async { - final firebase_auth.User? user = _firebaseAuth.currentUser; - if (user == null) { - throw NotAuthenticatedException( - technicalMessage: 'User not authenticated'); - } + return _service.run(() async { + final String uid = _service.auth.currentUser!.uid; // Query staff data from Firebase Data Connect final QueryResult result = - await _dataConnect.getStaffByUserId(userId: user.uid).execute(); + await _service.connector.getStaffByUserId(userId: uid).execute(); if (result.data.staffs.isEmpty) { throw const ServerException(technicalMessage: 'Staff profile not found'); @@ -53,10 +44,12 @@ class PersonalInfoRepositoryImpl } @override - Future updateStaffProfile({required String staffId, required Map data}) async { - return executeProtected(() async { + Future updateStaffProfile( + {required String staffId, required Map data}) async { + return _service.run(() async { // Start building the update mutation - UpdateStaffVariablesBuilder updateBuilder = _dataConnect.updateStaff(id: staffId); + UpdateStaffVariablesBuilder updateBuilder = + _service.connector.updateStaff(id: staffId); // Apply updates from map if present if (data.containsKey('name')) { @@ -72,8 +65,9 @@ class PersonalInfoRepositoryImpl updateBuilder = updateBuilder.photoUrl(data['avatar'] as String?); } if (data.containsKey('preferredLocations')) { - // After schema update and SDK regeneration, preferredLocations accepts List - updateBuilder = updateBuilder.preferredLocations(data['preferredLocations'] as List); + // After schema update and SDK regeneration, preferredLocations accepts List + updateBuilder = updateBuilder.preferredLocations( + data['preferredLocations'] as List); } // Execute the update @@ -81,7 +75,8 @@ class PersonalInfoRepositoryImpl await updateBuilder.execute(); if (result.data.staff_update == null) { - throw const ServerException(technicalMessage: 'Failed to update staff profile'); + throw const ServerException( + technicalMessage: 'Failed to update staff profile'); } // Fetch the updated staff profile to return complete entity diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/staff_profile_info_module.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/staff_profile_info_module.dart index 984d010a..47c80748 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/staff_profile_info_module.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/profile_info/lib/src/staff_profile_info_module.dart @@ -1,7 +1,5 @@ -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; -import 'package:krow_data_connect/krow_data_connect.dart'; import 'data/repositories/personal_info_repository_impl.dart'; import 'domain/repositories/personal_info_repository_interface.dart'; @@ -25,11 +23,7 @@ class StaffProfileInfoModule extends Module { void binds(Injector i) { // Repository i.addLazySingleton( - () => PersonalInfoRepositoryImpl( - dataConnect: ExampleConnector.instance, - firebaseAuth: FirebaseAuth.instance, - ), - ); + PersonalInfoRepositoryImpl.new); // Use Cases - delegate business logic to repository i.addLazySingleton(