feat: Refactor repositories to utilize DataConnectService and remove FirebaseAuth dependency
This commit is contained in:
@@ -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<AttireRepository>(
|
||||
() => AttireRepositoryImpl(ExampleConnector.instance),
|
||||
);
|
||||
|
||||
i.addLazySingleton<AttireRepository>(AttireRepositoryImpl.new);
|
||||
|
||||
// Use Cases
|
||||
i.addLazySingleton(GetAttireOptionsUseCase.new);
|
||||
i.addLazySingleton(SaveAttireUseCase.new);
|
||||
|
||||
@@ -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<List<AttireItem>> getAttireOptions() async {
|
||||
final QueryResult<ListAttireOptionsData, void> 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<ListAttireOptionsData, void> 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
|
||||
|
||||
@@ -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<String> _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<List<EmergencyContact>> 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<void> saveContacts(List<EmergencyContact> 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,
|
||||
|
||||
@@ -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<EmergencyContactRepositoryInterface>(
|
||||
() => EmergencyContactRepositoryImpl(
|
||||
dataConnect: ExampleConnector.instance,
|
||||
firebaseAuth: FirebaseAuth.instance,
|
||||
),
|
||||
EmergencyContactRepositoryImpl.new,
|
||||
);
|
||||
|
||||
// UseCases
|
||||
|
||||
@@ -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<dc.GetStaffByUserIdStaffs> _getStaff() async {
|
||||
final user = _firebaseAuth.currentUser;
|
||||
if (user == null) {
|
||||
throw const NotAuthenticatedException(
|
||||
technicalMessage: 'User not authenticated');
|
||||
}
|
||||
Future<dc.GetStaffByIdStaff> _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<List<String>> getIndustries() async {
|
||||
return executeProtected(() async {
|
||||
return _service.run(() async {
|
||||
final staff = await _getStaff();
|
||||
return staff.industries ?? [];
|
||||
});
|
||||
@@ -44,7 +33,7 @@ class ExperienceRepositoryImpl
|
||||
|
||||
@override
|
||||
Future<List<String>> getSkills() async {
|
||||
return executeProtected(() async {
|
||||
return _service.run(() async {
|
||||
final staff = await _getStaff();
|
||||
return staff.skills ?? [];
|
||||
});
|
||||
@@ -55,9 +44,9 @@ class ExperienceRepositoryImpl
|
||||
List<String> industries,
|
||||
List<String> 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)
|
||||
|
||||
@@ -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<ExperienceRepositoryInterface>(
|
||||
() => ExperienceRepositoryImpl(
|
||||
dataConnect: ExampleConnector.instance,
|
||||
firebaseAuth: FirebaseAuth.instance,
|
||||
),
|
||||
ExperienceRepositoryImpl.new,
|
||||
);
|
||||
|
||||
// UseCases
|
||||
|
||||
@@ -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<Staff> 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<GetStaffByUserIdData, GetStaffByUserIdVariables> 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<Staff> updateStaffProfile({required String staffId, required Map<String, dynamic> data}) async {
|
||||
return executeProtected(() async {
|
||||
Future<Staff> updateStaffProfile(
|
||||
{required String staffId, required Map<String, dynamic> 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<String>
|
||||
updateBuilder = updateBuilder.preferredLocations(data['preferredLocations'] as List<String>);
|
||||
// After schema update and SDK regeneration, preferredLocations accepts List<String>
|
||||
updateBuilder = updateBuilder.preferredLocations(
|
||||
data['preferredLocations'] as List<String>);
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@@ -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<PersonalInfoRepositoryInterface>(
|
||||
() => PersonalInfoRepositoryImpl(
|
||||
dataConnect: ExampleConnector.instance,
|
||||
firebaseAuth: FirebaseAuth.instance,
|
||||
),
|
||||
);
|
||||
PersonalInfoRepositoryImpl.new);
|
||||
|
||||
// Use Cases - delegate business logic to repository
|
||||
i.addLazySingleton<GetPersonalInfoUseCase>(
|
||||
|
||||
Reference in New Issue
Block a user