diff --git a/lib/src/components/drawer_menu.dart b/lib/src/components/drawer_menu.dart new file mode 100644 index 0000000..4a96b36 --- /dev/null +++ b/lib/src/components/drawer_menu.dart @@ -0,0 +1,235 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:flutter/material.dart'; +import 'package:prosappco/src/authentication/authentication_repository.dart'; +import 'package:prosappco/src/components/photo_view.dart'; + +class DrawerMenu extends StatelessWidget { + Reference? ref; + String userName; + String userPhoneNumber; + String userCity; + String userState; + + DrawerMenu({ + super.key, + required this.ref, + required this.userName, + required this.userPhoneNumber, + required this.userCity, + required this.userState, + }); + + @override + Widget build(BuildContext context) { + return Drawer( + child: ListView( + padding: EdgeInsets.zero, + children: [ + Column( + children: [ + Column( + children: [ + ListTile( + onTap: () { + if (ModalRoute.of(context)?.settings.name != '/profile') { + Navigator.pushNamed(context, '/profile'); + } else { + Scaffold.of(context).openEndDrawer(); + } + }, + title: Text(userName, + style: const TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + userPhoneNumber, + style: const TextStyle(fontSize: 12), + ), + Text( + userCity, + style: const TextStyle(fontSize: 12), + ), + ], + ), + leading: ReferencePhoto( + ref: ref, + size: 55, + sizeCircle: 60, + ), + trailing: const Icon(Icons.keyboard_arrow_right, + color: Colors.black), + contentPadding: const EdgeInsets.symmetric( + vertical: 20, horizontal: 16), + ), + ], // + ), + const Divider(height: 0, color: Colors.grey), + Column( + children: [ + ListTile( + onTap: () {}, + leading: const Icon( + Icons.history, + color: Colors.black, + ), + title: const Text( + 'Mis servicios', + style: TextStyle(fontSize: 15), + ), + ), + ListTile( + onTap: () { + if (ModalRoute.of(context)?.settings.name != '/profile') { + Navigator.pushNamed(context, '/profile'); + } else { + Scaffold.of(context).openEndDrawer(); + } + }, + leading: const Icon( + Icons.person_outline, + color: Colors.black, + ), + title: const Text( + 'Mi perfil', + style: TextStyle(fontSize: 15), + ), + ), + ListTile( + onTap: () {}, + leading: const Icon( + Icons.construction_outlined, + color: Colors.black, + ), + title: const Text( + 'Configuración', + style: TextStyle(fontSize: 15), + ), + ), + ListTile( + onTap: () {}, + leading: const Icon( + Icons.question_mark_rounded, + color: Colors.black, + ), + title: const Text( + 'Soporte', + style: TextStyle(fontSize: 15), + ), + ), + ListTile( + onTap: () {}, + leading: const Icon( + Icons.messenger_outline, + color: Colors.black, + ), + title: const Text( + 'Mensajes', + style: TextStyle(fontSize: 15), + ), + ), + Builder(builder: (BuildContext context) { + return ListTile( + onTap: () { + if (ModalRoute.of(context)?.settings.name != + '/welcome') { + Navigator.pushNamed(context, '/welcome'); + } else { + Scaffold.of(context).openEndDrawer(); + } + }, + trailing: const Icon( + Icons.keyboard_arrow_right, + color: Colors.white, + ), + title: const Text( + 'Solicitar servicio', + style: TextStyle( + color: Colors.white, + fontSize: 17, + fontWeight: FontWeight.bold), + ), + tileColor: const Color(0xFF2BA4EC), + contentPadding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 16), + ); + }), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Prosapp', + style: TextStyle(fontSize: 10, color: Colors.grey[700]), + ), + Padding( + padding: const EdgeInsets.only(top: 7, left: 3, right: 3), + child: Text( + '®', + style: TextStyle(fontSize: 25, color: Colors.grey[700]), + ), + ), + Text( + 'todos los derechos reservados', + style: TextStyle(fontSize: 10, color: Colors.grey[700]), + ), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 200), + child: Row( + children: [ + const SizedBox(width: 10), + ElevatedButton( + onPressed: () { + AuthenticationRepository.instance.logout(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + shape: const CircleBorder(), + elevation: 3, + minimumSize: const Size(45, 45), + ), + child: const Icon( + Icons.logout_outlined, + color: Colors.red, + size: 35, + ), + ), + const SizedBox(width: 5), + ElevatedButton( + onPressed: () { + if (userState == 'pendiente' || userState.isEmpty) { + Navigator.pushNamed(context, '/profesionalProfile'); + } else if (userState == 'revision') { + Navigator.pushNamed(context, '/profesionalRevision'); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF2BA4EC), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: const Size(200, 45), + ), + child: const Text( + 'Modo profesional', + style: TextStyle( + color: Colors.white, + fontSize: 15, + ), + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/src/components/photo_view.dart b/lib/src/components/photo_view.dart index 0e45fec..a9f010a 100644 --- a/lib/src/components/photo_view.dart +++ b/lib/src/components/photo_view.dart @@ -8,7 +8,12 @@ const double photoSize = 100; class ReferencePhoto extends StatelessWidget { Reference? ref; double size; - ReferencePhoto({super.key, required this.ref, this.size = photoSize}); + double sizeCircle; + ReferencePhoto( + {super.key, + required this.ref, + this.size = photoSize, + this.sizeCircle = photoSize}); Future downloadImage() async { try { @@ -28,7 +33,7 @@ class ReferencePhoto extends StatelessWidget { // ignore: empty_catches } catch (e) {} - return const DefaultPhoto(); + return DefaultPhoto(sizeDefault: sizeCircle); } @override @@ -48,20 +53,21 @@ class ReferencePhoto extends StatelessWidget { snapshot.hasData) { return snapshot.data!; } else { - return const DefaultPhoto(); + return DefaultPhoto(); } }); } } class DefaultPhoto extends StatelessWidget { - const DefaultPhoto({super.key}); + double sizeDefault; + DefaultPhoto({super.key, this.sizeDefault = photoSize}); @override Widget build(BuildContext context) { return Container( - width: photoSize, - height: photoSize, + width: sizeDefault, + height: sizeDefault, decoration: BoxDecoration( color: const Color(0xFF2BA4EC), borderRadius: BorderRadius.circular(50), diff --git a/lib/src/screens/professional_profile.dart b/lib/src/screens/professional_profile.dart index 63c0663..2af0f76 100644 --- a/lib/src/screens/professional_profile.dart +++ b/lib/src/screens/professional_profile.dart @@ -78,6 +78,7 @@ class ProfessionalProfileScreenState extends State { setState(() { imagen_to_upload = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), Divider(color: Colors.black54), @@ -92,6 +93,7 @@ class ProfessionalProfileScreenState extends State { setState(() { imagen_to_upload = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), ], @@ -121,6 +123,7 @@ class ProfessionalProfileScreenState extends State { setState(() { image_cedula = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), Divider(color: Colors.black54), @@ -135,6 +138,7 @@ class ProfessionalProfileScreenState extends State { setState(() { image_cedula = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), ], @@ -164,6 +168,7 @@ class ProfessionalProfileScreenState extends State { setState(() { image_certificado = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), Divider(color: Colors.black54), @@ -178,6 +183,7 @@ class ProfessionalProfileScreenState extends State { setState(() { image_certificado = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), ], @@ -307,65 +313,50 @@ class ProfessionalProfileScreenState extends State { } Future sendInfo() async { - final currentUser = _auth.currentUser; - - String cedula = _cedulaController.text.trim(); - - String especializacion = _especializacionController.text.trim(); - List especializaciones = - especializacion.split(',').map((element) => element.trim()).toList(); + final String cedula = _cedulaController.text.trim(); + final String especializacion = _especializacionController.text.trim(); + final List especializaciones = + especializacion.split(',').map((e) => e.trim()).toList(); if (cedula.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Ingrese una cedula válida')), - ); - return; - } else { - try { - FirebaseFirestore.instance.collection('users').doc(uid).update({ - 'cedula': cedula, - 'estado': 'revision', - }); - - print('cedula actualizado correctamente'); - } catch (e) { - print('Error al actualizar la cedula: $e'); - } - } - - if (especializacion.isNotEmpty) { - try { - FirebaseFirestore.instance - .collection('users') - .doc(uid) - .update({'especializaciones': especializaciones}); - - FirebaseFirestore.instance.collection('users').doc(uid).update({ - 'estado': 'revision', - }); - print('especializaciones agregadas correctamente'); - } catch (e) { - print('Error al cargar las especializaciones: $e'); - } - } else { + showSnackBar('Ingrese una cedula válida'); return; } - try { - if (imagen_to_upload == null) { - return; - } else { - final uploaded = await uploadImage(imagen_to_upload!); - updateImage(photoTemp); - //image - } - } catch (e) { - print('Error al actualizar la imagen de perfil $e'); + if (image_cedula == null) { + showSnackBar('Ingrese la imagen de la cedula'); + return; } - uploadEspecializaciones(images_especializacion); + if (image_certificado == null) { + showSnackBar('Ingrese la imagen de su certificado'); + return; + } + + // Actualiza los datos del usuario en Firestore + await FirebaseFirestore.instance.collection('users').doc(uid).update({ + 'cedula': cedula, + 'estado': 'revision', + 'especializaciones': especializaciones + }); + + // Sube las imágenes al storage de Firebase uploadCedula(image_cedula!); uploadCertificado(image_certificado!); + 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'); + } + + void showSnackBar(String message) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(message))); } Future downloadImage(Reference ref) async { @@ -500,6 +491,7 @@ class ProfessionalProfileScreenState extends State { : ReferencePhoto( ref: storage.ref().child(_photo), size: 100, + sizeCircle: 100, ), ), ), @@ -661,8 +653,6 @@ class ProfessionalProfileScreenState extends State { child: ElevatedButton( onPressed: () { sendInfo(); - Navigator.pushReplacementNamed( - context, '/solicitudEnviada'); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/src/screens/profile.dart b/lib/src/screens/profile.dart index 9bc222e..018cacd 100644 --- a/lib/src/screens/profile.dart +++ b/lib/src/screens/profile.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'dart:io'; import 'package:prosappco/src/authentication/authentication_repository.dart'; +import 'package:prosappco/src/components/drawer_menu.dart'; import 'package:prosappco/src/controllers/add_name_email_city.dart'; import 'package:prosappco/src/services/select_image_profile.dart'; @@ -223,6 +224,7 @@ class _ProfileScreenState extends State { ); return; } + if (newEmail.isEmpty) { // Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario ScaffoldMessenger.of(context).showSnackBar( @@ -303,6 +305,7 @@ class _ProfileScreenState extends State { setState(() { imagen_to_upload = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), Divider(color: Colors.black54), @@ -317,6 +320,7 @@ class _ProfileScreenState extends State { setState(() { imagen_to_upload = File(imagen[0]!.path); }); + Navigator.of(context).pop(); }, ), ], @@ -349,206 +353,12 @@ class _ProfileScreenState extends State { ), ), ), - drawer: Drawer( - child: ListView( - padding: EdgeInsets.zero, - children: [ - Column( - children: [ - Column( - children: [ - Builder(builder: (context) { - return ListTile( - onTap: () { - Scaffold.of(context).openEndDrawer(); - }, - title: Text(user?.displayName ?? '', - style: - const TextStyle(fontWeight: FontWeight.bold)), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - user?.phoneNumber ?? '', - style: const TextStyle(fontSize: 12), - ), - Text( - city, - style: const TextStyle(fontSize: 12), - ), - ], - ), - leading: ReferencePhoto( - ref: storage.ref().child(_photo), - size: 50, - ), - trailing: Icon(Icons.keyboard_arrow_right, - color: Colors.black), - contentPadding: EdgeInsets.symmetric( - vertical: 20, horizontal: 16), - ); - }), - ], // padding: const EdgeInsets.only(top: 20, bottom: 15), - ), - Divider(height: 0, color: Colors.grey), - Column( - children: [ - ListTile( - onTap: () {}, - leading: Icon( - Icons.history, - color: Colors.black, - ), - title: Text( - 'Mis servicios', - style: TextStyle(fontSize: 15), - ), - ), - Builder(builder: (context) { - return ListTile( - onTap: () { - Scaffold.of(context).openEndDrawer(); - }, - leading: Icon( - Icons.person_outline, - color: Colors.black, - ), - title: Text( - 'Mi perfil', - style: TextStyle(fontSize: 15), - ), - ); - }), - ListTile( - onTap: () {}, - leading: Icon( - Icons.construction_outlined, - color: Colors.black, - ), - title: Text( - 'Configuración', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () {}, - leading: Icon( - Icons.question_mark_rounded, - color: Colors.black, - ), - title: Text( - 'Soporte', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () {}, - leading: Icon( - Icons.messenger_outline, - color: Colors.black, - ), - title: Text( - 'Mensajes', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () { - Navigator.pushReplacementNamed(context, '/welcome'); - }, - trailing: Icon( - Icons.keyboard_arrow_right, - color: Colors.white, - ), - title: Text( - 'Solicitar servicio', - style: TextStyle( - color: Colors.white, - fontSize: 17, - fontWeight: FontWeight.bold), - ), - tileColor: Color(0xFF2BA4EC), - contentPadding: - EdgeInsets.symmetric(vertical: 5, horizontal: 16), - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Prosapp', - style: TextStyle(fontSize: 10, color: Colors.grey[700]), - ), - Padding( - padding: - const EdgeInsets.only(top: 7, left: 3, right: 3), - child: Text( - '®', - style: - TextStyle(fontSize: 25, color: Colors.grey[700]), - ), - ), - Text( - 'todos los derechos reservados', - style: TextStyle(fontSize: 10, color: Colors.grey[700]), - ), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 200), - child: Row( - children: [ - SizedBox(width: 10), - ElevatedButton( - onPressed: () { - AuthenticationRepository.instance.logout(); - }, - child: Icon( - Icons.logout_outlined, - color: Colors.red, - size: 35, - ), - style: ElevatedButton.styleFrom( - primary: Colors.white, - shape: CircleBorder(), - elevation: 3, - minimumSize: Size(45, 45), - ), - ), - SizedBox(width: 5), - ElevatedButton( - onPressed: () { - if (state == 'pendiente') { - Navigator.pushNamed(context, '/profesionalProfile'); - } else if (state == 'revision') { - Navigator.pushNamed(context, '/profesionalRevision'); - } - }, - child: Text( - 'Modo profesional', - style: TextStyle( - color: Colors.white, - fontSize: 15, - ), - ), - style: ElevatedButton.styleFrom( - primary: Color(0xFF2BA4EC), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(50), - ), - elevation: 0, - minimumSize: Size(200, 45), - ), - ), - ], - ), - ), - ], - ), - ), + drawer: DrawerMenu( + ref: storage.ref().child(_photo), + userName: user?.displayName ?? '', + userPhoneNumber: user?.phoneNumber ?? '', + userCity: city, + userState: state), body: Center( child: Column( children: [ @@ -562,7 +372,9 @@ class _ProfileScreenState extends State { ? LocalPhoto( file: imagen_to_upload!, ) - : ReferencePhoto(ref: storage.ref().child(_photo))), + : ReferencePhoto( + ref: storage.ref().child(_photo), + )), ), Container( width: 300, @@ -575,7 +387,7 @@ class _ProfileScreenState extends State { controller: _nameController, decoration: InputDecoration( prefixIcon: Icon(Icons.person_outline), - hintText: 'Nombre'), + hintText: 'Nombre (Obligatorio)'), ), SizedBox( height: @@ -585,7 +397,7 @@ class _ProfileScreenState extends State { controller: _emailController, decoration: InputDecoration( prefixIcon: Icon(Icons.email_outlined), - hintText: 'Email'), + hintText: 'Email (Obligatorio)'), ), SizedBox( height: diff --git a/lib/src/screens/welcome.dart b/lib/src/screens/welcome.dart index 5cbfa11..85f0e79 100644 --- a/lib/src/screens/welcome.dart +++ b/lib/src/screens/welcome.dart @@ -4,6 +4,7 @@ import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; +import 'package:prosappco/src/components/drawer_menu.dart'; import 'package:prosappco/src/controllers/add_name_email_city.dart'; import '../components/photo_view.dart'; @@ -69,201 +70,12 @@ class _WelcomeScreenState extends State { return SafeArea( child: Scaffold( - drawer: Drawer( - child: ListView( - padding: EdgeInsets.zero, - children: [ - Column( - children: [ - Column( - children: [ - ListTile( - onTap: () { - Navigator.pushNamed(context, '/profile'); - }, - title: Text(user?.displayName ?? '', - style: const TextStyle(fontWeight: FontWeight.bold)), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - user?.phoneNumber ?? '', - style: const TextStyle(fontSize: 12), - ), - Text( - city, - style: const TextStyle(fontSize: 12), - ), - ], - ), - leading: ReferencePhoto( - ref: storage.ref().child(_photo), - size: 50, - ), - trailing: const Icon(Icons.keyboard_arrow_right, - color: Colors.black), - contentPadding: const EdgeInsets.symmetric( - vertical: 20, horizontal: 16), - ), - ], // padding: const EdgeInsets.only(top: 20, bottom: 15), - ), - const Divider(height: 0, color: Colors.grey), - Column( - children: [ - ListTile( - onTap: () {}, - leading: const Icon( - Icons.history, - color: Colors.black, - ), - title: const Text( - 'Mis servicios', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () { - Navigator.pushNamed(context, '/profile'); - }, - leading: const Icon( - Icons.person_outline, - color: Colors.black, - ), - title: const Text( - 'Mi perfil', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () {}, - leading: const Icon( - Icons.construction_outlined, - color: Colors.black, - ), - title: const Text( - 'Configuración', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () {}, - leading: const Icon( - Icons.question_mark_rounded, - color: Colors.black, - ), - title: const Text( - 'Soporte', - style: TextStyle(fontSize: 15), - ), - ), - ListTile( - onTap: () {}, - leading: const Icon( - Icons.messenger_outline, - color: Colors.black, - ), - title: const Text( - 'Mensajes', - style: TextStyle(fontSize: 15), - ), - ), - Builder(builder: (BuildContext context) { - return ListTile( - onTap: () { - Scaffold.of(context).openEndDrawer(); - }, - trailing: const Icon( - Icons.keyboard_arrow_right, - color: Colors.white, - ), - title: const Text( - 'Solicitar servicio', - style: TextStyle( - color: Colors.white, - fontSize: 17, - fontWeight: FontWeight.bold), - ), - tileColor: const Color(0xFF2BA4EC), - contentPadding: const EdgeInsets.symmetric( - vertical: 5, horizontal: 16), - ); - }), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Prosapp', - style: TextStyle(fontSize: 10, color: Colors.grey[700]), - ), - Padding( - padding: const EdgeInsets.only(top: 7, left: 3, right: 3), - child: Text( - '®', - style: TextStyle(fontSize: 25, color: Colors.grey[700]), - ), - ), - Text( - 'todos los derechos reservados', - style: TextStyle(fontSize: 10, color: Colors.grey[700]), - ), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 200), - child: Row( - children: [ - const SizedBox(width: 10), - ElevatedButton( - onPressed: () { - AuthenticationRepository.instance.logout(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - shape: const CircleBorder(), - elevation: 3, - minimumSize: const Size(45, 45), - ), - child: const Icon( - Icons.logout_outlined, - color: Colors.red, - size: 35, - ), - ), - const SizedBox(width: 5), - ElevatedButton( - onPressed: () { - if (state == 'pendiente') { - Navigator.pushNamed(context, '/profesionalProfile'); - } else if (state == 'revision') { - Navigator.pushNamed(context, '/profesionalRevision'); - } - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF2BA4EC), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(50), - ), - elevation: 0, - minimumSize: const Size(200, 45), - ), - child: const Text( - 'Modo profesional', - style: TextStyle( - color: Colors.white, - fontSize: 15, - ), - ), - ), - ], - ), - ), - ], - ), - ), + drawer: DrawerMenu( + ref: storage.ref().child(_photo), + userName: user?.displayName ?? '', + userPhoneNumber: user?.phoneNumber ?? '', + userCity: city, + userState: state), resizeToAvoidBottomInset: false, backgroundColor: const Color(0xFFD6F4FF), body: Stack( @@ -340,7 +152,9 @@ class _WelcomeScreenState extends State { padding: const EdgeInsets.only(bottom: 40), child: Center( child: ElevatedButton( - onPressed: () {}, + onPressed: () { + print(ModalRoute.of(context)?.settings.name); + }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder(