import 'dart:developer'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:injector/injector.dart'; import 'package:intl/intl.dart'; import 'package:professional_repository/professional_repository.dart'; import 'package:prosappco/blocs/service_bloc/service_bloc.dart'; import 'package:prosappco/components/general_primary_button.dart'; import 'package:service_repository/service_repository.dart'; import 'package:setting_repository/setting_repository.dart'; import 'package:user_repository/user_repository.dart'; class UserServiceScreen extends StatefulWidget { final String serviceId; const UserServiceScreen({Key? key, required this.serviceId}) : super(key: key); @override State createState() => _UserServiceScreenState(); } class _UserServiceScreenState extends State { final settingRepository = Injector.appInstance.get(); SettingEntity? settings; @override void initState() { super.initState(); _loadSettings(); } void _loadSettings() { settingRepository.getSettings().then( (value) => setState(() { settings = value; }), ); } @override Widget build(BuildContext context) { return BlocProvider( create: (context) => Injector.appInstance.get(), child: Scaffold( appBar: AppBar( title: const Text('Servicio'), ), body: BlocBuilder( builder: (context, state) { if (state is ServiceLoaded) { final service = state.service; return FutureBuilder( future: _getUserAndProfessionalInfo(service), builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else { if (snapshot.hasError) { return Center( child: Text('Error inesperado: ${snapshot.error}'), ); } else { final userInfo = snapshot.data![0] as MyUser; final professionalInfo = snapshot.data![1] as ProfessionalEntity; return Column( children: [ ListTile( leading: Container( width: 60, height: 60, decoration: BoxDecoration( color: Colors.grey.shade300, shape: BoxShape.circle, image: userInfo.picture == null ? null : DecorationImage( image: NetworkImage(userInfo.picture!), fit: BoxFit.contain, ), ), child: userInfo.picture == null ? Icon( CupertinoIcons.person, color: Colors.grey.shade400, size: 40, ) : null, ), title: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${userInfo.name}', style: const TextStyle( fontWeight: FontWeight.bold), ), const SizedBox(width: 5), Text( '${DateFormat('dd MMMM', 'es').format(DateTime.parse(service.day))} - ${ScheduleEntity.getFormatTime(service.range1Hour1)}', style: TextStyle( color: Colors.grey[600], ), ), ], ), subtitle: const Text('Rating: 5.0'), ), Container( margin: const EdgeInsets.only( left: 40, right: 40, top: 20, bottom: 20), padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 15), decoration: BoxDecoration( color: const Color(0xFFD6F4FF), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 1, blurRadius: 5, offset: const Offset(1, 3), ), ], ), child: Row( children: [ const Icon( Icons.error_outline, size: 27, color: Colors.black54, ), const SizedBox(width: 15), service.location == ServiceLocationPreferences.delivery ? const Text( 'Servicio a su domicilio.', style: TextStyle( color: Colors.black, fontSize: 14), ) : const Text( 'Servicio en sitio / consultorio', style: TextStyle( color: Colors.black, fontSize: 14), ), ], ), ), Visibility( visible: settings?.tarifas ?? false, child: Column( children: [ Text( formatCurrency( int.tryParse(service.rate) ?? 0), style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 25), ), const Text('Tarifa de consulta'), const SizedBox(height: 15), const Text( 'Metodos de pago', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), professionalInfo.paymentMethods.datafono || professionalInfo.paymentMethods.nequi || professionalInfo .paymentMethods.transferencia ? Wrap( spacing: 8, runSpacing: 8, alignment: WrapAlignment.center, children: [ Visibility( visible: professionalInfo .paymentMethods.datafono, child: const Chip( label: Text('Datafono')), ), Visibility( visible: professionalInfo .paymentMethods.nequi, child: const Chip( label: Text('Nequi')), ), Visibility( visible: professionalInfo .paymentMethods.transferencia, child: const Chip( label: Text( 'Transferencia Bancaria')), ), ], ) : const Text( 'No hay metodos de pago registrados', overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 15, color: Colors.black45, ), ), ], ), ), ListTile( leading: const Icon(Icons.near_me), title: Text( service.address, style: TextStyle( fontSize: 15, color: Colors.grey[600]), ), subtitle: service.aditionalAddress.isEmpty ? null : Text( service.aditionalAddress, style: TextStyle( fontSize: 15, color: Colors.grey[600]), ), ), service.description.isEmpty ? const SizedBox() : Container( alignment: Alignment.center, width: MediaQuery.of(context).size.width * 0.8, child: Text( '"${service.description.trim()}"', style: TextStyle( color: Colors.grey[600], fontStyle: FontStyle.italic, ), ), ), Expanded( child: customMessageStatus(service), ), customButton(service, context), const SizedBox(height: 20), ], ); } } }, ); } else { BlocProvider.of(context) .add(LoadService(widget.serviceId)); return const Center( child: CircularProgressIndicator(), ); } }, ), ), ); } Center customMessageStatus(ServiceEntity service) { if (service.status == ServiceStatus.cancelled) { return const Center( child: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 20), child: Icon( CupertinoIcons.xmark_circle, color: Color(0xFF35A8ED), size: 70, ), ), Text( 'Servicio cancelado exitosamente', style: TextStyle( color: Color(0xFF35A8ED), fontSize: 17, fontWeight: FontWeight.w600, ), ), ], ), ); } if (service.status == ServiceStatus.completed) { return const Center( child: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 20), child: Icon( Icons.favorite_outline_sharp, color: Color(0xFF35A8ED), size: 70, ), ), Text( 'Servicio terminado exitosamente', style: TextStyle( color: Color(0xFF35A8ED), fontSize: 17, fontWeight: FontWeight.w600, ), ), ], ), ); } return const Center( child: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 20), child: Icon( Icons.check_circle_outline_rounded, color: Color(0xFF35A8ED), size: 70, ), ), Text( 'Servicio solicitado exitosamente', style: TextStyle( color: Color(0xFF35A8ED), fontSize: 17, fontWeight: FontWeight.w600, ), ), ], ), ); } GeneralPrimaryButton customButton( ServiceEntity service, BuildContext context) { if (service.status == ServiceStatus.pending) { return GeneralPrimaryButton( onPressed: () { final currentState = context.read().state; if (currentState is ServiceLoaded) { context.read().add( UpdateServiceStatus( widget.serviceId, ServiceStatus.cancelled, ), ); } }, color: Colors.red, label: 'Cancelar Servicio', ); } return GeneralPrimaryButton( onPressed: () { Navigator.pop(context); }, label: 'Volver', ); } String formatCurrency(int number) { final formatter = NumberFormat.currency(locale: 'es_CO', decimalDigits: 0, symbol: ''); return '\$${formatter.format(number)}'; } Future> _getUserAndProfessionalInfo( ServiceEntity service) async { final userRepo = FirebaseUserRepository(FirebaseAuth.instance); final userInfo = await userRepo.getMyUser(service.professionalId); final professionalRepo = FirebaseProfessionalRepository(); final professionalInfo = await professionalRepo.getProInfo(service.professionalId); return [userInfo, professionalInfo]; } }