diff --git a/lib/src/screens/chat.dart b/lib/src/screens/chat.dart index 8119df2..26068c2 100644 --- a/lib/src/screens/chat.dart +++ b/lib/src/screens/chat.dart @@ -1,4 +1,5 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; @@ -7,6 +8,8 @@ import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/models/chat_model.dart'; import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/user_model.dart'; +import 'package:prosappco/src/screens/professional.dart'; +import 'package:prosappco/src/screens/professional_info.dart'; class ChatScreen extends StatefulWidget { final String? eventoId; @@ -20,6 +23,8 @@ class _ChatScreenState extends State { final _textController = TextEditingController(); final uid = AuthenticationRepository.instance.getCurrentUserUid(); UserModel? user; + Professional? professional; + bool pro = false; @override void initState() { @@ -31,8 +36,10 @@ class _ChatScreenState extends State { (UserModel s) => setState(() => user = s), ); } else { + Professional.getProfessional(event.professionalId) + .then((value) => {professional = value}); UserModel.getUser(event.professionalId).then( - (UserModel s) => setState(() => user = s), + (UserModel s) => setState(() => {user = s, pro = true}), ); } } @@ -65,12 +72,27 @@ class _ChatScreenState extends State { color: const Color(0xFFD6F4FF), alignment: Alignment.topCenter, child: ListTile( - leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: ReferencePhoto( - ref: user?.photo, - size: 55, - sizeCircle: 60, + leading: GestureDetector( + onTap: () { + if (pro) { + Navigator.of(context).push( + CupertinoPageRoute( + builder: (BuildContext context) { + return ProfessionalInfoScreen( + professional: professional!, + ); + }, + ), + ); + } + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: ReferencePhoto( + ref: user?.photo, + size: 55, + sizeCircle: 60, + ), ), ), title: Text( @@ -119,6 +141,31 @@ class _ChatScreenState extends State { filled: true, fillColor: Colors.grey[200], ), + onFieldSubmitted: (value) { + String muestra = _textController.text.trim(); + if (muestra.isNotEmpty) { + final nuevoMensaje = MessageModel( + user: uid!, + content: + _textController.text.trimLeft().trimRight(), + timestamp: DateTime.now()); + + final nuevoMensajeMap = { + 'user': nuevoMensaje.user, + 'content': nuevoMensaje.content, + 'timestamp': nuevoMensaje.timestamp, + }; + + FirebaseFirestore.instance + .collection('chats') + .doc(widget.eventoId) + .update({ + 'message': FieldValue.arrayUnion([nuevoMensajeMap]) + }); + + _textController.clear(); + } else {} + }, ), ), const SizedBox(width: 12), diff --git a/lib/src/screens/cita.dart b/lib/src/screens/cita.dart index a974678..95a3f0c 100644 --- a/lib/src/screens/cita.dart +++ b/lib/src/screens/cita.dart @@ -359,20 +359,24 @@ class _CitaScreenState extends State { ElevatedButton( onPressed: () async { if (widget.evento.status != 'pendiente') { - await FirebaseFirestore.instance + final chatDoc = FirebaseFirestore.instance .collection('chats') - .doc(widget.evento.id) - .set( - { + .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')); + SetOptions(merge: true), + ).catchError((error) => print( + 'Error al crear el documento: $error')); + } Navigator.push( context, @@ -383,7 +387,35 @@ class _CitaScreenState extends State { }, ), ); - } else { + } + + // 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 { final snackBar = SnackBar( backgroundColor: Colors.blue, content: const Text( @@ -497,84 +529,86 @@ class _CitaScreenState extends State { ), ), widget.evento.status == 'aprobado' - ? 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) - ? Padding( - padding: const EdgeInsets.only(bottom: 30), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 20), - child: ElevatedButton( - onPressed: () { - FirebaseFirestore.instance - .collection("services") - .doc('${widget.evento.id}') - .update({"status": "iniciado"}).then( - (value) { - setState(() { - ver = false; + ? 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), + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF2BA4EC), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: const Size(230, 60), ), - elevation: 0, - minimumSize: const Size(230, 60), - ), - child: const Text( - 'Iniciar servicio', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18, + 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) { + 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, ), ), - ElevatedButton( - onPressed: () { - FirebaseFirestore.instance - .collection("services") - .doc('${widget.evento.id}') - .update({"status": "denegado"}).then( - (value) { - 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() + ) + : const SizedBox(), + ], + ), + ) : const SizedBox(), widget.evento.status == 'pendiente' ? Padding( @@ -583,33 +617,36 @@ class _CitaScreenState extends State { children: [ Padding( padding: const EdgeInsets.only(bottom: 20), - child: ElevatedButton( - onPressed: () { - FirebaseFirestore.instance - .collection("services") - .doc('${widget.evento.id}') - .update({"status": "aprobado"}).then((value) { - 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, - ), - ), - ), + child: widget.evento.professionalId == uid + ? ElevatedButton( + onPressed: () { + FirebaseFirestore.instance + .collection("services") + .doc('${widget.evento.id}') + .update({"status": "aprobado"}).then( + (value) { + 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: () { diff --git a/lib/src/screens/my_services.dart b/lib/src/screens/my_services.dart index f09a59b..5462ea5 100644 --- a/lib/src/screens/my_services.dart +++ b/lib/src/screens/my_services.dart @@ -52,8 +52,13 @@ class _MyServicesScreenState extends State { stream: FirebaseFirestore.instance .collection('services') .where('user_id', isEqualTo: uid) - .where('status', - whereIn: ['aprobado', 'denegado', 'iniciado', 'terminado']) + .where('status', whereIn: [ + 'aprobado', + 'denegado', + 'iniciado', + 'terminado', + 'pendiente' + ]) .snapshots() .asyncMap((snapshot) async { try { @@ -123,17 +128,23 @@ class _MyServicesScreenState extends State { color: Colors.blue, size: 40, ) - : event.status == 'terminado' + : event.status == 'pendiente' ? const Icon( - Icons.rocket_launch, + Icons.access_time_outlined, color: Colors.blue, size: 40, ) - : const Icon( - Icons.close, - color: Colors.red, - size: 40, - ), + : event.status == 'terminado' + ? const Icon( + Icons.rocket_launch, + color: Colors.blue, + size: 40, + ) + : const Icon( + Icons.close, + color: Colors.red, + size: 40, + ), title: RichText( text: TextSpan( children: [ diff --git a/lib/src/screens/professional_profile_web.dart b/lib/src/screens/professional_profile_web.dart index 32c7b6a..8a548f1 100644 --- a/lib/src/screens/professional_profile_web.dart +++ b/lib/src/screens/professional_profile_web.dart @@ -258,6 +258,9 @@ class _ProfessionalProfileWebScreenState .child(random); final metaData = SettableMetadata(contentType: 'image/jpeg'); + // final metaDataImg = SettableMetadata(contentType: 'image/jpeg'); + // final metaDataPdf = SettableMetadata(contentType: 'application/pdf'); + // final metaDataWord = SettableMetadata(contentType: 'application/msword'); final UploadTask uploadTask = ref.putData(imageCedulaBytes!, metaData); diff --git a/lib/src/screens/profile_pro.dart b/lib/src/screens/profile_pro.dart index 3f78415..a496aaa 100644 --- a/lib/src/screens/profile_pro.dart +++ b/lib/src/screens/profile_pro.dart @@ -445,10 +445,10 @@ class _ProfileProState extends State { }, child: Column( children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + const Padding( + padding: EdgeInsets.symmetric(vertical: 10), child: Row( - children: const [ + children: [ Expanded( child: Padding( padding: EdgeInsets.only(left: 30), @@ -482,11 +482,11 @@ class _ProfileProState extends State { : const EdgeInsets.only(bottom: 70), child: Row( children: [ - Padding( - padding: const EdgeInsets.only(left: 30), + const Padding( + padding: EdgeInsets.only(left: 30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: const [ + children: [ Text('Lunes'), Text('Martes'), Text('Miércoles'), diff --git a/lib/src/screens/profile_web.dart b/lib/src/screens/profile_web.dart index 0cde6eb..1ab7ab9 100644 --- a/lib/src/screens/profile_web.dart +++ b/lib/src/screens/profile_web.dart @@ -258,7 +258,7 @@ class _ProfileWebScreenState extends State { body: Center( child: SizedBox( width: 300, - height: 550, + height: 600, child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), @@ -412,7 +412,7 @@ class _ProfileWebScreenState extends State { ), Container( alignment: Alignment.bottomCenter, - margin: const EdgeInsets.only(top: 50), + margin: const EdgeInsets.only(top: 30), padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton( onPressed: () async { diff --git a/lib/src/screens/support.dart b/lib/src/screens/support.dart index fd3922c..cadd749 100644 --- a/lib/src/screens/support.dart +++ b/lib/src/screens/support.dart @@ -1,4 +1,5 @@ import 'package:community_material_icon/community_material_icon.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart'; import 'package:prosappco/src/components/pop_appbar.dart'; @@ -14,6 +15,8 @@ class SupportScreen extends StatefulWidget { class SsupportStateScreen extends State { SettingModel? settings; + final String subject = 'Soporte Prosapp'; + final String body = ''; Future _sendWhatsapp(String? number) async { final _whatsappUrl = @@ -26,8 +29,8 @@ class SsupportStateScreen extends State { Future _sendEmail(String recipients) async { final Email email = Email( - body: '', - subject: 'Soporte Prosapp', + body: body, + subject: subject, recipients: [recipients], isHTML: false, ); @@ -35,6 +38,17 @@ class SsupportStateScreen extends State { await FlutterEmailSender.send(email); } + void _sendEmailWeb(String recipients) async { + final email = + 'mailto:$recipients?subject=${Uri.encodeComponent(recipients)}&body=${Uri.encodeComponent(body)}'; + if (await canLaunch(email)) { + await launch(email); + } else { + // No se pudo abrir el cliente de correo electrónico + // Puedes mostrar un diálogo o realizar otra acción en este caso + } + } + @override void initState() { super.initState(); @@ -98,7 +112,11 @@ class SsupportStateScreen extends State { const SizedBox(width: 20), ElevatedButton( onPressed: () { - _sendEmail(settings?.email ?? ''); + if (kIsWeb) { + _sendEmailWeb(settings?.email ?? ''); + } else { + _sendEmail(settings?.email ?? ''); + } }, style: ElevatedButton.styleFrom( foregroundColor: Colors.white, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 1568684..82c1c20 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,6 +6,7 @@ import FlutterMacOS import Foundation import cloud_firestore +import device_info_plus import file_selector_macos import firebase_auth import firebase_core @@ -17,6 +18,7 @@ import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 05f36cb..7c053fa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.8" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: "2c35b6d1682b028e42d07b3aee4b98fa62996c10bc12cb651ec856a80d6a761b" + url: "https://pub.dev" + source: hosted + version: "9.0.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" diacritic: dependency: "direct main" description: @@ -1037,6 +1053,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.3" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 + url: "https://pub.dev" + source: hosted + version: "1.1.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 851e8d6..1bf4f6f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,7 @@ dependencies: flutter_local_notifications: ^14.1.1 http: ^0.13.5 flutter_dialogs: ^3.0.0 + device_info_plus: ^9.0.2 dev_dependencies: flutter_test: