import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/setting_model.dart'; import 'package:prosappco/src/models/user_model.dart'; import 'package:prosappco/src/presentation/screens/chat.dart'; import 'package:prosappco/src/presentation/screens/score.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:community_material_icon/community_material_icon.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class CitaScreen extends StatefulWidget { final Event evento; const CitaScreen({super.key, required this.evento}); @override State createState() => _CitaScreenState(); } class _CitaScreenState extends State { final uid = AuthenticationRepository.instance.getCurrentUserUid(); UserModel? user; DateTime today = DateTime.now(); String nombre = ''; String userToken = ''; String numberPhone = ''; int tarifa = 0; Reference? ref_photo; ScoresModel? scoresModel; bool? ver = true; bool? pro; String proName = ''; late final FirebaseAuth _auth; String formatCurrency(int number) { final formatter = NumberFormat.currency(locale: 'es_CO', decimalDigits: 0, symbol: ''); return '\$${formatter.format(number)}'; } Future sendPushNotification( String user, String accion, String proName) async { try { http.Response response = await http.post( Uri.parse('https://fcm.googleapis.com/fcm/send'), headers: { 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': 'key=AAAAORdR-xU:APA91bF_wblg86jHAC-uexrXPHavYRlk5wge1Gf46m56V4J2D2L37Cp_hf46JZUzpvsWPSpqc5ewHelKI9LTifUG_s2mciMI6e5VLKo7E1R8btbNo7iaM9do2ctoyHKUm1atlZBdKaN2', }, body: jsonEncode( { 'notification': { 'body': accion == 'rechazo' ? '$proName a rechazado tu solicitud de servicio' : '$proName a aprobado tu solicitud de servicio', 'title': '$proName $accion', }, 'priority': 'high', 'data': { 'click_action': 'FLUTTER_NOTIFICATION_CLICK', 'id': '1', 'status': 'done', 'screen': 'misservicios', }, 'to': user }, ), ); response; } catch (e) { print('error al enviar notificacion $e'); } } Future _openMap(double lat, double lng) async { final Uri _url = Uri.parse('https://www.google.com/maps/search/?api=1&query=$lat,$lng'); if (!await launchUrl(_url)) { throw Exception('Could not launch $_url'); } } Future _sendWhatsapp(String phoneNumber) async { final whatsappUrl = 'https://wa.me/$phoneNumber?text=${Uri.parse('Hola! me contactaste por Prossapp')}'; if (!await launch(whatsappUrl)) { throw Exception('Could not launch $whatsappUrl'); } } SettingModel? settings; @override void initState() { super.initState(); final uid = AuthenticationRepository.instance.getCurrentUserUid(); _auth = FirebaseAuth.instance; final currentUser = _auth.currentUser; if (currentUser != null && currentUser.displayName != null) { proName = currentUser.displayName!; } if (settings == null) { SettingModel.getSettings().then( (SettingModel value) => setState(() { settings = value; }), ); } if (scoresModel == null) { if (uid != widget.evento.userId) { ScoresModel.scoreTo(widget.evento.userId, false, false).then( (ScoresModel s) => setState(() { scoresModel = s; pro = true; }), ); } else { ScoresModel.scoreTo(widget.evento.professionalId, true, false).then( (ScoresModel s) => setState(() { scoresModel = s; pro = false; }), ); } } } @override Widget build(BuildContext context) { today.difference(DateTime.parse(widget.evento.range1Hour1)); final eventDate = DateFormat('yyyy-MM-dd').parse(widget.evento.day); if (nombre == '') { if (uid != widget.evento.userId) { UserModel.getUser(widget.evento.userId).then((value) { UserModel.getUser(uid.toString()).then((me) { setState(() { nombre = value.name; ref_photo = value.photo; userToken = value.token ?? ''; numberPhone = value.phoneNumber ?? ''; }); }); }); } else { UserModel.getUser(widget.evento.professionalId).then((value) { setState(() { nombre = value.name; ref_photo = value.photo; numberPhone = value.phoneNumber ?? ''; }); }); } } return Scaffold( appBar: PopAppbar( onPressed: () { Navigator.pop(context); }, label: 'Servicio'), body: Column( children: [ Expanded( child: Column( children: [ ListTile( leading: ReferencePhoto( ref: ref_photo, size: 50, sizeCircle: 50, sizeIcon: 35, ), title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( nombre, style: const TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 16, ), ), Text( '${DateFormat('dd MMMM', 'es').format(DateTime.parse(widget.evento.day))} ${DateFormat('h:mm a').format(DateTime.parse(widget.evento.range1Hour1))}', style: const TextStyle( color: Colors.grey, fontSize: 16, ), ) ], ), subtitle: Row( children: [ RatingBar.builder( initialRating: scoresModel?.average ?? 0, minRating: 1, direction: Axis.horizontal, allowHalfRating: true, itemCount: 5, itemSize: 25, maxRating: 5, itemPadding: const EdgeInsets.symmetric(horizontal: 0), itemBuilder: (context, _) => const Icon( Icons.star, color: Color(0xFF2BA4EC), ), onRatingUpdate: (rating) {}, ignoreGestures: true, ), const SizedBox(width: 5), Text( '(${scoresModel?.total.toString()}) ${scoresModel?.average.toStringAsFixed(1)}'), ], ), ), widget.evento.userId == widget.evento.professionalId ? const SizedBox() : 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), widget.evento.ubicacion != 'sitio' ? const Text( 'Servicio a domicilio.', style: TextStyle( color: Colors.black, fontSize: 14), ) : const Text( 'Servicio en su sitio / consultorio', style: TextStyle( color: Colors.black, fontSize: 14), ), ], ), ), settings?.tarifas == true && widget.evento.tarifa != 0 ? Column( children: [ Text( formatCurrency(widget.evento.tarifa ?? 0), style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 25), ), const Text('Tarifa consulta', style: TextStyle(fontSize: 15)), ], ) : const SizedBox(), const SizedBox(height: 15), // Text('${widget.evento.range1Hour1} - ${DateTime.now()}'), Text( textAlign: TextAlign.center, '"${widget.evento.description?.trim()}"', style: const TextStyle( color: Colors.grey, fontStyle: FontStyle.italic), ), widget.evento.userId == widget.evento.professionalId ? const SizedBox() : widget.evento.status == 'aprobado' || widget.evento.status == 'iniciado' ? const Padding( padding: EdgeInsets.symmetric(vertical: 20), child: Text( 'Medios de comunicación con el usuario.', style: TextStyle(color: Color(0xFF2BA4EC)), ), ) : const SizedBox(height: 10), widget.evento.userId == widget.evento.professionalId ? const SizedBox() : widget.evento.status == 'terminado' ? pro == true ? widget.evento.professionalScored == true ? const SizedBox() : Column( children: [ const SizedBox(height: 120), ElevatedButton( onPressed: () { Navigator.pushReplacement( context, CupertinoPageRoute( builder: (BuildContext context) { return ScoreScreen( evento: widget.evento, pro: pro!, ); }, ), ); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Puntuar servicio', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ], ) : widget.evento.userScored == true ? const SizedBox() : Column( children: [ const SizedBox(height: 120), ElevatedButton( onPressed: () { Navigator.pushReplacement( context, CupertinoPageRoute( builder: (BuildContext context) { return ScoreScreen( evento: widget.evento, pro: pro!, ); }, ), ); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Puntuar servicio', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ], ) : widget.evento.status == 'aprobado' || widget.evento.status == 'iniciado' ? Row( children: [ const Expanded(child: SizedBox()), ElevatedButton( onPressed: () => launch("tel:$numberPhone"), style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), side: const BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric( vertical: 18, horizontal: 0), child: Icon( Icons.phone_android, size: 30, color: Color(0xFF2BA4EC), ), ), ), const SizedBox(width: 20), ElevatedButton( onPressed: () async { if (widget.evento.status != 'pendiente') { final chatDoc = FirebaseFirestore .instance .collection('chats') .doc(widget.evento.id); final chatSnapshot = await chatDoc.get(); if (!chatSnapshot.exists || chatSnapshot.data()!['message'] == null) { await chatDoc.set( { 'professional_id': widget.evento.professionalId, 'user_id': widget.evento.userId, 'message': [], }, SetOptions(merge: true), ).catchError((error) => print( 'Error al crear el documento: $error')); } Navigator.push( context, CupertinoPageRoute( builder: (BuildContext context) { return ChatScreen( eventoId: widget.evento.id); }, ), ); } // if (widget.evento.status != 'pendiente') { // await FirebaseFirestore.instance // .collection('chats') // .doc(widget.evento.id) // .set( // { // 'professional_id': // widget.evento.professionalId, // 'user_id': widget.evento.userId, // 'message': [], // }, // SetOptions( // merge: // true)).catchError((error) => print( // 'Error al crear el documento: $error')); // Navigator.push( // context, // CupertinoPageRoute( // builder: (BuildContext context) { // return ChatScreen( // eventoId: widget.evento.id); // }, // ), // ); // } else { Get.snackbar( 'El profesional aun no ha aceptado tu solicitud', 'Debes esperar a que el profesional acepte tu solicitud para poder iniciar un chat.', snackPosition: SnackPosition.BOTTOM, ); } }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), side: const BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric( vertical: 18, horizontal: 0), child: Icon( Icons.message, size: 30, color: Color(0xFF2BA4EC), ), ), ), const SizedBox(width: 20), ElevatedButton( onPressed: () { _sendWhatsapp(numberPhone); }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), side: const BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric( vertical: 18, horizontal: 0), child: Icon( CommunityMaterialIcons.whatsapp, size: 30, color: Color(0xFF2BA4EC), ), ), ), const Expanded(child: SizedBox()), ], ) : SizedBox(), widget.evento.ubicacion == 'sitio' ? const SizedBox() : Padding( padding: const EdgeInsets.only(top: 40), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () { _openMap(widget.evento.latitud!, widget.evento.longitud!); }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), side: const BorderSide( color: Color(0xFF2BA4EC), width: 2, ), ), ), child: const Padding( padding: EdgeInsets.symmetric( vertical: 18, horizontal: 0), child: Icon( Icons.near_me, size: 30, color: Color(0xFFFFFFFF), ), ), ), const SizedBox(width: 20), SizedBox( width: 200, child: Text('${widget.evento.address}'), ) ], ), ), ], ), ), widget.evento.status == 'aprobado' ? Padding( padding: const EdgeInsets.only(bottom: 30), child: Column( children: [ Padding( padding: const EdgeInsets.only(bottom: 20), child: eventDate.year == today.year && eventDate.month == today.month && eventDate.day == today.day ? (DateTime.now() .difference(DateTime.parse( widget.evento.range1Hour1)) .abs() <= const Duration(minutes: 30) && ver == true) ? ElevatedButton( onPressed: () { FirebaseFirestore.instance .collection("services") .doc('${widget.evento.id}') .update({"status": "iniciado"}).then( (value) { setState(() { ver = false; }); }); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Iniciar servicio', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ) : const SizedBox() : const SizedBox(), ), widget.evento.professionalId == uid ? ElevatedButton( onPressed: () { FirebaseFirestore.instance .collection("services") .doc('${widget.evento.id}') .update({"status": "denegado"}).then( (value) { if (userToken != '') { sendPushNotification( userToken, 'rechazo', proName); } Navigator.pushReplacementNamed( context, '/solicitud'); }); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFEC2B2B), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Cancelar servicio', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ) : const SizedBox(), ], ), ) : const SizedBox(), widget.evento.status == 'pendiente' ? Padding( padding: const EdgeInsets.only(bottom: 30), child: Column( children: [ Padding( padding: const EdgeInsets.only(bottom: 20), child: widget.evento.professionalId == uid ? ElevatedButton( onPressed: () { FirebaseFirestore.instance .collection("services") .doc('${widget.evento.id}') .update({"status": "aprobado"}).then( (value) { if (userToken != '') { sendPushNotification( userToken, 'acepto', proName); } Navigator.pushReplacementNamed( context, '/solicitud'); }); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Aceptar', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ) : const SizedBox(), ), ElevatedButton( onPressed: () { FirebaseFirestore.instance .collection("services") .doc('${widget.evento.id}') .update({"status": "denegado"}).then((value) { if (userToken != '') { sendPushNotification( userToken, 'rechazo', proName); } Navigator.pushReplacementNamed( context, '/solicitud'); }); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFEC2B2B), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Cancelar servicio', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ], ), ) : const SizedBox(), widget.evento.status == 'iniciado' || ver == false ? Padding( padding: const EdgeInsets.only(bottom: 30), child: Column( children: [ ElevatedButton( onPressed: () { FirebaseFirestore.instance .collection("services") .doc('${widget.evento.id}') .update({"status": "terminado"}).then((value) { Navigator.pushReplacement( context, CupertinoPageRoute( builder: (BuildContext context) { return ScoreScreen( evento: widget.evento, pro: pro!, ); }, ), ); }); }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(230, 60), ), child: const Text( 'Terminar servicio', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ], ), ) : const SizedBox(), ], ), ); } }