From 6b09ce2f3aeec718ca8ac76a2e182066a465c589 Mon Sep 17 00:00:00 2001 From: Juan Felipe Duarte <70235683+DuarteJFelipe@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:03:01 -0500 Subject: [PATCH] =?UTF-8?q?se=20a=C3=B1adio=20un=20modelo=20y=20el=20menu?= =?UTF-8?q?=20de=20modo=20profesional?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 11 +- lib/src/components/drawer_menu.dart | 494 ++++++++++++-------- lib/src/components/drawer_professional.dart | 315 +++++++++++++ lib/src/models/score_model.dart | 11 +- lib/src/models/user_model.dart | 44 ++ lib/src/screens/professional.dart | 2 +- lib/src/screens/profile.dart | 38 +- lib/src/screens/prueba.dart | 89 ++++ lib/src/screens/service.dart | 25 +- lib/src/screens/welcome.dart | 42 +- 10 files changed, 777 insertions(+), 294 deletions(-) create mode 100644 lib/src/components/drawer_professional.dart create mode 100644 lib/src/models/user_model.dart create mode 100644 lib/src/screens/prueba.dart diff --git a/lib/main.dart b/lib/main.dart index 491b83c..7e49545 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/screens/city.dart'; @@ -9,10 +10,10 @@ import 'package:prosappco/src/screens/new_number.dart'; import 'package:prosappco/src/screens/new_password.dart'; import 'package:prosappco/src/screens/profession.dart'; import 'package:prosappco/src/screens/professional.dart'; -import 'package:prosappco/src/screens/professional_info.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/prueba.dart'; import 'package:prosappco/src/screens/register.dart'; import 'package:prosappco/src/screens/request_sent.dart'; import 'package:prosappco/src/screens/service.dart'; @@ -21,6 +22,11 @@ import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ).then((value) => Get.put(AuthenticationRepository())); @@ -41,7 +47,7 @@ class MyApp extends StatelessWidget { '/': (context) => const LoginScreen(), '/login': (context) => const LoginEmailScreen(), '/welcome': (context) => const WelcomeScreen(), - '/profile': (context) => ProfileScreen(), + '/profile': (context) => const ProfileScreen(), '/register': (context) => const RegisterScreen(), '/city': (context) => const CityScreen(), '/profession': (context) => const ProfessionScreen(), @@ -52,6 +58,7 @@ class MyApp extends StatelessWidget { '/nuevaPassword': (context) => NewPasswordScreen(), '/servicio': (context) => const ServiceScreen(), '/profesional': (context) => const ProfessionalScreen(), + '/prueba': (context) => const PruebaScreen(), }, onGenerateRoute: (settings) { throw Exception('Ruta desconocida: ${settings.name}'); diff --git a/lib/src/components/drawer_menu.dart b/lib/src/components/drawer_menu.dart index 4a96b36..8024335 100644 --- a/lib/src/components/drawer_menu.dart +++ b/lib/src/components/drawer_menu.dart @@ -1,233 +1,319 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_storage/firebase_storage.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/components/photo_view.dart'; +import 'package:prosappco/src/models/user_model.dart'; +import 'package:prosappco/src/screens/profile.dart'; -class DrawerMenu extends StatelessWidget { - Reference? ref; - String userName; - String userPhoneNumber; - String userCity; - String userState; +class DrawerMenu extends StatefulWidget { + @override + State createState() => _DrawerMenuState(); +} - DrawerMenu({ - super.key, - required this.ref, - required this.userName, - required this.userPhoneNumber, - required this.userCity, - required this.userState, - }); +class _DrawerMenuState extends State { + final uid = AuthenticationRepository.instance.getCurrentUserUid(); + UserModel? user; + + @override + void initState() { + super.initState(); + + if (user == null) { + UserModel.getUser(uid.toString()).then( + (UserModel s) => setState(() => user = s), + ); + } + } @override Widget build(BuildContext context) { + final User? currentUser = FirebaseAuth.instance.currentUser; + return Drawer( - child: ListView( - padding: EdgeInsets.zero, + child: Column( 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( + Container( + color: Colors.white, + child: Column( children: [ - const SizedBox(width: 10), - ElevatedButton( - onPressed: () { - AuthenticationRepository.instance.logout(); + ListTile( + onTap: () { + Navigator.push( + context, + CupertinoPageRoute( + builder: (BuildContext context) { + return const ProfileScreen(); + }, + ), + ); + // if (ModalRoute.of(context)?.settings.name != '/profile') { + // Navigator.pushNamed(context, '/profile'); + // } else { + // Scaffold.of(context).openEndDrawer(); + // } }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - shape: const CircleBorder(), - elevation: 3, - minimumSize: const Size(45, 45), + title: Text(user?.name ?? '', + style: const TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + currentUser?.phoneNumber ?? '', + style: const TextStyle(fontSize: 12), + ), + Text( + user?.city ?? '', + style: const TextStyle(fontSize: 12), + ), + ], ), - child: const Icon( - Icons.logout_outlined, - color: Colors.red, - size: 35, + leading: ReferencePhoto( + ref: user?.photo, + size: 55, + sizeCircle: 60, + ), + trailing: const Icon(Icons.keyboard_arrow_right, + color: Colors.black), + contentPadding: + const EdgeInsets.symmetric(vertical: 20, horizontal: 16), + ), + ], // + ), + ), + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 1, + blurRadius: 3, + offset: const Offset(0, 0), // changes position of shadow + ), + ], + ), + child: Divider( + height: 0, + color: Colors.grey[300], + ), + ), + Expanded( + child: Column( + children: [ + ListTile( + onTap: () {}, + leading: const Icon( + Icons.history, + color: Colors.black, + ), + title: const Text( + 'Mis servicios', + style: TextStyle(fontSize: 15), ), ), - const SizedBox(width: 5), - ElevatedButton( - onPressed: () { - if (userState == 'pendiente' || userState.isEmpty) { - Navigator.pushNamed(context, '/profesionalProfile'); - } else if (userState == 'revision') { - Navigator.pushNamed(context, '/profesionalRevision'); - } + ListTile( + onTap: () { + Navigator.push( + context, + CupertinoPageRoute( + builder: (BuildContext context) { + return const ProfileScreen(); + }, + ), + ); }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF2BA4EC), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(50), - ), - elevation: 0, - minimumSize: const Size(200, 45), + leading: const Icon( + Icons.person_outline, + color: Colors.black, ), - child: const Text( - 'Modo profesional', - style: TextStyle( + 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, - fontSize: 15, + ), + 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), + ); + }), + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 3, + offset: + const Offset(0, 2), // changes position of shadow + ), + ], + ), + child: Container( + color: const Color(0xFFD6F4FF), + child: ListTile( + tileColor: const Color(0xFFD6F4FF), + onTap: () {}, + trailing: const Icon(Icons.keyboard_arrow_right, + color: Colors.black), + title: const Text( + 'Reputación', + style: TextStyle(color: Colors.black), + ), + subtitle: Row( + children: [ + RatingBar.builder( + initialRating: user?.score?.average ?? 0, + minRating: 1, + direction: Axis.horizontal, + allowHalfRating: true, + itemCount: 5, + itemSize: 25, + maxRating: 5, + itemPadding: + const EdgeInsets.symmetric(horizontal: 0), + itemBuilder: (context, _) => const Icon( + Icons.star, + color: Color(0xFF2BA4EC), + ), + onRatingUpdate: (rating) {}, + ignoreGestures: true, + ), + const SizedBox(width: 5), + Text( + '(${user?.score?.total.toString()}) ${user?.score?.average.toString()}'), + ], + ), ), ), ), + 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]), + ), + ], + ), ], ), ), + 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 (user?.state == 'pendiente' || + user?.state?.isEmpty == true) { + Navigator.pushNamed(context, '/profesionalProfile'); + } else if (user?.state == 'revision') { + Navigator.pushNamed(context, '/profesionalRevision'); + } else if (user?.state == 'activo') { + Navigator.pushNamed(context, '/prueba'); + } + }, + 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, + ), + ), + ), + ], + ), + const SizedBox(height: 10), ], ), ); diff --git a/lib/src/components/drawer_professional.dart b/lib/src/components/drawer_professional.dart new file mode 100644 index 0000000..b7546b2 --- /dev/null +++ b/lib/src/components/drawer_professional.dart @@ -0,0 +1,315 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_rating_bar/flutter_rating_bar.dart'; +import 'package:prosappco/src/authentication/authentication_repository.dart'; +import 'package:prosappco/src/components/photo_view.dart'; +import 'package:prosappco/src/models/user_model.dart'; + +class DrawerProfessional extends StatefulWidget { + Reference? ref; + String userName; + String userPhoneNumber; + String userCity; + String userState; + + DrawerProfessional({ + super.key, + required this.ref, + required this.userName, + required this.userPhoneNumber, + required this.userCity, + required this.userState, + }); + + @override + State createState() => _DrawerProfessionalState(); +} + +class _DrawerProfessionalState extends State { + final uid = AuthenticationRepository.instance.getCurrentUserUid(); + UserModel? user; + + @override + void initState() { + super.initState(); + + if (user == null) { + UserModel.getUser(uid.toString()).then( + (UserModel s) => setState(() => user = s), + ); + } + } + + @override + Widget build(BuildContext context) { + final User? currentUser = FirebaseAuth.instance.currentUser; + + return Drawer( + child: Container( + color: const Color(0xFFE9F9FF), + child: Column( + children: [ + Container( + color: Colors.white, + child: Column( + children: [ + ListTile( + onTap: () {}, + title: Text(user?.name ?? '', + style: const TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + currentUser?.phoneNumber ?? '', + style: const TextStyle(fontSize: 12), + ), + Text( + user?.city ?? '', + style: const TextStyle(fontSize: 12), + ), + ], + ), + leading: ReferencePhoto( + ref: user?.photo, + size: 55, + sizeCircle: 60, + ), + trailing: const Icon(Icons.keyboard_arrow_right, + color: Colors.black), + contentPadding: const EdgeInsets.symmetric( + vertical: 20, horizontal: 16), + ), + ], + ), + ), + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 1, + blurRadius: 3, + offset: const Offset(0, 0), // changes position of shadow + ), + ], + ), + child: Divider( + height: 0, + color: Colors.grey[300], + ), + ), + Expanded( + child: Column( + children: [ + ListTile( + onTap: () {}, + leading: const Icon( + Icons.history, + color: Colors.black, + ), + title: const Text( + 'Mis servicios', + style: TextStyle(fontSize: 15), + ), + ), + ListTile( + onTap: () {}, + leading: const Icon( + Icons.person_outline, + color: Colors.black, + ), + title: const Text( + 'Perfil profesional', + 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), + ), + ), + ListTile( + onTap: () {}, + leading: const Icon( + Icons.calendar_month, + color: Colors.black, + ), + title: const Text( + 'Calendario', + style: TextStyle(fontSize: 15), + ), + ), + Builder(builder: (BuildContext context) { + return Container( + color: const Color(0xFF2BA4EC), + child: ListTile( + onTap: () {}, + trailing: const Icon( + Icons.keyboard_arrow_right, + color: Colors.white, + ), + title: const Text( + 'Solicitudes', + style: TextStyle( + color: Colors.white, + fontSize: 17, + fontWeight: FontWeight.bold), + ), + contentPadding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 16), + ), + ); + }), + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 3, + offset: + const Offset(0, 2), // changes position of shadow + ), + ], + ), + child: Container( + color: Colors.white, + child: ListTile( + onTap: () {}, + trailing: const Icon(Icons.keyboard_arrow_right, + color: Colors.black), + title: const Text( + 'Reputación', + style: TextStyle(color: Colors.black), + ), + subtitle: Row( + children: [ + RatingBar.builder( + initialRating: user?.score?.average ?? 0, + minRating: 1, + direction: Axis.horizontal, + allowHalfRating: true, + itemCount: 5, + itemSize: 25, + maxRating: 5, + itemPadding: + const EdgeInsets.symmetric(horizontal: 0), + itemBuilder: (context, _) => const Icon( + Icons.star, + color: Color(0xFF2BA4EC), + ), + onRatingUpdate: (rating) {}, + ignoreGestures: true, + ), + const SizedBox(width: 5), + Text( + '(${user?.score?.total.toString()}) ${user?.score?.average.toString()}'), + ], + ), + ), + ), + ), + 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]), + ), + ], + ), + ], + ), + ), + 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: () { + Navigator.pushReplacementNamed(context, '/welcome'); + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF2BA4EC), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + elevation: 0, + minimumSize: const Size(200, 45), + ), + child: const Text( + 'Modo usuario', + style: TextStyle( + color: Colors.white, + fontSize: 15, + ), + ), + ), + ], + ), + const SizedBox(height: 10), + ], + ), + ), + ); + } +} diff --git a/lib/src/models/score_model.dart b/lib/src/models/score_model.dart index ae9cae1..60dac64 100644 --- a/lib/src/models/score_model.dart +++ b/lib/src/models/score_model.dart @@ -8,13 +8,16 @@ class ScoreModel { ScoreModel(this.total, this.average, this.details); - static Future fromJson(Map? json) async { + static Future fromJson( + Map? json, bool requiredDetails) async { try { if (json == null) return ScoreModel(0, 0, []); List list = []; - for (var e in (json['detalles'] as List)) { - list.add(await ScoreDetailsModel.fromJson(e)); + if (requiredDetails) { + for (var e in (json['detalles'] as List)) { + list.add(await ScoreDetailsModel.fromJson(e)); + } } return ScoreModel( @@ -37,7 +40,7 @@ class ScoreDetailsModel { ScoreDetailsModel(this.name, this.avatar, this.score, this.comment); - static Future fromJson(Map? json) async { + static Future fromJson(Map? json) async { final FirebaseStorage storage = FirebaseStorage.instance; try { diff --git a/lib/src/models/user_model.dart b/lib/src/models/user_model.dart new file mode 100644 index 0000000..4146665 --- /dev/null +++ b/lib/src/models/user_model.dart @@ -0,0 +1,44 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:prosappco/src/models/score_model.dart'; +import 'package:prosappco/src/screens/professional.dart'; + +class UserModel { + final String name; + final String city; + final String? state; + final Reference? photo; + final ScoreModel? score; + + UserModel(this.name, this.city, this.state, this.photo, this.score); + + static Future fromJson(Map? json) async { + try { + if (json == null) return UserModel('', '', null, null, null); + + String? avatar = json['photo']; + return UserModel( + json['name'], + json['city'], + json['estado'], + avatar != null ? storage.ref().child(avatar) : null, + await ScoreModel.fromJson(json['puntuacion'], false), + ); + } catch (e) { + print('XD user $e'); + return UserModel('', '', null, null, null); + } + } + + static Future getUser(String uid) async { + try { + final snapshot = + await FirebaseFirestore.instance.collection('users').doc(uid).get(); + final Map? data = snapshot.data(); + return fromJson(data); + } catch (e) { + print('Error getting user: $e'); + return UserModel('', '', null, null, null); + } + } +} diff --git a/lib/src/screens/professional.dart b/lib/src/screens/professional.dart index 8c1b852..8d899f9 100644 --- a/lib/src/screens/professional.dart +++ b/lib/src/screens/professional.dart @@ -84,7 +84,7 @@ Future> getProfessionals() async { professionalRef: storage.ref().child(_photo), professionalEspecializado: especializaciones, ubicacion: data['ubicacion'], - puntuacion: await ScoreModel.fromJson(data['puntuacion']), + puntuacion: await ScoreModel.fromJson(data['puntuacion'], true), ); professionals.add(professional); } diff --git a/lib/src/screens/profile.dart b/lib/src/screens/profile.dart index 36b004d..89fc666 100644 --- a/lib/src/screens/profile.dart +++ b/lib/src/screens/profile.dart @@ -3,11 +3,11 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_animate/flutter_animate.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/components/pop_appbar.dart'; import 'package:prosappco/src/controllers/add_name_email_city.dart'; import 'package:prosappco/src/screens/city.dart'; import 'package:prosappco/src/screens/new_number.dart'; @@ -17,7 +17,7 @@ import 'package:prosappco/src/services/select_image_profile.dart'; import '../components/photo_view.dart'; class ProfileScreen extends StatefulWidget { - ProfileScreen({Key? key}) : super(key: key); + const ProfileScreen({Key? key}) : super(key: key); @override State createState() => _ProfileScreenState(); @@ -39,7 +39,6 @@ class _ProfileScreenState extends State { var photoTemp = ''; var _ciudad = '...'; var _photo = '...'; - var _estado = '...'; String? _email = ''; @override @@ -79,13 +78,6 @@ class _ProfileScreenState extends State { _photo = s; })); } - if (_estado == '...') { - AuthenticationRepository.instance - .getState(uid.toString()) - .then((String s) => setState(() { - _estado = s; - })); - } } Future updateImage(image) async { @@ -349,30 +341,16 @@ class _ProfileScreenState extends State { @override Widget build(BuildContext context) { - final User? user = FirebaseAuth.instance.currentUser; String city = _ciudad.toString(); - String state = _estado.toString(); return SafeArea( child: Scaffold( - appBar: AppBar( - backgroundColor: Colors.white, - iconTheme: const IconThemeData( - color: Colors.black, - ), - title: const Text( - 'Perfil', - style: TextStyle( - color: Colors.black, - ), - ), - ), - drawer: DrawerMenu( - ref: storage.ref().child(_photo), - userName: user?.displayName ?? '', - userPhoneNumber: user?.phoneNumber ?? '', - userCity: city, - userState: state), + appBar: PopAppbar( + onPressed: () { + Navigator.pop(context); + }, + label: 'Perfil'), + drawer: DrawerMenu(), body: SingleChildScrollView( reverse: true, child: Center( diff --git a/lib/src/screens/prueba.dart b/lib/src/screens/prueba.dart new file mode 100644 index 0000000..e2671dd --- /dev/null +++ b/lib/src/screens/prueba.dart @@ -0,0 +1,89 @@ +import 'dart:io'; + +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/drawer_professional.dart'; + +class PruebaScreen extends StatefulWidget { + const PruebaScreen({super.key}); + + @override + State createState() => _PruebaScreenState(); +} + +class _PruebaScreenState extends State { + File? imagen_to_upload; + + final uid = AuthenticationRepository.instance.getCurrentUserUid(); + + late final FirebaseAuth _auth; + final FirebaseStorage storage = FirebaseStorage.instance; + var photoTemp = ''; + var _ciudad = '...'; + var _photo = '...'; + var _estado = '...'; + + @override + void initState() { + super.initState(); + + final uid = AuthenticationRepository.instance.getCurrentUserUid(); + _auth = FirebaseAuth.instance; + + final currentUser = _auth.currentUser; + + if (_ciudad == '...') { + AuthenticationRepository.instance + .getCity(uid.toString()) + .then((String s) => setState(() { + _ciudad = s; + })); + } + + if (_photo == '...') { + AuthenticationRepository.instance + .getPhoto(uid.toString()) + .then((String s) => setState(() { + _photo = s; + })); + } + if (_estado == '...') { + AuthenticationRepository.instance + .getState(uid.toString()) + .then((String s) => setState(() { + _estado = s; + })); + } + } + + @override + Widget build(BuildContext context) { + final User? user = FirebaseAuth.instance.currentUser; + String city = _ciudad.toString(); + String state = _estado.toString(); + + return SafeArea( + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + iconTheme: const IconThemeData( + color: Colors.black, + ), + title: const Text( + 'Perfil', + style: TextStyle( + color: Colors.black, + ), + ), + ), + drawer: DrawerProfessional( + ref: storage.ref().child(_photo), + userName: user?.displayName ?? '', + userPhoneNumber: user?.phoneNumber ?? '', + userCity: city, + userState: state), + )); + } +} diff --git a/lib/src/screens/service.dart b/lib/src/screens/service.dart index 5f1650d..b3afb96 100644 --- a/lib/src/screens/service.dart +++ b/lib/src/screens/service.dart @@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/components/drawer_menu.dart'; +import 'package:prosappco/src/models/score_model.dart'; import 'package:prosappco/src/screens/professional.dart'; import 'package:intl/intl.dart'; @@ -16,6 +17,7 @@ class ServiceScreen extends StatefulWidget { class _ServiceScreenState extends State { final DateFormat formatter = DateFormat('dd/MM/yyyy'); + final DateTime now = DateTime.now(); DateTime? _selectedDate; TimeOfDay? _selectedTime; @@ -23,9 +25,9 @@ class _ServiceScreenState extends State { Future _selectDate(BuildContext context) async { final DateTime? picked = await showDatePicker( context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2022), - lastDate: DateTime(2025), + initialDate: now, + firstDate: DateTime(now.year), + lastDate: DateTime(now.year + 1), // builder: (context, child) { // return Theme(data: ThemeData.dark(), child: child!); // }, @@ -95,18 +97,10 @@ class _ServiceScreenState extends State { List opc = ["Servicio", "Opción 1", "Opción 2", "Opción 3"]; String defaultValue = opc[0]; - String city = _ciudad.toString(); - String state = _estado.toString(); - return SafeArea( child: Scaffold( backgroundColor: Color(0xFFD6F4FF), - drawer: DrawerMenu( - ref: storage.ref().child(_photo), - userName: user?.displayName ?? '', - userPhoneNumber: user?.phoneNumber ?? '', - userCity: city, - userState: state), + drawer: DrawerMenu(), body: SingleChildScrollView( reverse: true, child: Stack( @@ -243,8 +237,11 @@ class _ServiceScreenState extends State { _selectDate(context); }, readOnly: true, - decoration: const InputDecoration( - prefixIcon: Icon(Icons.calendar_month), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.calendar_month), + suffixIcon: _selectedDate == null + ? const Icon(Icons.arrow_drop_down) + : null, hintText: 'Fecha', ), controller: TextEditingController( diff --git a/lib/src/screens/welcome.dart b/lib/src/screens/welcome.dart index ca44cc6..75c1e50 100644 --- a/lib/src/screens/welcome.dart +++ b/lib/src/screens/welcome.dart @@ -7,6 +7,8 @@ import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/components/drawer_menu.dart'; import 'package:prosappco/src/components/primary_btn.dart'; import 'package:prosappco/src/controllers/add_name_email_city.dart'; +import 'package:prosappco/src/models/score_model.dart'; +import 'package:prosappco/src/models/user_model.dart'; import '../components/photo_view.dart'; @@ -21,55 +23,17 @@ class _WelcomeScreenState extends State { final FirebaseStorage storage = FirebaseStorage.instance; final uid = AuthenticationRepository.instance.getCurrentUserUid(); final controller = Get.put(NameEmailCityController()); - var _ciudad = ''; - var _photo = '...'; - var _estado = '...'; @override void initState() { super.initState(); - - if (_estado == '...') { - AuthenticationRepository.instance - .getState(uid.toString()) - .then((String s) => setState(() { - _estado = s; - })); - } - - if (_ciudad == '') { - AuthenticationRepository.instance - .getCity(uid.toString()) - .then((String s) => setState(() { - _ciudad = s; - })); - } - - if (_photo == '...') { - AuthenticationRepository.instance - .getPhoto(uid.toString()) - .then((String s) => setState(() { - _photo = s; - })); - } } @override Widget build(BuildContext context) { - final User? user = FirebaseAuth.instance.currentUser; - - // String name = _nombre.toString(); - String city = _ciudad.toString(); - String state = _estado.toString(); - return SafeArea( child: Scaffold( - drawer: DrawerMenu( - ref: storage.ref().child(_photo), - userName: user?.displayName ?? '', - userPhoneNumber: user?.phoneNumber ?? '', - userCity: city, - userState: state), + drawer: DrawerMenu(), resizeToAvoidBottomInset: false, backgroundColor: const Color(0xFFD6F4FF), body: Stack(