diff --git a/lib/blocs/professional_bloc/professional_bloc.dart b/lib/blocs/professional_bloc/professional_bloc.dart index 3ca3d26..151204e 100644 --- a/lib/blocs/professional_bloc/professional_bloc.dart +++ b/lib/blocs/professional_bloc/professional_bloc.dart @@ -20,11 +20,19 @@ class ProfessionalBloc extends Bloc { _userRepository = userRepository, super(ProfessionalInitial()) { bool isProModeActive = _professionalRepository.isProModeActive; - emit(LoadedModeProState(isProModeActive)); + final proInfo = _professionalRepository.lastProInfo(); + emit(LoadedModeProState(isProModeActive, proInfo)); + + _professionalRepository.streamProInfo().listen((proInfo) { + if (proInfo == null) { + emit(const ProfessionalStateFailure()); + } else { + final isProModeActive = _professionalRepository.isProModeActive; + emit(LoadedModeProState(isProModeActive, proInfo)); + } + }); _professionalRepository.sreamIsProModeActive().listen((isProModeActive) { - log('xdd despues de escuchar'); - add(UpdateProfessionalEvent(isProModeActive: isProModeActive)); }); @@ -33,7 +41,8 @@ class ProfessionalBloc extends Bloc { }); on((event, emit) async { - emit(LoadedModeProState(event.isProModeActive)); + final proInfo = _professionalRepository.lastProInfo(); + emit(LoadedModeProState(event.isProModeActive, proInfo)); }); on((event, emit) async { @@ -60,6 +69,7 @@ class ProfessionalBloc extends Bloc { identification: event.identification, identificationPicture: identificationPdfUrl, address: '', + aditionalAddress: '', profession: event.profession, specializations: event.specializations, specializationsPictures: specializationsPdfUrls, @@ -67,15 +77,15 @@ class ProfessionalBloc extends Bloc { latitude: '', longitude: '', rate: '', - location: '', + locationPreferences: LocationPreferences.office, + bannerPicture: '', schedules: Schedules.empty, paymentMethods: PaymentMethodEntity.empty, )); } catch (e) { log('error acceso a pro ${e.toString()}'); } - // _userRepository - // .updateUserInfo(myUser.copyWith(proState: ProState.pending)); + // _userRepository.updateUserInfo(myUser.copyWith(proState: ProState.pending)); }); } } diff --git a/lib/blocs/professional_bloc/professional_state.dart b/lib/blocs/professional_bloc/professional_state.dart index 430d559..6455dac 100644 --- a/lib/blocs/professional_bloc/professional_state.dart +++ b/lib/blocs/professional_bloc/professional_state.dart @@ -4,16 +4,25 @@ abstract class ProfessionalState extends Equatable { const ProfessionalState(); @override - List get props => []; + List get props => []; } class ProfessionalInitial extends ProfessionalState {} +class ProfessionalStateFailure extends ProfessionalState { + final String? message; + + const ProfessionalStateFailure({this.message}); +} + +class ProfessionalStateProcess extends ProfessionalState {} + class LoadedModeProState extends ProfessionalState { final bool isProModeActive; + final ProfessionalEntity? proInfo; - const LoadedModeProState(this.isProModeActive); + const LoadedModeProState(this.isProModeActive, this.proInfo); @override - List get props => [isProModeActive]; + List get props => [isProModeActive, proInfo]; } diff --git a/lib/blocs/professional_profile_bloc/professional_profile_bloc.dart b/lib/blocs/professional_profile_bloc/professional_profile_bloc.dart new file mode 100644 index 0000000..f560bc8 --- /dev/null +++ b/lib/blocs/professional_profile_bloc/professional_profile_bloc.dart @@ -0,0 +1,23 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:professional_repository/professional_repository.dart'; + +part 'professional_profile_event.dart'; +part 'professional_profile_state.dart'; + +class ProfessionalProfileBloc extends Bloc { + final FirebaseProfessionalRepository _professionalRepository; + + ProfessionalProfileBloc({required FirebaseProfessionalRepository professionalRepository}) : _professionalRepository = professionalRepository, super((UpdateProfessionalInfoInitial())) { + on(_onUpdateProfessionalInfo); + } + + void _onUpdateProfessionalInfo(UpdateProfessionalInfo event, Emitter emit) async { + emit(UpdateProfessionalInfoLoading()); + try { + emit(const UpdateProfessionalInfoSuccess()); + } catch (e) { + emit(UpdateProfessionalInfoFailure()); + } + } +} diff --git a/lib/blocs/professional_profile_bloc/professional_profile_event.dart b/lib/blocs/professional_profile_bloc/professional_profile_event.dart new file mode 100644 index 0000000..2e5217b --- /dev/null +++ b/lib/blocs/professional_profile_bloc/professional_profile_event.dart @@ -0,0 +1,21 @@ +part of 'professional_profile_bloc.dart'; + +abstract class ProfessionalProfileEvent extends Equatable { + const ProfessionalProfileEvent(); + + @override + List get props => []; +} + +class UpdateProfessionalInfo extends ProfessionalProfileEvent { + final ProfessionalEntity professional; + final String? fileBanner; + + const UpdateProfessionalInfo({ + required this.professional, + this.fileBanner, + }); + + @override + List get props => [professional, fileBanner]; +} diff --git a/lib/blocs/professional_profile_bloc/professional_profile_state.dart b/lib/blocs/professional_profile_bloc/professional_profile_state.dart new file mode 100644 index 0000000..a38741c --- /dev/null +++ b/lib/blocs/professional_profile_bloc/professional_profile_state.dart @@ -0,0 +1,21 @@ +part of 'professional_profile_bloc.dart'; + +abstract class ProfessionalProfileState extends Equatable { + const ProfessionalProfileState(); + + @override + List get props => []; +} + +class UpdateProfessionalInfoInitial extends ProfessionalProfileState {} + +class UpdateProfessionalInfoFailure extends ProfessionalProfileState {} + +class UpdateProfessionalInfoLoading extends ProfessionalProfileState {} + +class UpdateProfessionalInfoSuccess extends ProfessionalProfileState { + const UpdateProfessionalInfoSuccess(); + + @override + List get props => []; +} diff --git a/lib/blocs/profile_bloc/profile_bloc.dart b/lib/blocs/profile_bloc/profile_bloc.dart index 2bc74e5..6789279 100644 --- a/lib/blocs/profile_bloc/profile_bloc.dart +++ b/lib/blocs/profile_bloc/profile_bloc.dart @@ -8,9 +8,7 @@ part 'profile_state.dart'; class ProfileBloc extends Bloc { final UserRepository _userRepository; - ProfileBloc({ - required UserRepository userRepository, - }) : _userRepository = userRepository, + ProfileBloc({required UserRepository userRepository,}) : _userRepository = userRepository, super(UpdateUserInfoInitial()) { on(_onUpdateUserInfo); } diff --git a/lib/screens/professional/professional_profile_screen.dart b/lib/screens/professional/professional_profile_screen.dart index 7f823ea..628e434 100644 --- a/lib/screens/professional/professional_profile_screen.dart +++ b/lib/screens/professional/professional_profile_screen.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:prosappco/components/general_drawer.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:professional_repository/professional_repository.dart'; +import 'package:prosappco/blocs/professional_bloc/professional_bloc.dart'; class ProfessionalProfileScreen extends StatefulWidget { const ProfessionalProfileScreen({super.key}); @@ -14,11 +16,34 @@ class _ProfessionalProfileScreenState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('Perfil Profesional'), + title: const Text('Perfil Profesional'), ), - body: Center( - child: Text('Perfil profesional'), + body: BlocBuilder( + builder: (context, state) { + return Scaffold( + body: Center( + child: content(context, state), + ), + ); + }, ), ); } + + content(BuildContext context, ProfessionalState state) { + if (state is LoadedModeProState) { + if (state.isProModeActive) { + if (state.proInfo == null) { + return const Text('Loading...'); + } else { + return body(state.proInfo!); + } + } + } + return const Text('Go back'); + } + + body(ProfessionalEntity proInfo) { + return Text('Bienvenido Profesional ${proInfo.address}'); + } } diff --git a/packages/professional_repository/lib/professional_repository.dart b/packages/professional_repository/lib/professional_repository.dart index 02a279e..6e4483f 100644 --- a/packages/professional_repository/lib/professional_repository.dart +++ b/packages/professional_repository/lib/professional_repository.dart @@ -1,4 +1,5 @@ library professional_repository; +export 'src/models/models.dart'; export 'src/entities/entities.dart'; export 'src/repositories/firebase_professional_repository.dart'; diff --git a/packages/professional_repository/lib/src/entities/professional_entity.dart b/packages/professional_repository/lib/src/entities/professional_entity.dart index 44cc78d..c4002eb 100644 --- a/packages/professional_repository/lib/src/entities/professional_entity.dart +++ b/packages/professional_repository/lib/src/entities/professional_entity.dart @@ -1,13 +1,16 @@ import 'package:equatable/equatable.dart'; import 'package:professional_repository/professional_repository.dart'; +import 'package:professional_repository/src/models/location_preferences.dart'; class ProfessionalEntity extends Equatable { final String id; final String identification; final String address; + final String aditionalAddress; final String profession; final String rate; - final String location; + final LocationPreferences locationPreferences; + final String bannerPicture; final String identificationPicture; final String certificatePicture; final String latitude; @@ -21,9 +24,11 @@ class ProfessionalEntity extends Equatable { required this.id, required this.identification, required this.address, + required this.aditionalAddress, required this.profession, required this.rate, - required this.location, + required this.locationPreferences, + required this.bannerPicture, required this.identificationPicture, required this.certificatePicture, required this.latitude, @@ -39,9 +44,11 @@ class ProfessionalEntity extends Equatable { id: doc['id'] as String, identification: doc['identification'] as String, address: doc['address'] as String, + aditionalAddress: doc['aditional_address'] as String, profession: doc['profession'] as String, rate: doc['rate'] as String, - location: doc['location'] as String, + locationPreferences: intToEnum(doc['location_preferences'] as int), + bannerPicture: doc['banner_picture'] as String, identificationPicture: doc['identification_picture'] as String, certificatePicture: doc['certificate_picture'] as String, latitude: doc['latitude'] as String, @@ -54,14 +61,16 @@ class ProfessionalEntity extends Equatable { ); } - Map toJson() { + Map toDocument() { return { 'id': id, 'identification': identification, 'address': address, + 'aditional_address': aditionalAddress, 'profession': profession, 'rate': rate, - 'location': location, + 'location_preferences': enumToInt(locationPreferences), + 'banner_picture': bannerPicture, 'identification_picture': identificationPicture, 'certificate_picture': certificatePicture, 'latitude': latitude, @@ -78,9 +87,11 @@ class ProfessionalEntity extends Equatable { id, identification, address, + aditionalAddress, profession, rate, - location, + locationPreferences, + bannerPicture, identificationPicture, certificatePicture, latitude, @@ -97,9 +108,11 @@ class ProfessionalEntity extends Equatable { id: $id, identification: $identification, address: $address, + aditional_address: $aditionalAddress, profession: $profession, rate: $rate, - location: $location, + location_preferences: $locationPreferences, + bannerPicture: $bannerPicture, identificationPicture: $identificationPicture, certificatePicture: $certificatePicture, latitude: $latitude, diff --git a/packages/professional_repository/lib/src/models/location_preferences.dart b/packages/professional_repository/lib/src/models/location_preferences.dart new file mode 100644 index 0000000..d65bee5 --- /dev/null +++ b/packages/professional_repository/lib/src/models/location_preferences.dart @@ -0,0 +1,11 @@ +export 'location_preferences.dart'; + +enum LocationPreferences { office, delivery, both } + +int enumToInt(LocationPreferences state) { + return state.index; +} + +LocationPreferences intToEnum(int value) { + return LocationPreferences.values[value]; +} diff --git a/packages/professional_repository/lib/src/models/models.dart b/packages/professional_repository/lib/src/models/models.dart new file mode 100644 index 0000000..5888cec --- /dev/null +++ b/packages/professional_repository/lib/src/models/models.dart @@ -0,0 +1 @@ +export 'location_preferences.dart'; diff --git a/packages/professional_repository/lib/src/repositories/firebase_professional_repository.dart b/packages/professional_repository/lib/src/repositories/firebase_professional_repository.dart index 1c080b3..81a10ee 100644 --- a/packages/professional_repository/lib/src/repositories/firebase_professional_repository.dart +++ b/packages/professional_repository/lib/src/repositories/firebase_professional_repository.dart @@ -1,33 +1,103 @@ import 'dart:async'; import 'dart:developer'; import 'dart:io'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:professional_repository/professional_repository.dart'; import 'package:firebase_storage/firebase_storage.dart'; class FirebaseProfessionalRepository { - bool isProModeActive = false; final professionalCollection = FirebaseFirestore.instance.collection('professional_info'); - final StreamController _userStreamController = + + ProfessionalEntity? _proInfo; + final StreamController _proInfoBroadcast = + StreamController.broadcast(); + + bool isProModeActive = false; + + final StreamController _isProModeActiveBroadcast = StreamController.broadcast(); FirebaseProfessionalRepository() { - _userStreamController.add(isProModeActive); + _isProModeActiveBroadcast.add(isProModeActive); + + FirebaseAuth.instance.userChanges().listen((user) async { + if (user != null) { + await updateFromFirebase2( + userId: user.uid, + ); + } else { + _proInfo = null; + _proInfoBroadcast.add(null); + } + }); + } + + ProfessionalEntity? lastProInfo() { + return _proInfo; + } + + Stream streamProInfo() { + return _proInfoBroadcast.stream; + } + + Future updateFromFirebase2({ + required String userId, + }) async { + try { + final proInfo = await getProInfo(userId); + _proInfo = proInfo; + _proInfoBroadcast.add(proInfo); + } catch (e) { + log('xd -- Error updating from firebase ${e.toString()}'); + _proInfo = null; + _proInfoBroadcast.add(null); + } + } + + Future getProInfo(String myUserId) async { + try { + return professionalCollection.doc(myUserId).get().then((value) { + final valueData = value.data(); + if (valueData == null || valueData.isEmpty || !value.exists) { + return null; + } + + return ProfessionalEntity.fromDocument(valueData); + }); + } catch (e) { + log(e.toString()); + rethrow; + } } Stream sreamIsProModeActive() { - return _userStreamController.stream; + return _isProModeActiveBroadcast.stream; } switchProMode() async { isProModeActive = !isProModeActive; - _userStreamController.add(isProModeActive); + _isProModeActiveBroadcast.add(isProModeActive); } Future saveProfessionalInfo(ProfessionalEntity entity) async { - await professionalCollection.doc(entity.id).set(entity.toJson()); + await professionalCollection.doc(entity.id).set(entity.toDocument()); + } + + Future uploadBannerPicture(String file, String userId) async { + try { + File imageFile = File(file); + Reference firebaseStoreRef = + FirebaseStorage.instance.ref().child('$userId/BN/${userId}_banner'); + await firebaseStoreRef.putFile(imageFile); + String url = await firebaseStoreRef.getDownloadURL(); + return url; + } catch (e) { + log(e.toString()); + rethrow; + } } Future uploadPdfCedula(String file, String userId) async { diff --git a/packages/professional_repository/pubspec.lock b/packages/professional_repository/pubspec.lock index 3ec5301..eaf8601 100644 --- a/packages/professional_repository/pubspec.lock +++ b/packages/professional_repository/pubspec.lock @@ -89,6 +89,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "17b841e1b000c3441b8ffceca88f468e078d0443db9643e77541bdfb7a3fd16b" + url: "https://pub.dev" + source: hosted + version: "4.17.8" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: f294ceef40409a36c819a14280ca864fe487b44033e5276443377c66cb448310 + url: "https://pub.dev" + source: hosted + version: "7.1.8" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: "1f231da900fe7ff9f2974f8adcbdb3363c410c24725978afa5dc33e1e7e62e06" + url: "https://pub.dev" + source: hosted + version: "5.9.8" firebase_core: dependency: "direct main" description: diff --git a/packages/professional_repository/pubspec.yaml b/packages/professional_repository/pubspec.yaml index d71c85d..25d2c1d 100644 --- a/packages/professional_repository/pubspec.yaml +++ b/packages/professional_repository/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: firebase_storage: ^11.6.5 firebase_core: ^2.25.4 intl: ^0.18.1 + firebase_auth: ^4.17.8 dev_dependencies: flutter_lints: ^2.0.0 diff --git a/packages/user_repository/lib/src/repositories/user_repo.dart b/packages/user_repository/lib/src/repositories/user_repo.dart index 97e5aff..d6cbb3e 100644 --- a/packages/user_repository/lib/src/repositories/user_repo.dart +++ b/packages/user_repository/lib/src/repositories/user_repo.dart @@ -6,6 +6,7 @@ abstract class UserRepository { Future lastUser(); Stream streamUser(); + Stream isAuthenticated(); Future signIn(String email, String password);