import 'package:community_material_icon/community_material_icon.dart'; 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_secondary_button.dart'; import 'package:prosappco/screens/chat/chat_screen.dart'; import 'package:prosappco/screens/score/score_screen.dart'; import 'package:service_repository/service_repository.dart'; import 'package:setting_repository/setting_repository.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:user_repository/user_repository.dart'; class ProfessionalServiceScreen extends StatefulWidget { final String serviceId; const ProfessionalServiceScreen({super.key, required this.serviceId}); @override State createState() => _ProfessionalServiceScreenState(); } class _ProfessionalServiceScreenState 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; return Column( children: [ Expanded( child: SingleChildScrollView( child: 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 domicilio.', style: TextStyle( color: Colors.black, fontSize: 14, ), ) : const Text( 'Servicio en tu consultorio', style: TextStyle( color: Colors.black, fontSize: 14, ), ), ], ), ), customMapButton(service), // 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, ), ), ), const SizedBox(height: 20), customActionButtons(service, userInfo), const SizedBox(height: 60), customMessageStatus(service), const SizedBox(height: 20), ], ), ), ), const Divider( height: 1, thickness: 0.5, ), Padding( padding: const EdgeInsets.symmetric( vertical: 10, horizontal: 15, ), child: customButton(service, context), ), ], ); } } }, ); } else { BlocProvider.of(context) .add(LoadService(widget.serviceId)); return const Center(child: CircularProgressIndicator()); } }, ), ), ); } Widget customActionButtons(ServiceEntity service, MyUser user) { if (service.status == ServiceStatus.acepted || service.status == ServiceStatus.active) { return Wrap( alignment: WrapAlignment.center, spacing: 15, children: [ Visibility( visible: user.phone == null ? false : true, child: ElevatedButton( onPressed: () => launch("tel:${user.phone}"), style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, shape: const CircleBorder( side: BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric(vertical: 20, horizontal: 0), child: Icon( Icons.phone_android, size: 30, color: Color(0xFF2BA4EC), ), ), ), ), ElevatedButton( onPressed: () { if (service.id != null) { Navigator.push( context, CupertinoPageRoute( builder: (context) => ChatScreen(service: service), ), ); } }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, shape: const CircleBorder( side: BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric(vertical: 20, horizontal: 0), child: Icon( Icons.message, size: 30, color: Color(0xFF2BA4EC), ), ), ), Visibility( visible: user.phone == null ? false : true, child: ElevatedButton( onPressed: () async { final whatsappUrl = 'https://wa.me/${user.phone}?text=${Uri.parse('Hola! me contactaste por Prossapp')}'; if (!await launch(whatsappUrl)) { throw Exception('Could not launch $whatsappUrl'); } }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, shape: const CircleBorder( side: BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric(vertical: 20, horizontal: 0), child: Icon( CommunityMaterialIcons.whatsapp, size: 30, color: Color(0xFF2BA4EC), ), ), ), ), ], ); } return const SizedBox(); } Widget customMapButton(ServiceEntity service) { if ((service.status == ServiceStatus.acepted || service.status == ServiceStatus.pending || service.status == ServiceStatus.active) && service.location == ServiceLocationPreferences.delivery) { return Padding( padding: const EdgeInsets.only( top: 8, bottom: 25, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () async { final Uri url = Uri.parse( 'https://www.google.com/maps/search/?api=1&query=${service.latitude},${service.longitude}'); if (!await launchUrl(url)) { throw Exception('Could not launch $url'); } }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: const Color(0xFF2BA4EC), shape: const CircleBorder( side: BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric( vertical: 20, horizontal: 0, ), child: Icon( Icons.near_me, size: 30, color: Colors.white, ), ), ), const SizedBox(width: 15), SizedBox( width: 230, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( service.address, maxLines: 3, textAlign: TextAlign.start, style: const TextStyle( fontSize: 15, //center ), ), service.aditionalAddress.isEmpty ? Container() : Text( service.aditionalAddress, textAlign: TextAlign.start, maxLines: 3, style: const TextStyle( fontSize: 15, color: Colors.black54, ), ), ], ), ), ], ), ); } return const SizedBox(); } Widget customMessageStatus(ServiceEntity service) { // if (service.status == ServiceStatus.acepted) { // return Stack( // alignment: AlignmentDirectional.topCenter, // clipBehavior: Clip.none, // children: [ // Card( // color: Colors.green.shade50, // child: const Padding( // padding: EdgeInsets.fromLTRB(32, 56, 32, 32), // child: Text( // 'Aceptado', // style: TextStyle(fontSize: 32, color: Colors.green), // ), // ), // ), // Positioned( // top: -40, // child: Container( // padding: const EdgeInsets.all(16), // decoration: BoxDecoration( // color: Colors.white, // border: Border.all(color: Colors.green.shade50, width: 4), // shape: BoxShape.circle, // ), // child: const Icon(Icons.check, color: Colors.green, size: 48), // ), // ) // ], // ); // } if (service.status == ServiceStatus.cancelled) { return Stack( alignment: AlignmentDirectional.topCenter, clipBehavior: Clip.none, children: [ Card( color: Colors.red.shade100, child: const Padding( padding: EdgeInsets.fromLTRB(32, 56, 32, 32), child: Text( 'Cancelado', style: TextStyle(fontSize: 32, color: Colors.red), ), ), ), Positioned( top: -40, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.red.shade100, width: 4), shape: BoxShape.circle, ), child: const Icon(Icons.close_rounded, color: Colors.red, size: 48), ), ) ], ); } if (service.status == ServiceStatus.denied) { return Stack( alignment: AlignmentDirectional.topCenter, clipBehavior: Clip.none, children: [ Card( color: Colors.red.shade100, child: const Padding( padding: EdgeInsets.fromLTRB(32, 56, 32, 32), child: Text( 'Rechazado', style: TextStyle(fontSize: 32, color: Colors.red), ), ), ), Positioned( top: -40, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.red.shade100, width: 4), shape: BoxShape.circle, ), child: const Icon(Icons.close_rounded, color: Colors.red, size: 48), ), ) ], ); } if (service.status == ServiceStatus.completed) { if (service.userScored) { return Stack( alignment: AlignmentDirectional.topCenter, clipBehavior: Clip.none, children: [ Card( color: Colors.green.shade50, child: const Padding( padding: EdgeInsets.fromLTRB(32, 56, 32, 32), child: Text( 'Completado', style: TextStyle(fontSize: 32, color: Colors.green), ), ), ), Positioned( top: -40, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.green.shade50, width: 4), shape: BoxShape.circle, ), child: const Icon( Icons.check_rounded, color: Colors.green, size: 48, ), ), ) ], ); } else { return Stack( alignment: AlignmentDirectional.topCenter, clipBehavior: Clip.none, children: [ Card( color: Colors.green.shade50, child: Padding( padding: const EdgeInsets.fromLTRB(32, 56, 32, 32), child: Column( children: [ const Text( 'Completado', style: TextStyle(fontSize: 32, color: Colors.green), ), const SizedBox(height: 16), const Text( 'Califica el servicio', style: TextStyle(fontSize: 28, color: Colors.green), ), FilledButton( onPressed: () { Navigator.push( context, CupertinoPageRoute( builder: (context) => ScoreScreen( service: service, ), ), ); }, child: const Text('Calificar'), ), ], ), ), ), Positioned( top: -40, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.green.shade50, width: 4), shape: BoxShape.circle, ), child: const Icon( Icons.star, color: Colors.green, size: 48, ), ), ) ], ); } } return const SizedBox(); } Widget customButton(ServiceEntity service, BuildContext context) { if (service.status == ServiceStatus.pending) { return Column( children: [ GeneralSecondaryButton( label: 'Rechazar servicio', color: Theme.of(context).colorScheme.error, onPressed: () { final currentState = context.read().state; if (currentState is ServiceLoaded) { context.read().add(UpdateServiceStatus( widget.serviceId, ServiceStatus.denied)); } }, ), const SizedBox(height: 10), GeneralSecondaryButton( label: 'Aceptar servicio', onPressed: () { final currentState = context.read().state; if (currentState is ServiceLoaded) { context.read().add(UpdateServiceStatus( widget.serviceId, ServiceStatus.acepted)); } }, ), ], ); } if (service.status == ServiceStatus.acepted) { return GeneralSecondaryButton( label: 'Iniciar servicio', onPressed: () { final currentState = context.read().state; if (currentState is ServiceLoaded) { context.read().add( UpdateServiceStatus(widget.serviceId, ServiceStatus.active)); } }, ); } if (service.status == ServiceStatus.active) { return GeneralSecondaryButton( label: 'Terminar servicio', onPressed: () { final currentState = context.read().state; if (currentState is ServiceLoaded) { context.read().add(UpdateServiceStatus( widget.serviceId, ServiceStatus.completed)); } }); } return GeneralSecondaryButton( label: 'Volver', onPressed: () { Navigator.pop(context); }); // customStatusButton( // label: 'Volver', // onPressed: () { // Navigator.pop(context); // }, // ); } 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.userId); return [userInfo]; } }