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: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 'data/repositories_impl/attire_repository_impl.dart';
|
import 'data/repositories_impl/attire_repository_impl.dart';
|
||||||
import 'domain/repositories/attire_repository.dart';
|
import 'domain/repositories/attire_repository.dart';
|
||||||
@@ -14,9 +13,7 @@ class StaffAttireModule extends Module {
|
|||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repository
|
// Repository
|
||||||
i.addLazySingleton<AttireRepository>(
|
i.addLazySingleton<AttireRepository>(AttireRepositoryImpl.new);
|
||||||
() => AttireRepositoryImpl(ExampleConnector.instance),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Use Cases
|
// Use Cases
|
||||||
i.addLazySingleton(GetAttireOptionsUseCase.new);
|
i.addLazySingleton(GetAttireOptionsUseCase.new);
|
||||||
|
|||||||
@@ -6,24 +6,30 @@ import '../../domain/repositories/attire_repository.dart';
|
|||||||
|
|
||||||
/// Implementation of [AttireRepository].
|
/// Implementation of [AttireRepository].
|
||||||
///
|
///
|
||||||
/// Delegates data access to [ExampleConnector] from `data_connect`.
|
/// Delegates data access to [DataConnectService].
|
||||||
class AttireRepositoryImpl implements AttireRepository {
|
class AttireRepositoryImpl implements AttireRepository {
|
||||||
/// The Data Connect connector instance.
|
/// The Data Connect service.
|
||||||
final ExampleConnector _connector;
|
final DataConnectService _service;
|
||||||
|
|
||||||
/// Creates an [AttireRepositoryImpl].
|
/// Creates an [AttireRepositoryImpl].
|
||||||
AttireRepositoryImpl(this._connector);
|
AttireRepositoryImpl({DataConnectService? service})
|
||||||
|
: _service = service ?? DataConnectService.instance;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<AttireItem>> getAttireOptions() async {
|
Future<List<AttireItem>> getAttireOptions() async {
|
||||||
final QueryResult<ListAttireOptionsData, void> result = await _connector.listAttireOptions().execute();
|
return _service.run(() async {
|
||||||
return result.data.attireOptions.map((ListAttireOptionsAttireOptions e) => AttireItem(
|
final QueryResult<ListAttireOptionsData, void> result =
|
||||||
|
await _service.connector.listAttireOptions().execute();
|
||||||
|
return result.data.attireOptions
|
||||||
|
.map((ListAttireOptionsAttireOptions e) => AttireItem(
|
||||||
id: e.itemId,
|
id: e.itemId,
|
||||||
label: e.label,
|
label: e.label,
|
||||||
iconName: e.icon,
|
iconName: e.icon,
|
||||||
imageUrl: e.imageUrl,
|
imageUrl: e.imageUrl,
|
||||||
isMandatory: e.isMandatory ?? false,
|
isMandatory: e.isMandatory ?? false,
|
||||||
)).toList();
|
))
|
||||||
|
.toList();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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_data_connect/krow_data_connect.dart' as dc;
|
||||||
import 'package:krow_domain/krow_domain.dart';
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
import '../../domain/repositories/emergency_contact_repository_interface.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.
|
/// This repository delegates data operations to Firebase Data Connect.
|
||||||
class EmergencyContactRepositoryImpl
|
class EmergencyContactRepositoryImpl
|
||||||
with dc.DataErrorHandler
|
|
||||||
implements EmergencyContactRepositoryInterface {
|
implements EmergencyContactRepositoryInterface {
|
||||||
final dc.ExampleConnector _dataConnect;
|
final dc.DataConnectService _service;
|
||||||
final FirebaseAuth _firebaseAuth;
|
|
||||||
|
|
||||||
/// Creates an [EmergencyContactRepositoryImpl].
|
/// Creates an [EmergencyContactRepositoryImpl].
|
||||||
EmergencyContactRepositoryImpl({
|
EmergencyContactRepositoryImpl({
|
||||||
required dc.ExampleConnector dataConnect,
|
dc.DataConnectService? service,
|
||||||
required FirebaseAuth firebaseAuth,
|
}) : _service = service ?? dc.DataConnectService.instance;
|
||||||
}) : _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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<EmergencyContact>> getContacts() async {
|
Future<List<EmergencyContact>> getContacts() async {
|
||||||
return executeProtected(() async {
|
return _service.run(() async {
|
||||||
final staffId = await _getStaffId();
|
final staffId = await _service.getStaffId();
|
||||||
final result = await _dataConnect
|
final result = await _service.connector
|
||||||
.getEmergencyContactsByStaffId(staffId: staffId)
|
.getEmergencyContactsByStaffId(staffId: staffId)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@@ -55,11 +35,11 @@ class EmergencyContactRepositoryImpl
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> saveContacts(List<EmergencyContact> contacts) async {
|
Future<void> saveContacts(List<EmergencyContact> contacts) async {
|
||||||
return executeProtected(() async {
|
return _service.run(() async {
|
||||||
final staffId = await _getStaffId();
|
final staffId = await _service.getStaffId();
|
||||||
|
|
||||||
// 1. Get existing to delete
|
// 1. Get existing to delete
|
||||||
final existingResult = await _dataConnect
|
final existingResult = await _service.connector
|
||||||
.getEmergencyContactsByStaffId(staffId: staffId)
|
.getEmergencyContactsByStaffId(staffId: staffId)
|
||||||
.execute();
|
.execute();
|
||||||
final existingIds =
|
final existingIds =
|
||||||
@@ -67,7 +47,7 @@ class EmergencyContactRepositoryImpl
|
|||||||
|
|
||||||
// 2. Delete all existing
|
// 2. Delete all existing
|
||||||
await Future.wait(existingIds.map(
|
await Future.wait(existingIds.map(
|
||||||
(id) => _dataConnect.deleteEmergencyContact(id: id).execute()));
|
(id) => _service.connector.deleteEmergencyContact(id: id).execute()));
|
||||||
|
|
||||||
// 3. Create new
|
// 3. Create new
|
||||||
await Future.wait(contacts.map((contact) {
|
await Future.wait(contacts.map((contact) {
|
||||||
@@ -87,7 +67,7 @@ class EmergencyContactRepositoryImpl
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _dataConnect
|
return _service.connector
|
||||||
.createEmergencyContact(
|
.createEmergencyContact(
|
||||||
name: contact.name,
|
name: contact.name,
|
||||||
phone: contact.phone,
|
phone: contact.phone,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:flutter_modular/flutter_modular.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 'data/repositories/emergency_contact_repository_impl.dart';
|
||||||
import 'domain/repositories/emergency_contact_repository_interface.dart';
|
import 'domain/repositories/emergency_contact_repository_interface.dart';
|
||||||
import 'domain/usecases/get_emergency_contacts_usecase.dart';
|
import 'domain/usecases/get_emergency_contacts_usecase.dart';
|
||||||
@@ -13,10 +12,7 @@ class StaffEmergencyContactModule extends Module {
|
|||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repository
|
// Repository
|
||||||
i.addLazySingleton<EmergencyContactRepositoryInterface>(
|
i.addLazySingleton<EmergencyContactRepositoryInterface>(
|
||||||
() => EmergencyContactRepositoryImpl(
|
EmergencyContactRepositoryImpl.new,
|
||||||
dataConnect: ExampleConnector.instance,
|
|
||||||
firebaseAuth: FirebaseAuth.instance,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// UseCases
|
// UseCases
|
||||||
|
|||||||
@@ -1,42 +1,31 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
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 'package:krow_domain/krow_domain.dart';
|
||||||
|
|
||||||
|
import '../../domain/repositories/experience_repository_interface.dart';
|
||||||
|
|
||||||
/// Implementation of [ExperienceRepositoryInterface] that delegates to Data Connect.
|
/// Implementation of [ExperienceRepositoryInterface] that delegates to Data Connect.
|
||||||
class ExperienceRepositoryImpl
|
class ExperienceRepositoryImpl implements ExperienceRepositoryInterface {
|
||||||
with dc.DataErrorHandler
|
final dc.DataConnectService _service;
|
||||||
implements ExperienceRepositoryInterface {
|
|
||||||
final dc.ExampleConnector _dataConnect;
|
|
||||||
// ignore: unused_field
|
|
||||||
final FirebaseAuth _firebaseAuth;
|
|
||||||
|
|
||||||
/// Creates a [ExperienceRepositoryImpl] using Data Connect and Auth.
|
/// Creates a [ExperienceRepositoryImpl] using Data Connect Service.
|
||||||
ExperienceRepositoryImpl({
|
ExperienceRepositoryImpl({
|
||||||
required dc.ExampleConnector dataConnect,
|
dc.DataConnectService? service,
|
||||||
required FirebaseAuth firebaseAuth,
|
}) : _service = service ?? dc.DataConnectService.instance;
|
||||||
}) : _dataConnect = dataConnect,
|
|
||||||
_firebaseAuth = firebaseAuth;
|
|
||||||
|
|
||||||
Future<dc.GetStaffByUserIdStaffs> _getStaff() async {
|
Future<dc.GetStaffByIdStaff> _getStaff() async {
|
||||||
final user = _firebaseAuth.currentUser;
|
final staffId = await _service.getStaffId();
|
||||||
if (user == null) {
|
|
||||||
throw const NotAuthenticatedException(
|
|
||||||
technicalMessage: 'User not authenticated');
|
|
||||||
}
|
|
||||||
|
|
||||||
final result =
|
final result =
|
||||||
await _dataConnect.getStaffByUserId(userId: user.uid).execute();
|
await _service.connector.getStaffById(id: staffId).execute();
|
||||||
if (result.data.staffs.isEmpty) {
|
if (result.data.staff == null) {
|
||||||
throw const ServerException(technicalMessage: 'Staff profile not found');
|
throw const ServerException(technicalMessage: 'Staff profile not found');
|
||||||
}
|
}
|
||||||
return result.data.staffs.first;
|
return result.data.staff!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<String>> getIndustries() async {
|
Future<List<String>> getIndustries() async {
|
||||||
return executeProtected(() async {
|
return _service.run(() async {
|
||||||
final staff = await _getStaff();
|
final staff = await _getStaff();
|
||||||
return staff.industries ?? [];
|
return staff.industries ?? [];
|
||||||
});
|
});
|
||||||
@@ -44,7 +33,7 @@ class ExperienceRepositoryImpl
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<String>> getSkills() async {
|
Future<List<String>> getSkills() async {
|
||||||
return executeProtected(() async {
|
return _service.run(() async {
|
||||||
final staff = await _getStaff();
|
final staff = await _getStaff();
|
||||||
return staff.skills ?? [];
|
return staff.skills ?? [];
|
||||||
});
|
});
|
||||||
@@ -55,9 +44,9 @@ class ExperienceRepositoryImpl
|
|||||||
List<String> industries,
|
List<String> industries,
|
||||||
List<String> skills,
|
List<String> skills,
|
||||||
) async {
|
) async {
|
||||||
return executeProtected(() async {
|
return _service.run(() async {
|
||||||
final staff = await _getStaff();
|
final staff = await _getStaff();
|
||||||
await _dataConnect
|
await _service.connector
|
||||||
.updateStaff(id: staff.id)
|
.updateStaff(id: staff.id)
|
||||||
.industries(industries)
|
.industries(industries)
|
||||||
.skills(skills)
|
.skills(skills)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
library staff_profile_experience;
|
library staff_profile_experience;
|
||||||
|
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
|
|
||||||
@@ -22,10 +21,7 @@ class StaffProfileExperienceModule extends Module {
|
|||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repository
|
// Repository
|
||||||
i.addLazySingleton<ExperienceRepositoryInterface>(
|
i.addLazySingleton<ExperienceRepositoryInterface>(
|
||||||
() => ExperienceRepositoryImpl(
|
ExperienceRepositoryImpl.new,
|
||||||
dataConnect: ExampleConnector.instance,
|
|
||||||
firebaseAuth: FirebaseAuth.instance,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// UseCases
|
// 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:firebase_data_connect/firebase_data_connect.dart';
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
import 'package:krow_domain/krow_domain.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
|
/// - Mapping between data_connect DTOs and domain entities
|
||||||
/// - Containing no business logic
|
/// - Containing no business logic
|
||||||
class PersonalInfoRepositoryImpl
|
class PersonalInfoRepositoryImpl
|
||||||
with DataErrorHandler
|
|
||||||
implements PersonalInfoRepositoryInterface {
|
implements PersonalInfoRepositoryInterface {
|
||||||
|
|
||||||
/// Creates a [PersonalInfoRepositoryImpl].
|
/// Creates a [PersonalInfoRepositoryImpl].
|
||||||
///
|
///
|
||||||
/// Requires the Firebase Data Connect connector instance and Firebase Auth.
|
/// Requires the Firebase Data Connect service.
|
||||||
PersonalInfoRepositoryImpl({
|
PersonalInfoRepositoryImpl({
|
||||||
required ExampleConnector dataConnect,
|
DataConnectService? service,
|
||||||
required firebase_auth.FirebaseAuth firebaseAuth,
|
}) : _service = service ?? DataConnectService.instance;
|
||||||
}) : _dataConnect = dataConnect,
|
|
||||||
_firebaseAuth = firebaseAuth;
|
final DataConnectService _service;
|
||||||
final ExampleConnector _dataConnect;
|
|
||||||
final firebase_auth.FirebaseAuth _firebaseAuth;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Staff> getStaffProfile() async {
|
Future<Staff> getStaffProfile() async {
|
||||||
return executeProtected(() async {
|
return _service.run(() async {
|
||||||
final firebase_auth.User? user = _firebaseAuth.currentUser;
|
final String uid = _service.auth.currentUser!.uid;
|
||||||
if (user == null) {
|
|
||||||
throw NotAuthenticatedException(
|
|
||||||
technicalMessage: 'User not authenticated');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query staff data from Firebase Data Connect
|
// Query staff data from Firebase Data Connect
|
||||||
final QueryResult<GetStaffByUserIdData, GetStaffByUserIdVariables> result =
|
final QueryResult<GetStaffByUserIdData, GetStaffByUserIdVariables> result =
|
||||||
await _dataConnect.getStaffByUserId(userId: user.uid).execute();
|
await _service.connector.getStaffByUserId(userId: uid).execute();
|
||||||
|
|
||||||
if (result.data.staffs.isEmpty) {
|
if (result.data.staffs.isEmpty) {
|
||||||
throw const ServerException(technicalMessage: 'Staff profile not found');
|
throw const ServerException(technicalMessage: 'Staff profile not found');
|
||||||
@@ -53,10 +44,12 @@ class PersonalInfoRepositoryImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Staff> updateStaffProfile({required String staffId, required Map<String, dynamic> data}) async {
|
Future<Staff> updateStaffProfile(
|
||||||
return executeProtected(() async {
|
{required String staffId, required Map<String, dynamic> data}) async {
|
||||||
|
return _service.run(() async {
|
||||||
// Start building the update mutation
|
// Start building the update mutation
|
||||||
UpdateStaffVariablesBuilder updateBuilder = _dataConnect.updateStaff(id: staffId);
|
UpdateStaffVariablesBuilder updateBuilder =
|
||||||
|
_service.connector.updateStaff(id: staffId);
|
||||||
|
|
||||||
// Apply updates from map if present
|
// Apply updates from map if present
|
||||||
if (data.containsKey('name')) {
|
if (data.containsKey('name')) {
|
||||||
@@ -73,7 +66,8 @@ class PersonalInfoRepositoryImpl
|
|||||||
}
|
}
|
||||||
if (data.containsKey('preferredLocations')) {
|
if (data.containsKey('preferredLocations')) {
|
||||||
// After schema update and SDK regeneration, preferredLocations accepts List<String>
|
// After schema update and SDK regeneration, preferredLocations accepts List<String>
|
||||||
updateBuilder = updateBuilder.preferredLocations(data['preferredLocations'] as List<String>);
|
updateBuilder = updateBuilder.preferredLocations(
|
||||||
|
data['preferredLocations'] as List<String>);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the update
|
// Execute the update
|
||||||
@@ -81,7 +75,8 @@ class PersonalInfoRepositoryImpl
|
|||||||
await updateBuilder.execute();
|
await updateBuilder.execute();
|
||||||
|
|
||||||
if (result.data.staff_update == null) {
|
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
|
// 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/material.dart';
|
||||||
import 'package:flutter_modular/flutter_modular.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 'data/repositories/personal_info_repository_impl.dart';
|
||||||
import 'domain/repositories/personal_info_repository_interface.dart';
|
import 'domain/repositories/personal_info_repository_interface.dart';
|
||||||
@@ -25,11 +23,7 @@ class StaffProfileInfoModule extends Module {
|
|||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repository
|
// Repository
|
||||||
i.addLazySingleton<PersonalInfoRepositoryInterface>(
|
i.addLazySingleton<PersonalInfoRepositoryInterface>(
|
||||||
() => PersonalInfoRepositoryImpl(
|
PersonalInfoRepositoryImpl.new);
|
||||||
dataConnect: ExampleConnector.instance,
|
|
||||||
firebaseAuth: FirebaseAuth.instance,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Use Cases - delegate business logic to repository
|
// Use Cases - delegate business logic to repository
|
||||||
i.addLazySingleton<GetPersonalInfoUseCase>(
|
i.addLazySingleton<GetPersonalInfoUseCase>(
|
||||||
|
|||||||
Reference in New Issue
Block a user