This commit is contained in:
Felipe
2023-11-11 18:13:58 -05:00
parent f732d461d0
commit 24f0d80e32
15 changed files with 1439 additions and 194 deletions
+76 -1
View File
@@ -1 +1,76 @@
const String apiKey = 'AIzaSyBqZNw7kj3pEYH-pusqTMxXhbja8HR7eOc'; const String GOOGLE_MAPS_API_KEY = 'AIzaSyCW_og6qQ8W8G-5_BxIS4sBnl8cLkjL95s';
const String MAP_STYLE = '''
[
{
"elementType": "labels.icon",
"stylers": [
{
"visibility": "on",
"color": "#6F6F6F"
}
]
},
{
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#f5f5f5"
}
]
},
{
"featureType": "administrative.land_parcel",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#bdbdbd"
}
]
},
{
"featureType": "poi",
"elementType": "geometry",
"stylers": [
{
"color": "#eeeeee"
}
]
},
{
"featureType": "poi",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "poi.park",
"elementType": "geometry",
"stylers": [
{
"color": "#e5e5e5"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
}
]
''';
+1 -1
View File
@@ -21,7 +21,7 @@ import 'package:prosappco/src/presentation/screens/profile/profile_pro.dart';
import 'package:prosappco/src/presentation/screens/register/register.dart'; import 'package:prosappco/src/presentation/screens/register/register.dart';
import 'package:prosappco/src/presentation/screens/request_sent.dart'; import 'package:prosappco/src/presentation/screens/request_sent.dart';
import 'package:prosappco/src/presentation/screens/reset_password/reset_password.dart'; import 'package:prosappco/src/presentation/screens/reset_password/reset_password.dart';
import 'package:prosappco/src/presentation/screens/service.dart'; import 'package:prosappco/src/presentation/screens/map/service.dart';
import 'package:prosappco/src/presentation/screens/solicitudes.dart'; import 'package:prosappco/src/presentation/screens/solicitudes.dart';
import 'package:prosappco/src/services/local_notifications.dart'; import 'package:prosappco/src/services/local_notifications.dart';
import 'firebase_options.dart'; import 'firebase_options.dart';
@@ -4,7 +4,8 @@ import 'package:get/get.dart';
import 'package:google_sign_in/google_sign_in.dart'; import 'package:google_sign_in/google_sign_in.dart';
import 'package:prosappco/src/authentication/exceptions/register_failed.dart'; import 'package:prosappco/src/authentication/exceptions/register_failed.dart';
import 'package:prosappco/src/presentation/screens/login/login.dart'; import 'package:prosappco/src/presentation/screens/login/login.dart';
import 'package:prosappco/src/presentation/screens/service.dart'; // import 'package:prosappco/src/presentation/screens/service.dart';
import 'package:prosappco/src/presentation/screens/map/service.dart';
class AuthenticationRepository extends GetxController { class AuthenticationRepository extends GetxController {
static AuthenticationRepository get instance => Get.find(); static AuthenticationRepository get instance => Get.find();
+2 -1
View File
@@ -1,6 +1,7 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/presentation/screens/service.dart'; // import 'package:prosappco/src/presentation/screens/service.dart';
import 'package:prosappco/src/presentation/screens/map/service.dart';
class OTPController extends GetxController { class OTPController extends GetxController {
static OTPController get instance => Get.find(); static OTPController get instance => Get.find();
+41 -16
View File
@@ -29,30 +29,55 @@ class SettingModel {
this.terminosCondiciones, this.terminosCondiciones,
); );
static Future<SettingModel> fromJson(Map<String, dynamic> json) async { static Future<SettingModel> fromJson(Map<String, dynamic>? json) async {
try { try {
if (json == null) if (json == null) {
return SettingModel( return SettingModel(
false, false, false, '', '', '', '', '', '', '', '', ''); false,
false,
false,
'',
'',
'',
'',
'',
'',
'',
'',
'',
);
}
return SettingModel( return SettingModel(
json['domicilio'], json['domicilios'] ?? false,
json['google'], json['google'] ?? false,
json['tarifa'], json['tarifas'] ?? false,
json['titulo_soporte'], json['titulo_soporte'] ?? '',
json['parrafo_soporte'], json['parrafo_soporte'] ?? '',
json['numero_soporte'], json['numero_soporte'] ?? '',
json['email_soporte'], json['email_soporte'] ?? '',
json['dias_soporte'], json['dias_soporte'] ?? '',
json['horas_soporte'], json['horas_soporte'] ?? '',
json['version'], json['version'] ?? '', // Asegúrate de manejar nulos aquí
json['politicas_privacidad'], json['politicas_privacidad'] ?? '',
json['terminos_condiciones'], json['terminos_condiciones'] ?? '',
); );
} catch (e) { } catch (e) {
print('Error settings: $e'); print('Error settings: $e');
return SettingModel( return SettingModel(
false, false, false, '', '', '', '', '', '', '', '', ''); false,
false,
false,
'',
'',
'',
'',
'',
'',
'',
'',
'',
);
} }
} }
File diff suppressed because it is too large Load Diff
@@ -8,6 +8,7 @@ import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/controllers/info_%20professional.dart'; import 'package:prosappco/src/controllers/info_%20professional.dart';
import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart';
import 'package:prosappco/src/services/select_image_profile.dart'; import 'package:prosappco/src/services/select_image_profile.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
@@ -187,7 +188,7 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
Reference ref = Reference ref =
storage.ref().child('users').child(uid!).child('cedula').child(random); storage.ref().child('users').child(uid!).child('cedula').child(random);
final UploadTask uploadTask = ref.putFile(image); final UploadTask uploadTask = ref.putFile(image, metadata);
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
@@ -217,6 +218,10 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
} }
} }
final metadata = SettableMetadata(
contentType: 'application/pdf',
);
Future<bool> uploadCertificado(File image) async { Future<bool> uploadCertificado(File image) async {
final now = DateTime.now(); final now = DateTime.now();
final formattedDate = DateFormat('HHmmssddMMyyyy').format(now); final formattedDate = DateFormat('HHmmssddMMyyyy').format(now);
@@ -230,7 +235,7 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
.child('certificado_profesional') .child('certificado_profesional')
.child(random); .child(random);
final UploadTask uploadTask = ref.putFile(image); final UploadTask uploadTask = ref.putFile(image, metadata);
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
@@ -281,24 +286,31 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
} }
Future<bool> uploadImage(File image) async { Future<bool> uploadImage(File image) async {
final String namefile = image.path.split('/').last; try {
final String namefile = image.path.split('/').last;
Reference ref = storage Reference ref = storage
.ref() .ref()
.child('users') .child('users')
.child(uid!) .child(uid!)
.child('profile') .child('profile')
.child(namefile); .child(namefile);
final UploadTask uploadTask = ref.putFile(image); final UploadTask uploadTask = ref.putFile(image);
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); final TaskSnapshot snapshot = await uploadTask;
photoTemp = ref.fullPath; if (snapshot.state == TaskState.success) {
// Obtén la URL de descarga de la imagen y actualiza en Firestore
String downloadURL = await ref.getDownloadURL();
await updateImage(downloadURL);
if (snapshot.state == TaskState.success) { return true;
return true; } else {
} else { return false;
}
} catch (e) {
print('Error al cargar la imagen: $e');
return false; return false;
} }
} }
@@ -361,7 +373,7 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
.child('especializaciones') .child('especializaciones')
.child('e${DateTime.now().millisecondsSinceEpoch}.pdf'); .child('e${DateTime.now().millisecondsSinceEpoch}.pdf');
final UploadTask uploadTask = ref.putFile(image); final UploadTask uploadTask = ref.putFile(image, metadata);
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
@@ -419,22 +431,47 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
especializacion.split(',').map((e) => e.trim()).toList(); especializacion.split(',').map((e) => e.trim()).toList();
if (cedula.isEmpty) { if (cedula.isEmpty) {
_showCustomSnackBar( WarningSnackbar.show(
context, 'Por favor, adjunta el documento PDF de tu cédula.'); title: 'Te faltan campos!!',
message: 'Por favor, ingresa tu cedula',
);
return; return;
} }
if (image_cedula == null) { if (image_cedula == null) {
_showCustomSnackBar( WarningSnackbar.show(
context, 'Por favor, adjunte el documento PDF de su cédula.'); title: 'Te faltan archivos!!',
message: 'Por favor, adjunta el documento PDF de tu cedula',
);
return;
}
if (_profession.isEmpty) {
WarningSnackbar.show(
title: 'Te falta elegir una profesión!!',
message:
'Por favor, elige tu profesión antes de enviar la información.',
);
return; return;
} }
if (image_certificado == null) { if (image_certificado == null) {
_showCustomSnackBar(context, WarningSnackbar.show(
'Por favor, adjunta el documento PDF de tu certificado. ¡Gracias por tu colaboración!'); title: 'Te faltan archivos!!',
message: 'Por favor, adjunta el documento PDF de tu certificado',
);
return; return;
} }
if (imagen_to_upload == null) {
WarningSnackbar.show(
title: 'Sube una foto de perfil',
message: 'Para continuar debes subir una imagen de perfil',
);
return;
} else {
// Actualiza la imagen de perfil si hay cambios
updateImage(photoTemp);
}
// Actualiza los datos del usuario en Firestore // Actualiza los datos del usuario en Firestore
await FirebaseFirestore.instance.collection('users').doc(uid).update({ await FirebaseFirestore.instance.collection('users').doc(uid).update({
@@ -448,11 +485,6 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
uploadCertificado(image_certificado!); uploadCertificado(image_certificado!);
uploadEspecializaciones(images_especializacion); uploadEspecializaciones(images_especializacion);
// Actualiza la imagen de perfil si hay cambios
if (imagen_to_upload != null) {
updateImage(photoTemp);
}
// Navega a la siguiente pantalla
Navigator.pushReplacementNamed(context, '/solicitudEnviada'); Navigator.pushReplacementNamed(context, '/solicitudEnviada');
} }
+177 -113
View File
@@ -13,9 +13,13 @@ import 'package:prosappco/src/presentation/widgets/profile/birth_date_picker.dar
import 'package:prosappco/src/presentation/screens/city.dart'; import 'package:prosappco/src/presentation/screens/city.dart';
import 'package:prosappco/src/presentation/screens/new_number.dart'; import 'package:prosappco/src/presentation/screens/new_number.dart';
import 'package:prosappco/src/presentation/screens/new_password.dart'; import 'package:prosappco/src/presentation/screens/new_password.dart';
import 'package:prosappco/src/presentation/widgets/shared/primary_checkbox.dart';
import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart';
import 'package:prosappco/src/providers/user_provider.dart';
import 'package:prosappco/src/services/select_image_profile.dart'; import 'package:prosappco/src/services/select_image_profile.dart';
import 'package:prosappco/src/presentation/widgets/profile/gender_dropdown.dart'; import 'package:prosappco/src/presentation/widgets/profile/gender_dropdown.dart';
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart'; import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
import 'package:provider/provider.dart';
import '../../../components/photo_view.dart'; import '../../../components/photo_view.dart';
class ProfileScreen extends StatefulWidget { class ProfileScreen extends StatefulWidget {
@@ -275,13 +279,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
return; return;
} }
if (newEmail.isEmpty) { if (enableLoginWithEmail) {
Get.snackbar( if (newEmail.isEmpty) {
'Correo Invalido', Get.snackbar(
'Ingresa un email válido.', 'Correo Invalido',
snackPosition: SnackPosition.BOTTOM, 'Ingresa un email válido.',
); snackPosition: SnackPosition.BOTTOM,
return; );
return;
}
} }
if (currentUser?.displayName != newName) { if (currentUser?.displayName != newName) {
@@ -296,18 +302,29 @@ class _ProfileScreenState extends State<ProfileScreen> {
} }
} }
if (currentUser?.email != newEmail) { if (enableLoginWithEmail) {
if (newPassword.isNotEmpty) { if (currentUser?.email != newEmail) {
await FirebaseFirestore.instance.collection('users').doc(uid).update({ if (newPassword.isNotEmpty) {
'email': newEmail, bool updateEmailSuccess =
}); await updateEmailAndPassword(newEmail, newPassword);
updateEmailAndPassword(newEmail, newPassword);
} else { if (updateEmailSuccess) {
Get.snackbar( await FirebaseFirestore.instance
'Contraseña Invalida', .collection('users')
'Porfavor ingresa una contraseña.', .doc(uid)
snackPosition: SnackPosition.BOTTOM, .update({
); 'email': newEmail,
});
} else {
return;
}
} else {
Get.snackbar(
'Contraseña Invalida',
'Por favor ingresa una contraseña.',
snackPosition: SnackPosition.BOTTOM,
);
}
} }
} }
@@ -320,18 +337,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
print('e'); print('e');
} }
try {
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.update({'email': newEmail});
} catch (e) {
print('Error al actualizar la imagen de perfil $e');
}
try { try {
if (imagen_to_upload == null) { if (imagen_to_upload == null) {
return;
} else { } else {
final uploaded = await uploadImage(imagen_to_upload!); final uploaded = await uploadImage(imagen_to_upload!);
updateImage(photoTemp); updateImage(photoTemp);
@@ -341,10 +348,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
print('Error al actualizar la imagen de perfil $e'); print('Error al actualizar la imagen de perfil $e');
} }
Get.snackbar( WarningSnackbar.show(
'Informacion actualizada', title: 'Informacion actualizada',
'Tu informacion ha sido actualizada con exito.', message: 'Tu informacion ha sido actualizada con exito.',
snackPosition: SnackPosition.BOTTOM, icon: const Icon(
Icons.check,
color: Colors.white,
),
backgroundColor: Colors.green,
); );
} }
@@ -401,19 +412,23 @@ class _ProfileScreenState extends State<ProfileScreen> {
_email = newEmail; _email = newEmail;
}); });
Get.snackbar( WarningSnackbar.show(
'Éxito', title: 'Actualizado exitosamente',
'Correo electrónico actualizado correctamente.', message: 'Correo electronico actualizado correctamente.',
snackPosition: SnackPosition.BOTTOM, icon: const Icon(Icons.check, color: Colors.white),
backgroundColor: Colors.green,
); );
Navigator.of(context).pop(); if (Navigator.canPop(context)) {
Navigator.of(context).pop();
}
} catch (e) { } catch (e) {
Get.snackbar( WarningSnackbar.show(
'No se pudo actualizar el correo', title: 'No se pudo actualizar el correo',
'Verifica tu contraseña actual y asegúrate de que el nuevo correo electrónico no se haya utilizado previamente.', message:
snackPosition: SnackPosition.BOTTOM, 'Verifica tu contraseña actual y asegúrate de que el nuevo correo electrónico no se haya utilizado previamente.',
); );
print('Error al actualizar el correo electrónico: $e'); print('Error al actualizar el correo electrónico: $e');
} }
} }
@@ -472,23 +487,26 @@ class _ProfileScreenState extends State<ProfileScreen> {
); );
} }
Future<void> updateEmailAndPassword(String email, String password) async { Future<bool> updateEmailAndPassword(String email, String password) async {
final User? user = FirebaseAuth.instance.currentUser; final User? user = FirebaseAuth.instance.currentUser;
if (user != null) { if (user != null) {
try { try {
await user.updateEmail(email); await user.updateEmail(email);
await user.updatePassword(password); await user.updatePassword(password);
return true;
} catch (e) { } catch (e) {
Get.snackbar( WarningSnackbar.show(
'Agregar correo', title: 'Inicia sesión de nuevo',
'Inicia sesión para asegurarnos de que seas tú.', message:
snackPosition: SnackPosition.BOTTOM, 'Para agregar un correo debes haber iniciado sesión recientemente.');
);
// AuthenticationRepository.instance.logout(uid!);
} }
} }
return false;
} }
bool enableLoginWithEmail = false;
Future<void> _showChoiceDialog(BuildContext context) async { Future<void> _showChoiceDialog(BuildContext context) async {
return showDialog( return showDialog(
context: context, context: context,
@@ -538,6 +556,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
String city = _ciudad.toString(); String city = _ciudad.toString();
final userProvider = Provider.of<UserProvider>(context);
return Scaffold( return Scaffold(
appBar: PopAppbar( appBar: PopAppbar(
onPressed: () { onPressed: () {
@@ -582,70 +602,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
prefixIcon: Icon(Icons.person_outline), prefixIcon: Icon(Icons.person_outline),
hintText: 'Nombre (Obligatorio)'), hintText: 'Nombre (Obligatorio)'),
), ),
const SizedBox(height: 0), const SizedBox(),
_email != null
? TextFormField(
onTap: () {
_showEmailUpdateDialog(context);
},
readOnly: true,
controller: _emailController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
hintText: 'Email (Obligatorio)'),
)
: TextFormField(
controller: _emailController,
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Por favor ingrese un email';
}
final RegExp emailRegExp =
RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
if (!emailRegExp.hasMatch(value)) {
return 'Por favor ingrese un email válido';
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
hintText: 'Email (Obligatorio)'),
),
const SizedBox(height: 20.0),
_email != null
? const SizedBox.shrink()
: TextFormField(
controller: _passwordController,
obscureText: _obscureText,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Porfavor ingrese una contraseña.';
}
if (value.length < 5) {
return 'Debe tener al menos 5 caracteres.';
}
return null;
},
decoration: InputDecoration(
prefixIcon: const Icon(Icons.lock_outline),
suffixIcon: IconButton(
icon: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
color: Colors.grey,
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
),
hintText: 'Contraseña (Obligatorio)'),
),
_email != null
? const SizedBox.shrink()
: const SizedBox(height: 20.0),
TextFormField( TextFormField(
readOnly: true, readOnly: true,
onTap: () async { onTap: () async {
@@ -719,6 +676,111 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
) )
: const SizedBox(), : const SizedBox(),
_email != null
? TextFormField(
onTap: () {
_showEmailUpdateDialog(context);
},
readOnly: true,
controller: _emailController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
hintText: 'Email (Obligatorio)'),
)
: const SizedBox(),
const SizedBox(height: 20),
_email == null
? PrimaryCheckbox(
text:
'Habilitar inicio de sesión con correo (Opcional)',
initialValue: enableLoginWithEmail,
onChanged: (value) {
setState(() {
enableLoginWithEmail = value;
});
},
)
: const SizedBox(),
const SizedBox(height: 15),
enableLoginWithEmail
? Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 0.5,
),
borderRadius: BorderRadius.circular(10),
),
padding: const EdgeInsets.all(10),
child: Column(
children: [
TextFormField(
controller: _emailController,
validator: (String? value) {
if (enableLoginWithEmail) {
if (value == null || value.isEmpty) {
return 'Por favor ingrese un email';
}
final RegExp emailRegExp = RegExp(
r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
if (!emailRegExp.hasMatch(value)) {
return 'Por favor ingrese un email válido';
}
return null;
} else {
return null;
}
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
hintText: 'Email'),
),
const SizedBox(height: 20.0),
_email != null
? const SizedBox.shrink()
: TextFormField(
controller: _passwordController,
obscureText: _obscureText,
validator: (value) {
if (enableLoginWithEmail) {
if (value == null ||
value.isEmpty) {
return 'Por favor ingrese una contraseña.';
}
if (value.length < 5) {
return 'Debe tener al menos 5 caracteres.';
}
return null;
} else {
return null;
}
},
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.lock_outline),
suffixIcon: IconButton(
icon: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
color: Colors.grey,
),
onPressed: () {
setState(() {
_obscureText =
!_obscureText;
});
},
),
hintText: 'Contraseña'),
),
_email != null
? const SizedBox.shrink()
: const SizedBox(height: 20),
],
),
)
: const SizedBox(),
], ],
), ),
), ),
@@ -752,6 +814,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
await updateInfo(); await updateInfo();
} }
await userProvider.updateUserDataAndScores();
}, },
text: 'Guardar', text: 'Guardar',
), ),
@@ -8,7 +8,7 @@ import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/models/setting_model.dart'; import 'package:prosappco/src/models/setting_model.dart';
import 'package:prosappco/src/models/user_model.dart'; import 'package:prosappco/src/models/user_model.dart';
import 'package:prosappco/src/presentation/screens/service.dart'; import 'package:prosappco/src/presentation/screens/map/service.dart';
class ServiceAfterScreen extends StatefulWidget { class ServiceAfterScreen extends StatefulWidget {
var eventoId; var eventoId;
@@ -30,14 +30,14 @@ import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart'; import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class ServiceScreen extends StatefulWidget { class ServiceOldScreen extends StatefulWidget {
const ServiceScreen({super.key}); const ServiceOldScreen({super.key});
@override @override
State<ServiceScreen> createState() => _ServiceScreenState(); State<ServiceOldScreen> createState() => _ServiceOldScreenState();
} }
class _ServiceScreenState extends State<ServiceScreen> { class _ServiceOldScreenState extends State<ServiceOldScreen> {
late String appVersion; late String appVersion;
final Uri _url = Uri.parse( final Uri _url = Uri.parse(
'https://play.google.com/store/apps/details?id=com.prosapp.prosapp'); 'https://play.google.com/store/apps/details?id=com.prosapp.prosapp');
@@ -57,27 +57,6 @@ class _ServiceScreenState extends State<ServiceScreen> {
} }
} }
// Future<List<LatLng>> getRouteCoordinates(
// double startLat, double startLng, double endLat, double endLng) async {
// List<LatLng> polylineCoordinates = [];
// PolylinePoints polylinePoints = PolylinePoints();
// PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
// 'AIzaSyCW_og6qQ8W8G-5_BxIS4sBnl8cLkjL95s',
// PointLatLng(startLat, startLng),
// PointLatLng(endLat, endLng),
// );
// if (result.points.isNotEmpty) {
// result.points.forEach((PointLatLng point) {
// polylineCoordinates.add(LatLng(point.latitude, point.longitude));
// });
// }
// return polylineCoordinates;
// }
Future<void> sendPushNotification(String pro) async { Future<void> sendPushNotification(String pro) async {
try { try {
http.Response response = await http.post( http.Response response = await http.post(
@@ -1217,9 +1196,10 @@ class _ServiceScreenState extends State<ServiceScreen> {
const SizedBox(height: 15), const SizedBox(height: 15),
TextFormField( TextFormField(
controller: _observacionController, controller: _observacionController,
decoration: const InputDecoration( decoration: InputDecoration(
prefixIcon: Icon(Icons.message_outlined), prefixIcon: Icon(Icons.message_outlined),
hintText: 'Observaciones'), hintText:
'Observaciones ${user?.name} - ${user?.phoneNumber}'),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
PrimaryButton( PrimaryButton(
@@ -6,6 +6,7 @@ import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/models/user_model.dart'; import 'package:prosappco/src/models/user_model.dart';
import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart';
import 'package:prosappco/src/providers/user_provider.dart'; import 'package:prosappco/src/providers/user_provider.dart';
import 'package:prosappco/src/presentation/screens/configuracion.dart'; import 'package:prosappco/src/presentation/screens/configuracion.dart';
import 'package:prosappco/src/presentation/screens/messages_user.dart'; import 'package:prosappco/src/presentation/screens/messages_user.dart';
@@ -322,10 +323,10 @@ class DrawerMenu extends StatelessWidget {
user?.city == '' || user?.city == '' ||
user?.phoneNumber == '' || user?.phoneNumber == '' ||
user?.phoneNumber == null) { user?.phoneNumber == null) {
Get.snackbar( WarningSnackbar.show(
'Completa tu perfil', title: 'Completa tu perfil',
'Para ser un profesional registrado, asegúrate de llenar todos los campos necesarios y no olvides guardar tus cambios para que surtan efecto.', message:
snackPosition: SnackPosition.BOTTOM, 'Para ser un profesional registrado, asegúrate de llenar todos los campos necesarios y no olvides guardar tus cambios para que surtan efecto.',
); );
} else { } else {
if (user?.phoneNumber != user?.phoneNumber) { if (user?.phoneNumber != user?.phoneNumber) {
+14
View File
@@ -35,6 +35,20 @@ class UserProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> updateUserDataAndScores() async {
var uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
var documentSnapshot = await _firestore.collection('users').doc(uid).get();
if (documentSnapshot.exists) {
final data = documentSnapshot.data() as Map<String, dynamic>;
_user = UserModel.fromFirestore(data);
_score = await ScoresModel.scoreTo(uid, false, false);
notifyListeners();
}
}
UserModel? get user => _user; UserModel? get user => _user;
ScoresModel? get score => _score; ScoresModel? get score => _score;
} }
@@ -13,6 +13,7 @@ import firebase_messaging
import firebase_storage import firebase_storage
import flutter_local_notifications import flutter_local_notifications
import geolocator_apple import geolocator_apple
import location
import package_info_plus import package_info_plus
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
@@ -26,6 +27,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin")) FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
+24
View File
@@ -773,6 +773,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
location:
dependency: "direct main"
description:
name: location
sha256: "06be54f682c9073cbfec3899eb9bc8ed90faa0e17735c9d9fa7fe426f5be1dd1"
url: "https://pub.dev"
source: hosted
version: "5.0.3"
location_platform_interface:
dependency: transitive
description:
name: location_platform_interface
sha256: "8aa1d34eeecc979d7c9fe372931d84f6d2ebbd52226a54fe1620de6fdc0753b1"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
location_web:
dependency: transitive
description:
name: location_web
sha256: ec484c66e8a4ff1ee5d044c203f4b6b71e3a0556a97b739a5bc9616de672412b
url: "https://pub.dev"
source: hosted
version: "4.2.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
+3 -2
View File
@@ -35,6 +35,9 @@ dependencies:
sdk: flutter sdk: flutter
shared_preferences: ^2.0.10 shared_preferences: ^2.0.10
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
location: ^5.0.3
flutter_polyline_points: ^2.0.0
google_maps_flutter: ^2.5.0
firebase_auth: ^4.6.2 firebase_auth: ^4.6.2
firebase_core: ^2.13.1 firebase_core: ^2.13.1
file_picker: ^5.3.2 file_picker: ^5.3.2
@@ -51,8 +54,6 @@ dependencies:
flutter_animate: flutter_animate:
flutter_rating_bar: flutter_rating_bar:
table_calendar: table_calendar:
google_maps_flutter: ^2.5.0
flutter_polyline_points: ^2.0.0
http: ^1.1.0 http: ^1.1.0
geolocator: ^9.0.2 geolocator: ^9.0.2
geocoding: ^2.1.0 geocoding: ^2.1.0