From 33d7da756fcb1e3b582096d74142dffb9a2497db Mon Sep 17 00:00:00 2001 From: Juan Felipe Duarte <70235683+DuarteJFelipe@users.noreply.github.com> Date: Mon, 10 Apr 2023 15:31:16 -0500 Subject: [PATCH] professional profile --- lib/main.dart | 6 +- .../authentication_repository.dart | 13 + lib/src/components/professional_photo.dart | 74 ++ lib/src/controllers/info_ professional.dart | 10 + lib/src/screens/profession.dart | 159 ++++ lib/src/screens/professional_profile.dart | 699 +++++++++++++++++- lib/src/screens/professional_revision.dart | 1 + lib/src/screens/profile.dart | 18 +- lib/src/screens/request_sent.dart | 69 ++ lib/src/services/select_image_profile.dart | 11 +- 10 files changed, 1030 insertions(+), 30 deletions(-) create mode 100644 lib/src/components/professional_photo.dart create mode 100644 lib/src/controllers/info_ professional.dart create mode 100644 lib/src/screens/profession.dart create mode 100644 lib/src/screens/request_sent.dart diff --git a/lib/main.dart b/lib/main.dart index 151c5dc..9ffa008 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,10 +6,12 @@ import 'package:prosappco/src/screens/login.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:prosappco/src/screens/login_email.dart'; import 'package:prosappco/src/screens/new_number.dart'; +import 'package:prosappco/src/screens/profession.dart'; import 'package:prosappco/src/screens/professional_profile.dart'; import 'package:prosappco/src/screens/professional_revision.dart'; import 'package:prosappco/src/screens/profile.dart'; import 'package:prosappco/src/screens/register.dart'; +import 'package:prosappco/src/screens/request_sent.dart'; import 'package:prosappco/src/screens/welcome.dart'; import 'firebase_options.dart'; @@ -38,9 +40,11 @@ class MyApp extends StatelessWidget { '/profile': (context) => ProfileScreen(), '/register': (context) => RegisterScreen(), '/city': (context) => CityScreen(), + '/profession': (context) => ProfessionScreen(), '/newNumber': (context) => NewNumberScreen(), '/profesionalRevision': (context) => ProfessionalRevisionScreen(), - '/profesionalProfile': (context) => ProfessionalProfileScreen() + '/profesionalProfile': (context) => ProfessionalProfileScreen(), + '/solicitudEnviada': (context) => RequestSentScreen() }, onGenerateRoute: (settings) { throw Exception('Ruta desconocida: ${settings.name}'); diff --git a/lib/src/authentication/authentication_repository.dart b/lib/src/authentication/authentication_repository.dart index d289580..fe2d7fd 100644 --- a/lib/src/authentication/authentication_repository.dart +++ b/lib/src/authentication/authentication_repository.dart @@ -159,6 +159,19 @@ class AuthenticationRepository extends GetxController { return photo; } + Future getProfession(String uid) async { + String profession = ''; + try { + final snapshot = + await FirebaseFirestore.instance.collection('users').doc(uid).get(); + final Map? data = snapshot.data(); + profession = data?['profesion'] ?? ''; + } catch (e) { + print('Error getting profesion: $e'); + } + return profession; + } + Future getState(String uid) async { String state = ''; try { diff --git a/lib/src/components/professional_photo.dart b/lib/src/components/professional_photo.dart new file mode 100644 index 0000000..0650689 --- /dev/null +++ b/lib/src/components/professional_photo.dart @@ -0,0 +1,74 @@ +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:flutter/material.dart'; + +const double photoSize = 100; + +class ProfessionalPhoto extends StatelessWidget { + Reference? ref; + double size; + ProfessionalPhoto({super.key, required this.ref, this.size = photoSize}); + + Future downloadImage() async { + try { + if (ref != null) { + final imageData = await ref!.getData(); + if (imageData != null) { + return ClipOval( + child: Image.memory( + imageData, + width: size, + height: size, + fit: BoxFit.cover, + ), + ); + } + } + // ignore: empty_catches + } catch (e) {} + + return const DefaultProfessionalPhoto(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: downloadImage(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // mientras la llamada asíncrona está en proceso, muestra un mensaje de carga + return const SizedBox( + width: photoSize, + height: photoSize, + child: Center( + child: CircularProgressIndicator(), + )); + } else if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + return snapshot.data!; + } else { + return const DefaultProfessionalPhoto(); + } + }); + } +} + +class DefaultProfessionalPhoto extends StatelessWidget { + const DefaultProfessionalPhoto({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + width: photoSize, + height: photoSize, + decoration: BoxDecoration( + color: const Color(0xFF2BA4EC), + borderRadius: BorderRadius.circular(50), + ), + child: const Icon( + Icons.person, + color: Color.fromARGB(255, 255, 255, 255), + size: 55, + ), + ); + } +} diff --git a/lib/src/controllers/info_ professional.dart b/lib/src/controllers/info_ professional.dart new file mode 100644 index 0000000..db957c7 --- /dev/null +++ b/lib/src/controllers/info_ professional.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class InforProfessionalController extends GetxController { + static InforProfessionalController get instance => Get.find(); + + final cedula = TextEditingController(); + final profesion = TextEditingController(); + final especializacion = TextEditingController(); +} diff --git a/lib/src/screens/profession.dart b/lib/src/screens/profession.dart new file mode 100644 index 0000000..a06bf16 --- /dev/null +++ b/lib/src/screens/profession.dart @@ -0,0 +1,159 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:diacritic/diacritic.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:prosappco/src/authentication/authentication_repository.dart'; + +final CollectionReference professionsCollection = + FirebaseFirestore.instance.collection('professions'); + +Future> getProfessions() async { + try { + DocumentSnapshot profession = + await professionsCollection.doc('professions').get(); + + Map data = profession.data() as Map; + + var professionsList = (data['professions'] as List) + .map((e) => e.toString()) + .toList(); + + return professionsList; + } catch (e) { + print('xd $e'); + } + + return []; +} + +class ProfessionScreen extends StatefulWidget { + const ProfessionScreen({super.key}); + + @override + State createState() => _ProfessionScreenState(); +} + +class _ProfessionScreenState extends State { + List? filteredProfessions; + TextEditingController searchController = TextEditingController(); + final User? user = FirebaseAuth.instance.currentUser; + List? _professions; + final uid = AuthenticationRepository.instance.getCurrentUserUid(); + + @override + void initState() { + super.initState(); + searchController.addListener(() { + setState(() { + if (_professions != null) { + if (searchController.text.isEmpty) { + filteredProfessions = _professions!; + } else { + filteredProfessions = _professions! + .where((profession) => removeDiacritics(profession) + .toLowerCase() + .contains( + removeDiacritics(searchController.text.toLowerCase()))) + .toList(); + } + } + }); + }); + + if (_professions == null) { + getProfessions().then((List element) => setState(() { + _professions = element; + filteredProfessions = element; + })); + } + } + + Future updateProfession(String profession) async { + try { + await FirebaseFirestore.instance + .collection('users') + .doc(uid) + .update({'profesion': profession}); + + print('Profesion actualizada correctamente'); + } catch (e) { + try { + await FirebaseFirestore.instance + .collection('users') + .doc(uid) + .set({'profesion': profession}); + } catch (e) { + print('Error al agregar la profesion: $e'); + } + + print('Error al actualizar la profesion: $e'); + } + } + + @override + Widget build(BuildContext context) { + if (filteredProfessions == null) { + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Color(0xFF2BA4EC)), + ), + ); + } + var professions = filteredProfessions!; + + return SafeArea( + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + leading: IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () { + Navigator.pop(context); + }, + ), + iconTheme: const IconThemeData( + color: Colors.black, + ), + title: const Text( + 'Seleccione su profesión', + style: TextStyle( + color: Colors.black, + ), + )), + body: Column( + children: [ + Padding( + padding: EdgeInsets.only(left: 10, right: 10, top: 10), + child: TextField( + controller: searchController, + decoration: InputDecoration( + hintText: 'Buscar su profesión', + prefixIcon: Icon(Icons.assignment_ind_rounded), + ), + ), + ), + Expanded( + child: ListView.builder( + itemCount: professions.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + professions[index], + style: const TextStyle( + fontSize: 18.0, + color: Colors.black, + ), + ), + onTap: () { + updateProfession(professions[index]); + Navigator.pop(context, professions[index]); + }, + ); + }, + ), + ), + ], + ), + )); + } +} diff --git a/lib/src/screens/professional_profile.dart b/lib/src/screens/professional_profile.dart index efb3956..63c0663 100644 --- a/lib/src/screens/professional_profile.dart +++ b/lib/src/screens/professional_profile.dart @@ -1,4 +1,15 @@ +import 'dart:io'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +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/photo_view.dart'; +import 'package:prosappco/src/components/professional_photo.dart'; +import 'package:prosappco/src/controllers/info_%20professional.dart'; +import 'package:prosappco/src/services/select_image_profile.dart'; class ProfessionalProfileScreen extends StatefulWidget { const ProfessionalProfileScreen({super.key}); @@ -9,29 +20,681 @@ class ProfessionalProfileScreen extends StatefulWidget { } class ProfessionalProfileScreenState extends State { + File? imagen_to_upload; + File? image_cedula; + File? image_certificado; + + late final FirebaseAuth _auth; + final FirebaseStorage storage = FirebaseStorage.instance; + + final uid = AuthenticationRepository.instance.getCurrentUserUid(); + final _formKey = GlobalKey(); + + final controller = Get.put(InforProfessionalController()); + final _cedulaController = TextEditingController(); + final _especializacionController = TextEditingController(); + List images_especializacion = []; + var _profession = '...'; + var photoTemp = ''; + var _photo = '...'; + @override - Widget build(BuildContext context) { - return SafeArea( - child: Scaffold( - appBar: AppBar( - backgroundColor: Colors.white, - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () { - Navigator.pop(context); + void initState() { + super.initState(); + _auth = FirebaseAuth.instance; + if (_photo == '...') { + AuthenticationRepository.instance + .getPhoto(uid.toString()) + .then((String s) => setState(() { + _photo = s; + })); + } + + if (_profession == '...') { + AuthenticationRepository.instance + .getProfession(uid.toString()) + .then((String s) => setState(() { + _profession = s; + })); + } + } + + Future _showChoiceDialog(BuildContext context) async { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SingleChildScrollView( + child: ListBody( + children: [ + GestureDetector( + child: Text( + textAlign: TextAlign.center, + "Tomar foto", + style: TextStyle(color: Color(0xFF2BA4EC)), + ), + onTap: () async { + final imagen = await getImage(1); + setState(() { + imagen_to_upload = File(imagen[0]!.path); + }); }, ), - iconTheme: IconThemeData( - color: Colors.black, + Divider(color: Colors.black54), + GestureDetector( + child: Text( + textAlign: TextAlign.center, + "Abrir Galería", + style: TextStyle(color: Color(0xFF2BA4EC)), + ), + onTap: () async { + final imagen = await getImage(2); + setState(() { + imagen_to_upload = File(imagen[0]!.path); + }); + }, ), - title: Text( - 'Perfil profesional', - style: TextStyle( - color: Colors.black, + ], + ), + ), + ); + }, + ); + } + + Future _showChoiceDialogCedula(BuildContext context) async { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SingleChildScrollView( + child: ListBody( + children: [ + GestureDetector( + child: Text( + textAlign: TextAlign.center, + "Tomar foto", + style: TextStyle(color: Color(0xFF2BA4EC)), + ), + onTap: () async { + final imagen = await getImage(1); + setState(() { + image_cedula = File(imagen[0]!.path); + }); + }, + ), + Divider(color: Colors.black54), + GestureDetector( + child: Text( + textAlign: TextAlign.center, + "Abrir Galería", + style: TextStyle(color: Color(0xFF2BA4EC)), + ), + onTap: () async { + final imagen = await getImage(2); + setState(() { + image_cedula = File(imagen[0]!.path); + }); + }, + ), + ], + ), + ), + ); + }, + ); + } + + Future _showChoiceDialogCertificado(BuildContext context) async { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: SingleChildScrollView( + child: ListBody( + children: [ + GestureDetector( + child: Text( + textAlign: TextAlign.center, + "Tomar foto", + style: TextStyle(color: Color(0xFF2BA4EC)), + ), + onTap: () async { + final imagen = await getImage(1); + setState(() { + image_certificado = File(imagen[0]!.path); + }); + }, + ), + Divider(color: Colors.black54), + GestureDetector( + child: Text( + textAlign: TextAlign.center, + "Abrir Galería", + style: TextStyle(color: Color(0xFF2BA4EC)), + ), + onTap: () async { + final imagen = await getImage(2); + setState(() { + image_certificado = File(imagen[0]!.path); + }); + }, + ), + ], + ), + ), + ); + }, + ); + } + + Future uploadCedula(File image) async { + final String namefile = image.path.split('/').last; + + Reference ref = storage + .ref() + .child('users') + .child(uid!) + .child('cedula') + .child(namefile); + + final UploadTask uploadTask = ref.putFile(image); + + final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); + + photoTemp = ref.fullPath; + + if (snapshot.state == TaskState.success) { + return true; + } else { + return false; + } + } + + Future> uploadEspecializaciones(List images) async { + List photoPaths = []; + + for (File image in images) { + final String namefile = image.path.split('/').last; + + Reference ref = storage + .ref() + .child('users') + .child(uid!) + .child('especializaciones') + .child(namefile); + + final UploadTask uploadTask = ref.putFile(image); + + final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); + + photoPaths.add(ref.fullPath); + + if (snapshot.state != TaskState.success) { + return []; + } + } + + return photoPaths; + } + + Future uploadCertificado(File image) async { + final String namefile = image.path.split('/').last; + + Reference ref = storage + .ref() + .child('users') + .child(uid!) + .child('certificado_profesional') + .child(namefile); + + final UploadTask uploadTask = ref.putFile(image); + + final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); + + photoTemp = ref.fullPath; + + if (snapshot.state == TaskState.success) { + return true; + } else { + return false; + } + } + + Future updateImage(image) async { + try { + await FirebaseFirestore.instance + .collection('users') + .doc(uid) + .update({'photo': image}); + + print('imagen actualizada correctamente'); + } catch (e) { + try { + await FirebaseFirestore.instance + .collection('users') + .doc(uid) + .set({'photo': image}); + } catch (e) { + print('Error al agregar la imagen de perfil: $e'); + } + + print('Error al actualizar la imagen de perfil: $e'); + } + } + + Future uploadImage(File image) async { + final String namefile = image.path.split('/').last; + + Reference ref = storage + .ref() + .child('users') + .child(uid!) + .child('profile') + .child(namefile); + + final UploadTask uploadTask = ref.putFile(image); + + final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); + + photoTemp = ref.fullPath; + + if (snapshot.state == TaskState.success) { + return true; + } else { + return false; + } + } + + 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(); + + 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 { + 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'); + } + + uploadEspecializaciones(images_especializacion); + uploadCedula(image_cedula!); + uploadCertificado(image_certificado!); + } + + Future downloadImage(Reference ref) async { + try { + if (_photo == '...' || _photo.isEmpty) { + return GestureDetector( + onTap: () { + _showChoiceDialog(context); + }, + child: Container( + margin: EdgeInsets.symmetric(vertical: 50), + width: 100, + height: 100, + decoration: BoxDecoration( + color: Color(0xFF2BA4EC), + borderRadius: BorderRadius.circular(50), + ), + child: Icon( + Icons.person, + color: Colors.white, + size: 90, + ), + ), + ); + } else { + final imageData = await ref.getData(); + if (imageData != null) { + // final widgetImage = Image.memory(imageData); + final widgetImage = GestureDetector( + onTap: () { + _showChoiceDialog(context); + }, + child: Container( + margin: EdgeInsets.symmetric(vertical: 50), + child: ClipOval( + child: Image.memory( + imageData, + width: 60, + height: 60, + fit: BoxFit.cover, + ), + ), + ), + ); + return widgetImage; + } else { + return GestureDetector( + onTap: () { + _showChoiceDialog(context); + }, + child: Container( + margin: EdgeInsets.symmetric(vertical: 50), + width: 100, + height: 100, + decoration: BoxDecoration( + color: Color(0xFF2BA4EC), + borderRadius: BorderRadius.circular(50), + ), + child: Icon( + Icons.person, + color: Colors.white, + size: 90, + ), + ), + ); + } + } + } catch (e) { + print('$e'); + return GestureDetector( + onTap: () { + _showChoiceDialog(context); + }, + child: Container( + margin: EdgeInsets.symmetric(vertical: 50), + width: 100, + height: 100, + decoration: BoxDecoration( + color: Color(0xFF2BA4EC), + borderRadius: BorderRadius.circular(50), + ), + child: Icon( + Icons.person, + color: Colors.white, + size: 90, + ), + ), + ); + } + } + + @override + Widget build(BuildContext context) { + final User? user = FirebaseAuth.instance.currentUser; + + String profession = _profession.toString(); + + double _space = 10; + return SafeArea( + child: Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + backgroundColor: Colors.white, + leading: IconButton( + icon: Icon(Icons.arrow_back), + onPressed: () { + Navigator.pop(context); + }, + ), + iconTheme: IconThemeData( + color: Colors.black, + ), + title: Text( + 'Perfil profesional', + style: TextStyle( + color: Colors.black, + ), + )), + body: Center( + child: Column( + children: [ + GestureDetector( + onTap: () { + _showChoiceDialog(context); + }, + child: Container( + margin: const EdgeInsets.symmetric(vertical: 25), + child: (imagen_to_upload != null) + ? LocalPhoto( + file: imagen_to_upload!, + ) + : ReferencePhoto( + ref: storage.ref().child(_photo), + size: 100, + ), + ), + ), + Container( + width: 300, + padding: const EdgeInsets.only(top: 0), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + controller: _cedulaController, + decoration: InputDecoration( + prefixIcon: Icon(Icons.person_outline), + hintText: 'Cedula (Obligatorio)'), + ), + SizedBox(height: _space), + ElevatedButton( + onPressed: () { + _showChoiceDialogCedula(context); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Cedula', + style: TextStyle( + color: Color(0xFF2BA4EC), + fontSize: 17, + ), + ), + SizedBox(width: 15), + Icon( + image_cedula != null + ? Icons.check + : Icons.file_upload_outlined, + color: Color(0xFF2BA4EC), + size: 30, + ), + ], + ), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFFD6F4FF), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: Size(250, 50), + ), + ), + SizedBox(height: _space), + TextFormField( + readOnly: true, + onTap: () async { + final String? profesion = (await Navigator.pushNamed( + context, '/profession')) as String?; + + if (profesion != null) { + setState(() { + _profession = profesion as String; + }); + } + }, + decoration: InputDecoration( + prefixIcon: Icon(Icons.assignment_ind_rounded), + suffixIcon: Icon(Icons.arrow_drop_down), + hintStyle: profession == '' + ? TextStyle() + : TextStyle(color: Colors.black87), + hintText: profession == '' + ? 'Profesión (Obligatorio)' + : '$profession'), + ), + SizedBox(height: _space), + ElevatedButton( + onPressed: () { + _showChoiceDialogCertificado(context); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Certificado profesional', + style: TextStyle( + color: Color(0xFF2BA4EC), + fontSize: 17, + ), + ), + SizedBox(width: 15), + Icon( + image_certificado != null + ? Icons.check + : Icons.file_upload_outlined, + color: Color(0xFF2BA4EC), + size: 30, + ), + ], + ), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFFD6F4FF), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: Size(250, 50), + ), + ), + SizedBox(height: _space), + TextFormField( + controller: _especializacionController, + decoration: InputDecoration( + prefixIcon: Icon(Icons.assignment_ind_rounded), + hintText: 'Especialización'), + ), + SizedBox(height: _space), + ElevatedButton( + onPressed: () async { + final images = await getImage(3); + setState(() { + images_especializacion = + images.map((e) => File(e!.path)).toList(); + }); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Especialización', + style: TextStyle( + color: Color(0xFF2BA4EC), + fontSize: 17, + ), + ), + SizedBox(width: 15), + Icon( + images_especializacion.isEmpty + ? Icons.file_upload_outlined + : Icons.check, + color: Color(0xFF2BA4EC), + size: 30, + ), + ], + ), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFFD6F4FF), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: Size(250, 50), + ), + ), + ], + )), + ), + Container( + alignment: Alignment.bottomCenter, + margin: EdgeInsets.only(top: 120, right: 70, left: 70), + child: ElevatedButton( + onPressed: () { + sendInfo(); + Navigator.pushReplacementNamed( + context, '/solicitudEnviada'); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Enviar información', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 17, + ), + ), + SizedBox(width: 15), + Icon( + Icons.send, + color: Colors.white, + size: 20, + ), + ], + ), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF2BA4EC), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: Size(250, 50), ), )), - body: Container( - child: Text('data'), - ))); + ], + ), + ), + )); } } diff --git a/lib/src/screens/professional_revision.dart b/lib/src/screens/professional_revision.dart index 7886822..de71eb1 100644 --- a/lib/src/screens/professional_revision.dart +++ b/lib/src/screens/professional_revision.dart @@ -32,6 +32,7 @@ class _ProfessionalRevisionScreenState ), )), body: Container( + color: Colors.white, child: Padding( padding: const EdgeInsets.only(top: 40), child: Column( diff --git a/lib/src/screens/profile.dart b/lib/src/screens/profile.dart index 502cddb..9bc222e 100644 --- a/lib/src/screens/profile.dart +++ b/lib/src/screens/profile.dart @@ -20,8 +20,6 @@ class ProfileScreen extends StatefulWidget { class _ProfileScreenState extends State { File? imagen_to_upload; - bool _mostrarMenuDesplegable = true; - final uid = AuthenticationRepository.instance.getCurrentUserUid(); final _formKey = GlobalKey(); final controller = Get.put(NameEmailCityController()); @@ -38,8 +36,8 @@ class _ProfileScreenState extends State { @override void initState() { super.initState(); + final uid = AuthenticationRepository.instance.getCurrentUserUid(); _auth = FirebaseAuth.instance; - final Reference ref = storage.ref().child(_photo); final currentUser = _auth.currentUser; @@ -103,7 +101,12 @@ class _ProfileScreenState extends State { Future uploadImage(File image) async { final String namefile = image.path.split('/').last; - Reference ref = storage.ref().child('profile').child(namefile); + Reference ref = storage + .ref() + .child('users') + .child(uid!) + .child('profile') + .child(namefile); final UploadTask uploadTask = ref.putFile(image); @@ -242,7 +245,7 @@ class _ProfileScreenState extends State { if (currentUser?.email != newEmail) { AuthCredential credential = - EmailAuthProvider.credential(email: newEmail, password: '654321'); + EmailAuthProvider.credential(email: newEmail, password: ''); try { await FirebaseAuth.instance.currentUser!.updateEmail(newEmail); await FirebaseFirestore.instance.collection('users').doc(uid).update({ @@ -274,6 +277,7 @@ class _ProfileScreenState extends State { } else { final uploaded = await uploadImage(imagen_to_upload!); updateImage(photoTemp); + //image } } catch (e) { print('Error al actualizar la imagen de perfil $e'); @@ -297,7 +301,7 @@ class _ProfileScreenState extends State { onTap: () async { final imagen = await getImage(1); setState(() { - imagen_to_upload = File(imagen!.path); + imagen_to_upload = File(imagen[0]!.path); }); }, ), @@ -311,7 +315,7 @@ class _ProfileScreenState extends State { onTap: () async { final imagen = await getImage(2); setState(() { - imagen_to_upload = File(imagen!.path); + imagen_to_upload = File(imagen[0]!.path); }); }, ), diff --git a/lib/src/screens/request_sent.dart b/lib/src/screens/request_sent.dart new file mode 100644 index 0000000..6825cd4 --- /dev/null +++ b/lib/src/screens/request_sent.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; + +class RequestSentScreen extends StatelessWidget { + const RequestSentScreen({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + leading: IconButton( + icon: Icon(Icons.arrow_back), + onPressed: () { + Navigator.pushReplacementNamed(context, '/welcome'); + }, + ), + iconTheme: IconThemeData( + color: Colors.black, + ), + title: Text( + 'Solicitud enviada', + style: TextStyle( + color: Colors.black, + ), + )), + body: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 90, bottom: 40), + child: Icon( + Icons.check_circle_outline, + size: 50, + color: Color(0xFF35A8ED), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 350), + child: Text('Información enviada con éxito.', + style: + TextStyle(color: Color(0xFF2BA4EC), fontSize: 20)), + ), + ElevatedButton( + onPressed: () { + Navigator.pushReplacementNamed(context, '/welcome'); + }, + child: Text( + 'Inicio', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF2BA4EC), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: Size(200, 60), + ), + ) + ], + ), + ))); + } +} diff --git a/lib/src/services/select_image_profile.dart b/lib/src/services/select_image_profile.dart index a6f1dac..a972fb6 100644 --- a/lib/src/services/select_image_profile.dart +++ b/lib/src/services/select_image_profile.dart @@ -1,13 +1,16 @@ import 'package:image_picker/image_picker.dart'; -Future getImage(opc) async { +Future> getImage(opc) async { final ImagePicker picker = ImagePicker(); if (opc == 1) { XFile? image = await picker.pickImage(source: ImageSource.camera); - return image; - } else { + return [image]; + } else if (opc == 2) { XFile? image = await picker.pickImage(source: ImageSource.gallery); - return image; + return [image]; + } else { + final List images = await picker.pickMultiImage(); + return images; } }