This commit is contained in:
Felipe
2024-03-18 17:46:03 -05:00
parent b7b66c389f
commit bb840260ba
15 changed files with 259 additions and 30 deletions
@@ -20,11 +20,19 @@ class ProfessionalBloc extends Bloc<ProfessionalEvent, ProfessionalState> {
_userRepository = userRepository, _userRepository = userRepository,
super(ProfessionalInitial()) { super(ProfessionalInitial()) {
bool isProModeActive = _professionalRepository.isProModeActive; 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) { _professionalRepository.sreamIsProModeActive().listen((isProModeActive) {
log('xdd despues de escuchar');
add(UpdateProfessionalEvent(isProModeActive: isProModeActive)); add(UpdateProfessionalEvent(isProModeActive: isProModeActive));
}); });
@@ -33,7 +41,8 @@ class ProfessionalBloc extends Bloc<ProfessionalEvent, ProfessionalState> {
}); });
on<UpdateProfessionalEvent>((event, emit) async { on<UpdateProfessionalEvent>((event, emit) async {
emit(LoadedModeProState(event.isProModeActive)); final proInfo = _professionalRepository.lastProInfo();
emit(LoadedModeProState(event.isProModeActive, proInfo));
}); });
on<SendProfessionalToReviewEvent>((event, emit) async { on<SendProfessionalToReviewEvent>((event, emit) async {
@@ -60,6 +69,7 @@ class ProfessionalBloc extends Bloc<ProfessionalEvent, ProfessionalState> {
identification: event.identification, identification: event.identification,
identificationPicture: identificationPdfUrl, identificationPicture: identificationPdfUrl,
address: '', address: '',
aditionalAddress: '',
profession: event.profession, profession: event.profession,
specializations: event.specializations, specializations: event.specializations,
specializationsPictures: specializationsPdfUrls, specializationsPictures: specializationsPdfUrls,
@@ -67,15 +77,15 @@ class ProfessionalBloc extends Bloc<ProfessionalEvent, ProfessionalState> {
latitude: '', latitude: '',
longitude: '', longitude: '',
rate: '', rate: '',
location: '', locationPreferences: LocationPreferences.office,
bannerPicture: '',
schedules: Schedules.empty, schedules: Schedules.empty,
paymentMethods: PaymentMethodEntity.empty, paymentMethods: PaymentMethodEntity.empty,
)); ));
} catch (e) { } catch (e) {
log('error acceso a pro ${e.toString()}'); log('error acceso a pro ${e.toString()}');
} }
// _userRepository // _userRepository.updateUserInfo(myUser.copyWith(proState: ProState.pending));
// .updateUserInfo(myUser.copyWith(proState: ProState.pending));
}); });
} }
} }
@@ -4,16 +4,25 @@ abstract class ProfessionalState extends Equatable {
const ProfessionalState(); const ProfessionalState();
@override @override
List<Object> get props => []; List<Object?> get props => [];
} }
class ProfessionalInitial extends ProfessionalState {} class ProfessionalInitial extends ProfessionalState {}
class ProfessionalStateFailure extends ProfessionalState {
final String? message;
const ProfessionalStateFailure({this.message});
}
class ProfessionalStateProcess extends ProfessionalState {}
class LoadedModeProState extends ProfessionalState { class LoadedModeProState extends ProfessionalState {
final bool isProModeActive; final bool isProModeActive;
final ProfessionalEntity? proInfo;
const LoadedModeProState(this.isProModeActive); const LoadedModeProState(this.isProModeActive, this.proInfo);
@override @override
List<Object> get props => [isProModeActive]; List<Object?> get props => [isProModeActive, proInfo];
} }
@@ -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<ProfessionalProfileEvent, ProfessionalProfileState> {
final FirebaseProfessionalRepository _professionalRepository;
ProfessionalProfileBloc({required FirebaseProfessionalRepository professionalRepository}) : _professionalRepository = professionalRepository, super((UpdateProfessionalInfoInitial())) {
on<UpdateProfessionalInfo>(_onUpdateProfessionalInfo);
}
void _onUpdateProfessionalInfo(UpdateProfessionalInfo event, Emitter<ProfessionalProfileState> emit) async {
emit(UpdateProfessionalInfoLoading());
try {
emit(const UpdateProfessionalInfoSuccess());
} catch (e) {
emit(UpdateProfessionalInfoFailure());
}
}
}
@@ -0,0 +1,21 @@
part of 'professional_profile_bloc.dart';
abstract class ProfessionalProfileEvent extends Equatable {
const ProfessionalProfileEvent();
@override
List<Object?> get props => [];
}
class UpdateProfessionalInfo extends ProfessionalProfileEvent {
final ProfessionalEntity professional;
final String? fileBanner;
const UpdateProfessionalInfo({
required this.professional,
this.fileBanner,
});
@override
List<Object?> get props => [professional, fileBanner];
}
@@ -0,0 +1,21 @@
part of 'professional_profile_bloc.dart';
abstract class ProfessionalProfileState extends Equatable {
const ProfessionalProfileState();
@override
List<Object> get props => [];
}
class UpdateProfessionalInfoInitial extends ProfessionalProfileState {}
class UpdateProfessionalInfoFailure extends ProfessionalProfileState {}
class UpdateProfessionalInfoLoading extends ProfessionalProfileState {}
class UpdateProfessionalInfoSuccess extends ProfessionalProfileState {
const UpdateProfessionalInfoSuccess();
@override
List<Object> get props => [];
}
+1 -3
View File
@@ -8,9 +8,7 @@ part 'profile_state.dart';
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> { class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
final UserRepository _userRepository; final UserRepository _userRepository;
ProfileBloc({ ProfileBloc({required UserRepository userRepository,}) : _userRepository = userRepository,
required UserRepository userRepository,
}) : _userRepository = userRepository,
super(UpdateUserInfoInitial()) { super(UpdateUserInfoInitial()) {
on<UpdateUserInfo>(_onUpdateUserInfo); on<UpdateUserInfo>(_onUpdateUserInfo);
} }
@@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; 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 { class ProfessionalProfileScreen extends StatefulWidget {
const ProfessionalProfileScreen({super.key}); const ProfessionalProfileScreen({super.key});
@@ -14,11 +16,34 @@ class _ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Perfil Profesional'), title: const Text('Perfil Profesional'),
), ),
body: BlocBuilder<ProfessionalBloc, ProfessionalState>(
builder: (context, state) {
return Scaffold(
body: Center( body: Center(
child: Text('Perfil profesional'), 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}');
}
} }
@@ -1,4 +1,5 @@
library professional_repository; library professional_repository;
export 'src/models/models.dart';
export 'src/entities/entities.dart'; export 'src/entities/entities.dart';
export 'src/repositories/firebase_professional_repository.dart'; export 'src/repositories/firebase_professional_repository.dart';
@@ -1,13 +1,16 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:professional_repository/professional_repository.dart'; import 'package:professional_repository/professional_repository.dart';
import 'package:professional_repository/src/models/location_preferences.dart';
class ProfessionalEntity extends Equatable { class ProfessionalEntity extends Equatable {
final String id; final String id;
final String identification; final String identification;
final String address; final String address;
final String aditionalAddress;
final String profession; final String profession;
final String rate; final String rate;
final String location; final LocationPreferences locationPreferences;
final String bannerPicture;
final String identificationPicture; final String identificationPicture;
final String certificatePicture; final String certificatePicture;
final String latitude; final String latitude;
@@ -21,9 +24,11 @@ class ProfessionalEntity extends Equatable {
required this.id, required this.id,
required this.identification, required this.identification,
required this.address, required this.address,
required this.aditionalAddress,
required this.profession, required this.profession,
required this.rate, required this.rate,
required this.location, required this.locationPreferences,
required this.bannerPicture,
required this.identificationPicture, required this.identificationPicture,
required this.certificatePicture, required this.certificatePicture,
required this.latitude, required this.latitude,
@@ -39,9 +44,11 @@ class ProfessionalEntity extends Equatable {
id: doc['id'] as String, id: doc['id'] as String,
identification: doc['identification'] as String, identification: doc['identification'] as String,
address: doc['address'] as String, address: doc['address'] as String,
aditionalAddress: doc['aditional_address'] as String,
profession: doc['profession'] as String, profession: doc['profession'] as String,
rate: doc['rate'] 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, identificationPicture: doc['identification_picture'] as String,
certificatePicture: doc['certificate_picture'] as String, certificatePicture: doc['certificate_picture'] as String,
latitude: doc['latitude'] as String, latitude: doc['latitude'] as String,
@@ -54,14 +61,16 @@ class ProfessionalEntity extends Equatable {
); );
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toDocument() {
return { return {
'id': id, 'id': id,
'identification': identification, 'identification': identification,
'address': address, 'address': address,
'aditional_address': aditionalAddress,
'profession': profession, 'profession': profession,
'rate': rate, 'rate': rate,
'location': location, 'location_preferences': enumToInt(locationPreferences),
'banner_picture': bannerPicture,
'identification_picture': identificationPicture, 'identification_picture': identificationPicture,
'certificate_picture': certificatePicture, 'certificate_picture': certificatePicture,
'latitude': latitude, 'latitude': latitude,
@@ -78,9 +87,11 @@ class ProfessionalEntity extends Equatable {
id, id,
identification, identification,
address, address,
aditionalAddress,
profession, profession,
rate, rate,
location, locationPreferences,
bannerPicture,
identificationPicture, identificationPicture,
certificatePicture, certificatePicture,
latitude, latitude,
@@ -97,9 +108,11 @@ class ProfessionalEntity extends Equatable {
id: $id, id: $id,
identification: $identification, identification: $identification,
address: $address, address: $address,
aditional_address: $aditionalAddress,
profession: $profession, profession: $profession,
rate: $rate, rate: $rate,
location: $location, location_preferences: $locationPreferences,
bannerPicture: $bannerPicture,
identificationPicture: $identificationPicture, identificationPicture: $identificationPicture,
certificatePicture: $certificatePicture, certificatePicture: $certificatePicture,
latitude: $latitude, latitude: $latitude,
@@ -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];
}
@@ -0,0 +1 @@
export 'location_preferences.dart';
@@ -1,33 +1,103 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'dart:io'; import 'dart:io';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:professional_repository/professional_repository.dart'; import 'package:professional_repository/professional_repository.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
class FirebaseProfessionalRepository { class FirebaseProfessionalRepository {
bool isProModeActive = false;
final professionalCollection = final professionalCollection =
FirebaseFirestore.instance.collection('professional_info'); FirebaseFirestore.instance.collection('professional_info');
final StreamController<bool> _userStreamController =
ProfessionalEntity? _proInfo;
final StreamController<ProfessionalEntity?> _proInfoBroadcast =
StreamController<ProfessionalEntity?>.broadcast();
bool isProModeActive = false;
final StreamController<bool> _isProModeActiveBroadcast =
StreamController.broadcast(); StreamController.broadcast();
FirebaseProfessionalRepository() { 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<ProfessionalEntity?> streamProInfo() {
return _proInfoBroadcast.stream;
}
Future<void> 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<ProfessionalEntity?> 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<bool> sreamIsProModeActive() { Stream<bool> sreamIsProModeActive() {
return _userStreamController.stream; return _isProModeActiveBroadcast.stream;
} }
switchProMode() async { switchProMode() async {
isProModeActive = !isProModeActive; isProModeActive = !isProModeActive;
_userStreamController.add(isProModeActive); _isProModeActiveBroadcast.add(isProModeActive);
} }
Future<void> saveProfessionalInfo(ProfessionalEntity entity) async { Future<void> saveProfessionalInfo(ProfessionalEntity entity) async {
await professionalCollection.doc(entity.id).set(entity.toJson()); await professionalCollection.doc(entity.id).set(entity.toDocument());
}
Future<String> 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<String> uploadPdfCedula(String file, String userId) async { Future<String> uploadPdfCedula(String file, String userId) async {
@@ -89,6 +89,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" 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: firebase_core:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -17,6 +17,7 @@ dependencies:
firebase_storage: ^11.6.5 firebase_storage: ^11.6.5
firebase_core: ^2.25.4 firebase_core: ^2.25.4
intl: ^0.18.1 intl: ^0.18.1
firebase_auth: ^4.17.8
dev_dependencies: dev_dependencies:
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
@@ -6,6 +6,7 @@ abstract class UserRepository {
Future<MyUser?> lastUser(); Future<MyUser?> lastUser();
Stream<MyUser?> streamUser(); Stream<MyUser?> streamUser();
Stream<bool> isAuthenticated(); Stream<bool> isAuthenticated();
Future<void> signIn(String email, String password); Future<void> signIn(String email, String password);