import 'dart:developer'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:professional_repository/professional_repository.dart'; import 'package:service_repository/service_repository.dart'; import 'package:user_repository/user_repository.dart'; part 'service_event.dart'; part 'service_state.dart'; class ServiceBloc extends Bloc { final FirebaseServiceRepository _serviceRepository; final UserRepository _userRepository; final FirebaseProfessionalRepository _professionalRepository; ServiceBloc({ required FirebaseServiceRepository serviceRepository, required UserRepository userRepository, required FirebaseProfessionalRepository professionRepository, }) : _serviceRepository = serviceRepository, _userRepository = userRepository, _professionalRepository = professionRepository, super(CreateServiceInitial()) { on(_onCreateService); on(_onLoadService); on(_onUpdateServiceStatus); on(_onLoadServicesForUser); on(_onLoadServicesForProfessional); on(_onLoadServicesHistoryForUser); on( _onLoadServicesHistoryForProfessional); } void _onCreateService(CreateService event, Emitter emit) async { try { emit(CreateServiceLoading()); ServiceEntity service = ServiceEntity( professionalId: event.professionalId, professionalScored: false, userId: event.userId, userScored: false, address: event.address, aditionalAddress: event.aditionalAddress, latitude: event.latitude, longitude: event.longitude, day: event.day, createdAt: event.createdAt, description: event.description, range1Hour1: event.range1Hour1, range1Hour2: event.range1Hour2, rate: event.rate, status: ServiceStatus.pending, location: event.location, ); String serviceId = await _serviceRepository.createService(service); emit(CreateServiceSuccess(serviceId)); } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } void _onLoadService(LoadService event, Emitter emit) async { try { final serviceStream = _serviceRepository.getService(event.serviceId); await for (var service in serviceStream) { emit(ServiceLoaded(service)); } } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } void _onLoadServicesHistoryForUser( LoadServicesHistoryForUser event, Emitter emit) async { try { final servicesStream = _serviceRepository.getServicesHistoryForUser(event.userId); await for (var services in servicesStream) { if (services.isEmpty) { emit(const ServicesForUserLoaded([])); return; } final professionalIds = services.map((e) => e.professionalId); final List users = await _userRepository.getUsersFromIds(professionalIds); final usersDir = {for (var e in users) e.id: e}; final List professionsList = await _professionalRepository .getProfessionalsFromIds(professionalIds); final professionsDir = {for (var e in professionsList) e.id: e}; final servicesInfo = services.map((e) { return ServiceInfoUI( service: e, user: usersDir[e.professionalId]!, professional: professionsDir[e.professionalId]!); }).toList(); emit(ServicesForUserLoaded(servicesInfo)); } } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } void _onLoadServicesHistoryForProfessional( LoadServicesHistoryForProfessional event, Emitter emit) async { try { final servicesStream = _serviceRepository.getServicesHistoryForProfessional(event.userId); await for (var services in servicesStream) { if (services.isEmpty) { emit(const ServicesForUserLoaded([])); return; } final userIds = services.map((e) => e.userId); final List users = await _userRepository.getUsersFromIds(userIds); final usersDir = {for (var e in users) e.id: e}; final servicesInfo = services.map((e) { return ServiceInfoUI( service: e, user: usersDir[e.userId]!, ); }).toList(); emit(ServicesForUserLoaded(servicesInfo)); } } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } void _onLoadServicesForUser( LoadServicesForUser event, Emitter emit) async { try { final servicesStream = _serviceRepository.getServicesForUser(event.userId); await for (var services in servicesStream) { if (services.isEmpty) { emit(const ServicesForUserLoaded([])); return; } final professionalIds = services.map((e) => e.professionalId); final List users = await _userRepository.getUsersFromIds(professionalIds); final usersDir = {for (var e in users) e.id: e}; final List professionsList = await _professionalRepository .getProfessionalsFromIds(professionalIds); final professionsDir = {for (var e in professionsList) e.id: e}; final servicesInfo = services.map((e) { return ServiceInfoUI( service: e, user: usersDir[e.professionalId]!, professional: professionsDir[e.professionalId]!); }).toList(); emit(ServicesForUserLoaded(servicesInfo)); } } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } void _onLoadServicesForProfessional( LoadServicesForProfessional event, Emitter emit) async { try { final servicesStream = _serviceRepository.getServicesForProfessional(event.userId); await for (var services in servicesStream) { if (services.isEmpty) { emit(const ServicesForUserLoaded([])); return; } final userIds = services.map((e) => e.userId); final List users = await _userRepository.getUsersFromIds(userIds); final usersDir = {for (var e in users) e.id: e}; final servicesInfo = services.map((e) { return ServiceInfoUI( service: e, user: usersDir[e.userId]!, ); }).toList(); emit(ServicesForUserLoaded(servicesInfo)); } } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } void _onUpdateServiceStatus( UpdateServiceStatus event, Emitter emit) async { try { emit(CreateServiceLoading()); await _serviceRepository.updateServiceStatus( event.serviceId, event.newStatus); emit(ServiceStatusUpdated(event.newStatus)); } catch (e) { log(e.toString()); emit(CreateServiceFailure()); } } } class ServiceInfoUI { final ServiceEntity service; final MyUser user; final ProfessionalEntity? professional; ServiceInfoUI({ required this.service, required this.user, this.professional, }); }