This commit is contained in:
Juan Felipe Duarte
2023-06-20 11:21:14 -05:00
parent 05fa9438a1
commit a190833b53
10 changed files with 279 additions and 136 deletions
+54 -7
View File
@@ -1,4 +1,5 @@
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:prosappco/src/authentication/authentication_repository.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/chat_model.dart';
import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/user_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 { class ChatScreen extends StatefulWidget {
final String? eventoId; final String? eventoId;
@@ -20,6 +23,8 @@ class _ChatScreenState extends State<ChatScreen> {
final _textController = TextEditingController(); final _textController = TextEditingController();
final uid = AuthenticationRepository.instance.getCurrentUserUid(); final uid = AuthenticationRepository.instance.getCurrentUserUid();
UserModel? user; UserModel? user;
Professional? professional;
bool pro = false;
@override @override
void initState() { void initState() {
@@ -31,8 +36,10 @@ class _ChatScreenState extends State<ChatScreen> {
(UserModel s) => setState(() => user = s), (UserModel s) => setState(() => user = s),
); );
} else { } else {
Professional.getProfessional(event.professionalId)
.then((value) => {professional = value});
UserModel.getUser(event.professionalId).then( 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<ChatScreen> {
color: const Color(0xFFD6F4FF), color: const Color(0xFFD6F4FF),
alignment: Alignment.topCenter, alignment: Alignment.topCenter,
child: ListTile( child: ListTile(
leading: Padding( leading: GestureDetector(
padding: const EdgeInsets.symmetric(horizontal: 10), onTap: () {
child: ReferencePhoto( if (pro) {
ref: user?.photo, Navigator.of(context).push(
size: 55, CupertinoPageRoute(
sizeCircle: 60, 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( title: Text(
@@ -119,6 +141,31 @@ class _ChatScreenState extends State<ChatScreen> {
filled: true, filled: true,
fillColor: Colors.grey[200], 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), const SizedBox(width: 12),
+146 -109
View File
@@ -359,20 +359,24 @@ class _CitaScreenState extends State<CitaScreen> {
ElevatedButton( ElevatedButton(
onPressed: () async { onPressed: () async {
if (widget.evento.status != 'pendiente') { if (widget.evento.status != 'pendiente') {
await FirebaseFirestore.instance final chatDoc = FirebaseFirestore.instance
.collection('chats') .collection('chats')
.doc(widget.evento.id) .doc(widget.evento.id);
.set( final chatSnapshot = await chatDoc.get();
{
if (!chatSnapshot.exists ||
chatSnapshot.data()!['message'] == null) {
await chatDoc.set(
{
'professional_id': 'professional_id':
widget.evento.professionalId, widget.evento.professionalId,
'user_id': widget.evento.userId, 'user_id': widget.evento.userId,
'message': [], 'message': [],
}, },
SetOptions( SetOptions(merge: true),
merge: ).catchError((error) => print(
true)).catchError((error) => print( 'Error al crear el documento: $error'));
'Error al crear el documento: $error')); }
Navigator.push( Navigator.push(
context, context,
@@ -383,7 +387,35 @@ class _CitaScreenState extends State<CitaScreen> {
}, },
), ),
); );
} 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( final snackBar = SnackBar(
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
content: const Text( content: const Text(
@@ -497,84 +529,86 @@ class _CitaScreenState extends State<CitaScreen> {
), ),
), ),
widget.evento.status == 'aprobado' widget.evento.status == 'aprobado'
? eventDate.year == today.year && ? Padding(
eventDate.month == today.month && padding: const EdgeInsets.only(bottom: 30),
eventDate.day == today.day child: Column(
? (DateTime.now() children: [
.difference( Padding(
DateTime.parse(widget.evento.range1Hour1)) padding: const EdgeInsets.only(bottom: 20),
.abs() <= child: eventDate.year == today.year &&
const Duration(minutes: 30) && eventDate.month == today.month &&
ver == true) eventDate.day == today.day
? Padding( ? (DateTime.now()
padding: const EdgeInsets.only(bottom: 30), .difference(DateTime.parse(
child: Column( widget.evento.range1Hour1))
children: [ .abs() <=
Padding( const Duration(minutes: 30) &&
padding: const EdgeInsets.only(bottom: 20), ver == true)
child: ElevatedButton( ? ElevatedButton(
onPressed: () { onPressed: () {
FirebaseFirestore.instance FirebaseFirestore.instance
.collection("services") .collection("services")
.doc('${widget.evento.id}') .doc('${widget.evento.id}')
.update({"status": "iniciado"}).then( .update({"status": "iniciado"}).then(
(value) { (value) {
setState(() { setState(() {
ver = false; ver = false;
});
}); });
}); },
}, style: ElevatedButton.styleFrom(
style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC),
backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder(
shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50),
borderRadius: BorderRadius.circular(50), ),
elevation: 0,
minimumSize: const Size(230, 60),
), ),
elevation: 0, child: const Text(
minimumSize: const Size(230, 60), 'Iniciar servicio',
), style: TextStyle(
child: const Text( color: Colors.white,
'Iniciar servicio', fontWeight: FontWeight.bold,
style: TextStyle( fontSize: 18,
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: () { : const SizedBox(),
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' widget.evento.status == 'pendiente'
? Padding( ? Padding(
@@ -583,33 +617,36 @@ class _CitaScreenState extends State<CitaScreen> {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.only(bottom: 20),
child: ElevatedButton( child: widget.evento.professionalId == uid
onPressed: () { ? ElevatedButton(
FirebaseFirestore.instance onPressed: () {
.collection("services") FirebaseFirestore.instance
.doc('${widget.evento.id}') .collection("services")
.update({"status": "aprobado"}).then((value) { .doc('${widget.evento.id}')
Navigator.pushReplacementNamed( .update({"status": "aprobado"}).then(
context, '/solicitud'); (value) {
}); Navigator.pushReplacementNamed(
}, context, '/solicitud');
style: ElevatedButton.styleFrom( });
backgroundColor: const Color(0xFF2BA4EC), },
shape: RoundedRectangleBorder( style: ElevatedButton.styleFrom(
borderRadius: BorderRadius.circular(50), backgroundColor: const Color(0xFF2BA4EC),
), shape: RoundedRectangleBorder(
elevation: 0, borderRadius: BorderRadius.circular(50),
minimumSize: const Size(230, 60), ),
), elevation: 0,
child: const Text( minimumSize: const Size(230, 60),
'Aceptar', ),
style: TextStyle( child: const Text(
color: Colors.white, 'Aceptar',
fontWeight: FontWeight.bold, style: TextStyle(
fontSize: 18, color: Colors.white,
), fontWeight: FontWeight.bold,
), fontSize: 18,
), ),
),
)
: const SizedBox(),
), ),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
+20 -9
View File
@@ -52,8 +52,13 @@ class _MyServicesScreenState extends State<MyServicesScreen> {
stream: FirebaseFirestore.instance stream: FirebaseFirestore.instance
.collection('services') .collection('services')
.where('user_id', isEqualTo: uid) .where('user_id', isEqualTo: uid)
.where('status', .where('status', whereIn: [
whereIn: ['aprobado', 'denegado', 'iniciado', 'terminado']) 'aprobado',
'denegado',
'iniciado',
'terminado',
'pendiente'
])
.snapshots() .snapshots()
.asyncMap((snapshot) async { .asyncMap((snapshot) async {
try { try {
@@ -123,17 +128,23 @@ class _MyServicesScreenState extends State<MyServicesScreen> {
color: Colors.blue, color: Colors.blue,
size: 40, size: 40,
) )
: event.status == 'terminado' : event.status == 'pendiente'
? const Icon( ? const Icon(
Icons.rocket_launch, Icons.access_time_outlined,
color: Colors.blue, color: Colors.blue,
size: 40, size: 40,
) )
: const Icon( : event.status == 'terminado'
Icons.close, ? const Icon(
color: Colors.red, Icons.rocket_launch,
size: 40, color: Colors.blue,
), size: 40,
)
: const Icon(
Icons.close,
color: Colors.red,
size: 40,
),
title: RichText( title: RichText(
text: TextSpan( text: TextSpan(
children: [ children: [
@@ -258,6 +258,9 @@ class _ProfessionalProfileWebScreenState
.child(random); .child(random);
final metaData = SettableMetadata(contentType: 'image/jpeg'); 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); final UploadTask uploadTask = ref.putData(imageCedulaBytes!, metaData);
+6 -6
View File
@@ -445,10 +445,10 @@ class _ProfileProState extends State<ProfilePro> {
}, },
child: Column( child: Column(
children: [ children: [
Padding( const Padding(
padding: const EdgeInsets.symmetric(vertical: 10), padding: EdgeInsets.symmetric(vertical: 10),
child: Row( child: Row(
children: const [ children: [
Expanded( Expanded(
child: Padding( child: Padding(
padding: EdgeInsets.only(left: 30), padding: EdgeInsets.only(left: 30),
@@ -482,11 +482,11 @@ class _ProfileProState extends State<ProfilePro> {
: const EdgeInsets.only(bottom: 70), : const EdgeInsets.only(bottom: 70),
child: Row( child: Row(
children: [ children: [
Padding( const Padding(
padding: const EdgeInsets.only(left: 30), padding: EdgeInsets.only(left: 30),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: const [ children: [
Text('Lunes'), Text('Lunes'),
Text('Martes'), Text('Martes'),
Text('Miércoles'), Text('Miércoles'),
+2 -2
View File
@@ -258,7 +258,7 @@ class _ProfileWebScreenState extends State<ProfileWebScreen> {
body: Center( body: Center(
child: SizedBox( child: SizedBox(
width: 300, width: 300,
height: 550, height: 600,
child: Card( child: Card(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
@@ -412,7 +412,7 @@ class _ProfileWebScreenState extends State<ProfileWebScreen> {
), ),
Container( Container(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
margin: const EdgeInsets.only(top: 50), margin: const EdgeInsets.only(top: 30),
padding: const EdgeInsets.only(bottom: 30), padding: const EdgeInsets.only(bottom: 30),
child: ElevatedButton( child: ElevatedButton(
onPressed: () async { onPressed: () async {
+21 -3
View File
@@ -1,4 +1,5 @@
import 'package:community_material_icon/community_material_icon.dart'; import 'package:community_material_icon/community_material_icon.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
@@ -14,6 +15,8 @@ class SupportScreen extends StatefulWidget {
class SsupportStateScreen extends State<SupportScreen> { class SsupportStateScreen extends State<SupportScreen> {
SettingModel? settings; SettingModel? settings;
final String subject = 'Soporte Prosapp';
final String body = '';
Future<void> _sendWhatsapp(String? number) async { Future<void> _sendWhatsapp(String? number) async {
final _whatsappUrl = final _whatsappUrl =
@@ -26,8 +29,8 @@ class SsupportStateScreen extends State<SupportScreen> {
Future<void> _sendEmail(String recipients) async { Future<void> _sendEmail(String recipients) async {
final Email email = Email( final Email email = Email(
body: '', body: body,
subject: 'Soporte Prosapp', subject: subject,
recipients: [recipients], recipients: [recipients],
isHTML: false, isHTML: false,
); );
@@ -35,6 +38,17 @@ class SsupportStateScreen extends State<SupportScreen> {
await FlutterEmailSender.send(email); 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 @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -98,7 +112,11 @@ class SsupportStateScreen extends State<SupportScreen> {
const SizedBox(width: 20), const SizedBox(width: 20),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
_sendEmail(settings?.email ?? ''); if (kIsWeb) {
_sendEmailWeb(settings?.email ?? '');
} else {
_sendEmail(settings?.email ?? '');
}
}, },
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, foregroundColor: Colors.white,
@@ -6,6 +6,7 @@ import FlutterMacOS
import Foundation import Foundation
import cloud_firestore import cloud_firestore
import device_info_plus
import file_selector_macos import file_selector_macos
import firebase_auth import firebase_auth
import firebase_core import firebase_core
@@ -17,6 +18,7 @@ import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
+24
View File
@@ -129,6 +129,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.8" 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: diacritic:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1037,6 +1053,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.3" 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: xdg_directories:
dependency: transitive dependency: transitive
description: description:
+1
View File
@@ -66,6 +66,7 @@ dependencies:
flutter_local_notifications: ^14.1.1 flutter_local_notifications: ^14.1.1
http: ^0.13.5 http: ^0.13.5
flutter_dialogs: ^3.0.0 flutter_dialogs: ^3.0.0
device_info_plus: ^9.0.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: