diff --git a/apps/mobile/packages/domain/lib/src/entities/users/staff.dart b/apps/mobile/packages/domain/lib/src/entities/users/staff.dart index f3bc2bf0..cef37448 100644 --- a/apps/mobile/packages/domain/lib/src/entities/users/staff.dart +++ b/apps/mobile/packages/domain/lib/src/entities/users/staff.dart @@ -29,17 +29,21 @@ enum StaffStatus { /// Contains all personal and professional details of a staff member. /// Linked to a [User] via [authProviderId]. class Staff extends Equatable { - const Staff({ required this.id, required this.authProviderId, required this.name, required this.email, this.phone, + this.avatar, required this.status, this.address, - this.avatar, - this.livePhoto, + this.totalShifts, + this.averageRating, + this.onTimeRate, + this.noShowCount, + this.cancellationCount, + this.reliabilityScore, }); /// Unique identifier for the staff profile. final String id; @@ -56,17 +60,34 @@ class Staff extends Equatable { /// Contact phone number. final String? phone; + /// Profile picture URL. + final String? avatar; + /// Current workflow status of the staff member. final StaffStatus status; - /// Physical address string. + /// The user's physical address. + /// + /// Can be used for location-based job matching. final String? address; - /// URL to the avatar image. - final String? avatar; + /// The total number of shifts completed. + final int? totalShifts; - /// URL to a verified live photo for identity verification. - final String? livePhoto; + /// The average rating from businesses. + final double? averageRating; + + /// The percentage of shifts arrived on time. + final int? onTimeRate; + + /// The number of no-shows. + final int? noShowCount; + + /// The number of cancellations within 24h. + final int? cancellationCount; + + /// The reliability score (0-100). + final int? reliabilityScore; @override List get props => [ @@ -75,9 +96,14 @@ class Staff extends Equatable { name, email, phone, + avatar, status, address, - avatar, - livePhoto, + totalShifts, + averageRating, + onTimeRate, + noShowCount, + cancellationCount, + reliabilityScore, ]; -} \ No newline at end of file +} diff --git a/apps/mobile/packages/features/client/create_order/lib/src/create_order_module.dart b/apps/mobile/packages/features/client/create_order/lib/src/create_order_module.dart index f539b1bf..f317863d 100644 --- a/apps/mobile/packages/features/client/create_order/lib/src/create_order_module.dart +++ b/apps/mobile/packages/features/client/create_order/lib/src/create_order_module.dart @@ -41,7 +41,7 @@ class ClientCreateOrderModule extends Module { i.addLazySingleton(CreateRapidOrderUseCase.new); // BLoCs - i.addSingleton(ClientCreateOrderBloc.new); + i.add(ClientCreateOrderBloc.new); i.add(RapidOrderBloc.new); i.add( () => OneTimeOrderBloc( diff --git a/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart b/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart index 9f38a448..cf3049fe 100644 --- a/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile/lib/src/data/repositories/profile_repository_impl.dart @@ -14,22 +14,49 @@ import '../../domain/repositories/profile_repository.dart'; /// Currently uses [ProfileRepositoryMock] from data_connect. /// When Firebase Data Connect is ready, this will be swapped with a real implementation. class ProfileRepositoryImpl implements ProfileRepositoryInterface { - final ProfileRepositoryMock _dataConnectRepository; - /// Creates a [ProfileRepositoryImpl]. /// - /// Requires a [ProfileRepositoryMock] from the data_connect package. - const ProfileRepositoryImpl(this._dataConnectRepository); + /// Requires a [ExampleConnector] from the data_connect package. + const ProfileRepositoryImpl({required this.connector}); + + /// The Data Connect connector used for data operations. + final ExampleConnector connector; @override - Future getStaffProfile(String userId) { - // Delegate directly to data_connect - no business logic here - return _dataConnectRepository.getStaffProfile(userId); + Future getStaffProfile(String userId) async { + // ignore: always_specify_types + final response = await connector.getStaffByUserId(userId: userId).execute(); + + if (response.data.staffs.isEmpty) { + // TODO: Handle user not found properly with domain exception + throw Exception('Staff not found'); + } + + final GetStaffByUserIdStaffs rawStaff = response.data.staffs.first; + + // Map the raw data connect object to the Domain Entity + return Staff( + id: rawStaff.id, + authProviderId: rawStaff.userId, + name: rawStaff.fullName, + email: rawStaff.email ?? '', + phone: rawStaff.phone, + avatar: rawStaff.photoUrl, + status: StaffStatus.active, + address: null, + totalShifts: rawStaff.totalShifts, + averageRating: rawStaff.averageRating, + onTimeRate: rawStaff.onTimeRate, + noShowCount: rawStaff.noShowCount, + cancellationCount: rawStaff.cancellationCount, + reliabilityScore: rawStaff.reliabilityScore, + ); } @override Future signOut() { - // Delegate directly to data_connect - no business logic here - return _dataConnectRepository.signOut(); + // TODO: Implement sign out via Auth interface, not profile repository + // For now, no-op or delegate if connector has auth + return Future.value(); } } diff --git a/apps/mobile/packages/features/staff/profile/lib/src/domain/usecases/get_profile_usecase.dart b/apps/mobile/packages/features/staff/profile/lib/src/domain/usecases/get_profile_usecase.dart index 8834eda5..5288c865 100644 --- a/apps/mobile/packages/features/staff/profile/lib/src/domain/usecases/get_profile_usecase.dart +++ b/apps/mobile/packages/features/staff/profile/lib/src/domain/usecases/get_profile_usecase.dart @@ -31,19 +31,18 @@ class GetProfileUseCase implements UseCase { final staff = await _repository.getStaffProfile(userId); // Map to UI entity with additional profile data - // TODO: Replace mock data with actual profile statistics from backend return StaffProfileUI( staff: staff, - totalShifts: 0, - averageRating: 5.0, - onTimeRate: 100, - noShowCount: 0, - cancellationCount: 0, - reliabilityScore: 100, + totalShifts: staff.totalShifts ?? 0, + averageRating: staff.averageRating ?? 5.0, + onTimeRate: staff.onTimeRate ?? 0, + noShowCount: staff.noShowCount ?? 0, + cancellationCount: staff.cancellationCount ?? 0, + reliabilityScore: staff.reliabilityScore ?? 100, hasPersonalInfo: staff.phone != null && staff.phone!.isNotEmpty, hasEmergencyContact: false, // TODO: Fetch from backend hasExperience: false, // TODO: Fetch from backend - hasAttire: staff.avatar != null, + hasAttire: false, // TODO: Check attire items from backend when available hasDocuments: false, // TODO: Fetch from backend hasCertificates: false, // TODO: Fetch from backend hasTaxForms: false, // TODO: Fetch from backend diff --git a/apps/mobile/packages/features/staff/profile/lib/src/presentation/pages/staff_profile_page.dart b/apps/mobile/packages/features/staff/profile/lib/src/presentation/pages/staff_profile_page.dart index c81dc81a..bea50286 100644 --- a/apps/mobile/packages/features/staff/profile/lib/src/presentation/pages/staff_profile_page.dart +++ b/apps/mobile/packages/features/staff/profile/lib/src/presentation/pages/staff_profile_page.dart @@ -28,8 +28,8 @@ class StaffProfilePage extends StatelessWidget { @override Widget build(BuildContext context) { - final i18n = t.staff.profile; - final cubit = Modular.get(); + final TranslationsStaffProfileEn i18n = t.staff.profile; + final ProfileCubit cubit = Modular.get(); // Load profile data on first build // TODO: Get actual userId from auth session @@ -40,7 +40,6 @@ class StaffProfilePage extends StatelessWidget { } return Scaffold( - backgroundColor: UiColors.background, body: BlocBuilder( bloc: cubit, builder: (context, state) { diff --git a/apps/mobile/packages/features/staff/profile/lib/src/staff_profile_module.dart b/apps/mobile/packages/features/staff/profile/lib/src/staff_profile_module.dart index 4ad1dcca..d9aee76c 100644 --- a/apps/mobile/packages/features/staff/profile/lib/src/staff_profile_module.dart +++ b/apps/mobile/packages/features/staff/profile/lib/src/staff_profile_module.dart @@ -15,19 +15,15 @@ import 'presentation/pages/staff_profile_page.dart'; /// following Clean Architecture principles. /// /// Dependency flow: -/// - Data source (ProfileRepositoryMock) from data_connect package /// - Repository implementation (ProfileRepositoryImpl) delegates to data_connect /// - Use cases depend on repository interface /// - Cubit depends on use cases class StaffProfileModule extends Module { @override void binds(Injector i) { - // Data layer - Get mock from data_connect package - i.addLazySingleton(ProfileRepositoryMock.new); - // Repository implementation - delegates to data_connect i.addLazySingleton( - () => ProfileRepositoryImpl(i.get()), + () => ProfileRepositoryImpl(connector: ExampleConnector.instance), ); // Use cases - depend on repository interface @@ -39,8 +35,7 @@ class StaffProfileModule extends Module { ); // Presentation layer - Cubit depends on use cases - // Use addLazySingleton to create a new instance per module lifecycle - i.addLazySingleton( + i.add( () => ProfileCubit( i.get(), i.get(), diff --git a/apps/mobile/packages/features/staff/profile/lib/staff_profile.dart b/apps/mobile/packages/features/staff/profile/lib/staff_profile.dart index 4ca64d73..a5b7a40d 100644 --- a/apps/mobile/packages/features/staff/profile/lib/staff_profile.dart +++ b/apps/mobile/packages/features/staff/profile/lib/staff_profile.dart @@ -1,2 +1 @@ -/// Export the modular feature definition. export 'src/staff_profile_module.dart';