From 50737e03ddfba2584518bc4a88d11b662aee56b8 Mon Sep 17 00:00:00 2001 From: Juan Felipe Duarte <70235683+DuarteJFelipe@users.noreply.github.com> Date: Tue, 4 Apr 2023 09:18:33 -0500 Subject: [PATCH] ciudades --- .../authentication_repository.dart | 11 + lib/src/controllers/new_phone_controller.dart | 13 + lib/src/screens/city.dart | 235 +++++++----------- lib/src/screens/new_number.dart | 40 ++- lib/src/screens/new_number_validation.dart | 153 ++++++++++++ lib/src/screens/profile.dart | 4 +- lib/src/screens/welcome.dart | 3 +- 7 files changed, 304 insertions(+), 155 deletions(-) create mode 100644 lib/src/controllers/new_phone_controller.dart create mode 100644 lib/src/screens/new_number_validation.dart diff --git a/lib/src/authentication/authentication_repository.dart b/lib/src/authentication/authentication_repository.dart index f2d7fdd..91b2512 100644 --- a/lib/src/authentication/authentication_repository.dart +++ b/lib/src/authentication/authentication_repository.dart @@ -132,4 +132,15 @@ class AuthenticationRepository extends GetxController { } return city; } + + Future updatePhoneNumber(String verificationId, String smsCode) async { + try { + PhoneAuthCredential credential = PhoneAuthProvider.credential( + verificationId: verificationId, smsCode: smsCode); + await FirebaseAuth.instance.currentUser!.updatePhoneNumber(credential); + print("Phone number updated successfully"); + } catch (e) { + print("Error updating phone number: $e"); + } + } } diff --git a/lib/src/controllers/new_phone_controller.dart b/lib/src/controllers/new_phone_controller.dart new file mode 100644 index 0000000..de5ac72 --- /dev/null +++ b/lib/src/controllers/new_phone_controller.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:prosappco/src/authentication/authentication_repository.dart'; + +class NewPhoneController extends GetxController { + static NewPhoneController get instance => Get.find(); + + final newPhoneNo = TextEditingController(); + + void phoneAuthentication(String newPhoneNo) { + AuthenticationRepository.instance.phoneAuthentication(newPhoneNo); + } +} diff --git a/lib/src/screens/city.dart b/lib/src/screens/city.dart index 31d9875..4e4f9d5 100644 --- a/lib/src/screens/city.dart +++ b/lib/src/screens/city.dart @@ -11,162 +11,90 @@ class CityScreen extends StatefulWidget { State createState() => _CityScreenState(); } -List cities = [ - "Abrego", - "Aguada", - "Albania", - "Aratoca", - "Arboledas", - "Barbosa", - "Barichara", - "Barrancabermeja", - "Betulia", - "Bochalema", - "Bolivar", - "Bucaramanga", - "Bucarasica", - "Cabrera", - "Cachira", - "Cacota", - "California", - "Capitanejo", - "Carcasi", - "Cepita", - "Cerrito", - "Charala", - "Charta", - "Chima", - "Chinácota", - "Chipata", - "Chitagá", - "Cimitarra", - "Concepcion", - "Confines", - "Contratacion", - "Convención", - "Coromoro", - "Cucutilla", - "Cúcuta", - "Curiti", - "Durania", - "El Carmen", - "El Carmen de Chucuri", - "El Guacamayo", - "El Penon", - "El Playon", - "El Tarra", - "El Zulia", - "Encino", - "Enciso", - "Florian", - "Floridablanca", - "Galán", - "Gambita", - "Giron", - "Gramalote", - "Guaca", - "Guadalupe", - "Guapota", - "Guavata", - "Guepsa", - "Hacarí", - "Hato", - "Herrán", - "Jesús Maria", - "Jordan", - "La Belleza", - "La Esperanza", - "La Paz", - "La Playa", - "Landazuri", - "Labateca", - "Lebrija", - "Los Patios", - "Los Santos", - "Lourdes", - "Macaravita", - "Malaga", - "Matanza", - "Mogotes", - "Molagavita", - "Mutiscua", - "Ocaña", - "Ocamonte", - "Oiba", - "Onzaga", - "Pamplona", - "Pamplonita", - "Palmar", - "Palmas del Socorro", - "Paramo", - "Piedecuesta", - "Pinchote", - "Puente Nacional", - "Puerto Parra", - "Puerto Santander", - "Puerto Wilches", - "Ragonvalia", - "Rionegro", - "Sabana de Torres", - "Salazar", - "San Andres", - "San Benito", - "San Calixto", - "San Cayetano", - "San Gil", - "San Joaquin", - "San Jose de Miranda", - "San Miguel", - "San Vicente de Chucuri", - "Santa Barbara", - "Santa Helena del Opon", - "Santiago", - "Sardinata", - "Silos", - "Simacota", - "Socorro", - "Surata", - "Suaita", - "Sucre", - "Tibú", - "Tona", - "Toledo", - "Valle de San Jose", - "Velez", - "Vetas", - "Villa Caro", - "Villa del Rosario", - "Zapatoca", - "Villanueva", -]; +final CollectionReference countriesCollection = + FirebaseFirestore.instance.collection('countries'); class City { - final String name; - City({required this.name}); + String? cityName; + String? stateOfCity; + String? countryOfCity; + + City({this.cityName, this.stateOfCity, this.countryOfCity}); + @override + String toString() { + return "${cityName ?? ""}, ${stateOfCity ?? ""}, ${countryOfCity ?? ""}"; + } } -List citiesList = cities.map((city) => City(name: city)).toList(); +Future> getCountries() async { + List citys = []; + + try { + QuerySnapshot countries = await countriesCollection.get(); + for (DocumentSnapshot country in countries.docs) { + String countryName = country.id; + Map data = country.data() as Map; + Map> states = {}; + + for (var entry in data.entries) { + String key = entry.key; + List value = List.from(entry.value); + states[key] = value; + } + + for (var state in states.entries) { + var citysState = state.value + .map((cityName) => City( + cityName: cityName, + stateOfCity: state.key, + countryOfCity: countryName)) + .toList(); + + citys.addAll(citysState); + } + } + } catch (e) { + print('xd $e'); + } + + return citys; +} class _CityScreenState extends State { - List filteredCities = citiesList; + List? filteredCities; TextEditingController searchController = TextEditingController(); final User? user = FirebaseAuth.instance.currentUser; - late final FirebaseAuth _auth; final uid = AuthenticationRepository.instance.getCurrentUserUid(); + List? _cities; @override void initState() { super.initState(); searchController.addListener(() { setState(() { - filteredCities = citiesList - .where((city) => removeDiacritics(city.name).toLowerCase().contains( - removeDiacritics(searchController.text.toLowerCase()))) - .toList(); + if (_cities != null) { + if (searchController.text.isEmpty) { + filteredCities = _cities!; + } else { + filteredCities = _cities! + .where((city) => removeDiacritics(city.cityName!) + .toLowerCase() + .contains( + removeDiacritics(searchController.text.toLowerCase()))) + .toList(); + } + } }); }); + + if (_cities == null) { + getCountries().then((List element) => setState(() { + _cities = element; + filteredCities = element; + })); + } } Future updateCity(String cityName) async { @@ -193,6 +121,15 @@ class _CityScreenState extends State { @override Widget build(BuildContext context) { + if (filteredCities == null) { + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.red), + ), + ); + } + var citys = filteredCities!; + return SafeArea( child: Scaffold( appBar: AppBar( @@ -226,12 +163,30 @@ class _CityScreenState extends State { ), Expanded( child: ListView.builder( - itemCount: filteredCities.length, + itemCount: citys.length, itemBuilder: (BuildContext context, int index) { return ListTile( - title: Text(filteredCities[index].name), + title: RichText( + text: TextSpan( + style: const TextStyle( + fontSize: 18.0, + color: Colors.black, + ), + children: [ + TextSpan( + text: '${citys[index].cityName ?? ""}, ', + style: const TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan( + text: + "${citys[index].stateOfCity ?? ""}, ${citys[index].countryOfCity ?? ""}", + style: TextStyle(color: Colors.grey[600]), + ), + ], + ), + ), onTap: () { - updateCity(filteredCities[index].name); + updateCity(citys[index].cityName ?? ""); Navigator.pushReplacementNamed(context, '/profile'); }, ); diff --git a/lib/src/screens/new_number.dart b/lib/src/screens/new_number.dart index a0b1fe7..7bddb27 100644 --- a/lib/src/screens/new_number.dart +++ b/lib/src/screens/new_number.dart @@ -1,5 +1,8 @@ +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:intl_phone_field/intl_phone_field.dart'; +import 'package:prosappco/src/controllers/phone_auth_controller.dart'; class NewNumberScreen extends StatefulWidget { const NewNumberScreen({super.key}); @@ -8,7 +11,22 @@ class NewNumberScreen extends StatefulWidget { State createState() => _NewNumberScreenState(); } +// Actualizar número de teléfono en Firebase +Future updatePhoneNumber(String verificationId, String smsCode) async { + try { + PhoneAuthCredential credential = PhoneAuthProvider.credential( + verificationId: verificationId, smsCode: smsCode); + await FirebaseAuth.instance.currentUser!.updatePhoneNumber(credential); + print("Phone number updated successfully"); + } catch (e) { + print("Error updating phone number: $e"); + } +} + class _NewNumberScreenState extends State { + String completePhoneNumber = ''; + final _formKey = GlobalKey(); + @override Widget build(BuildContext context) { return SafeArea( @@ -37,15 +55,15 @@ class _NewNumberScreenState extends State { style: TextStyle(fontSize: 18.0, color: Color(0xFF65676B))), )), Form( - // key: _formKey, + key: _formKey, child: Padding( padding: EdgeInsets.only(bottom: 5), child: IntlPhoneField( // controller: controller.phoneNo, initialCountryCode: 'CO', - // onChanged: (phoneNo) { - // completePhoneNumber = phoneNo.completeNumber; - // }, + onChanged: (phoneNo) { + completePhoneNumber = phoneNo.completeNumber; + }, decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Color(0xFFECECEC)), @@ -74,12 +92,14 @@ class _NewNumberScreenState extends State { child: Center( child: ElevatedButton( onPressed: () { - // if (_formKey.currentState!.validate()) { - // PhoneAuthController.instance.phoneAuthentication( - // completePhoneNumber.trim(), - // ); - // Get.to(() => const CodeValidationScreen()); - // } + // updatePhoneNumber(completePhoneNumber, '123456'); + + if (_formKey.currentState!.validate()) { + PhoneAuthController.instance.phoneAuthentication( + completePhoneNumber.trim(), + ); + Get.to(NewNumberScreen()); + } }, child: Text( 'Enviar código', diff --git a/lib/src/screens/new_number_validation.dart b/lib/src/screens/new_number_validation.dart new file mode 100644 index 0000000..9f1a840 --- /dev/null +++ b/lib/src/screens/new_number_validation.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_otp_text_field/flutter_otp_text_field.dart'; +import 'package:prosappco/src/controllers/otp_controller.dart'; + +class NewNumberValidationScreen extends StatefulWidget { + const NewNumberValidationScreen({super.key}); + + @override + State createState() => + _NewNumberValidationScreenState(); +} + +class _NewNumberValidationScreenState extends State { + var otp; + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Color(0xFFD6F4FF), + body: Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 280), + width: double.infinity, + height: 600, + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topRight: Radius.circular(50), + topLeft: Radius.circular(50))), + ), + Container( + margin: const EdgeInsets.only(top: 120, left: 70, right: 70), + child: const Image(image: AssetImage('images/logo_prosapp.png')), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 20), + margin: const EdgeInsets.only(top: 280, left: 25), + child: Row( + children: [ + IconButton( + icon: Icon( + Icons.arrow_back, + size: 30, + ), + onPressed: () { + Navigator.pop(context); + }, + ), + Text( + 'Validar código', + style: TextStyle( + color: Color(0xFF262626), + fontSize: 38.0, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.right, + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 20), + margin: const EdgeInsets.only(top: 350, left: 50, right: 50), + child: Column(children: [ + const Padding( + padding: EdgeInsets.only(bottom: 5), + child: Align( + alignment: Alignment.topLeft, + child: Text('Numero de celular', + style: TextStyle( + fontSize: 18.0, color: Color(0xFF65676B))), + )), + Padding( + padding: EdgeInsets.only(bottom: 20), + child: Row( + children: [ + Expanded( + child: TextField( + decoration: InputDecoration( + border: InputBorder.none, + hintText: '+57', + suffixIcon: Icon(Icons.edit), + ), + ), + ), + TextButton( + onPressed: () { + // Acción a realizar cuando se hace clic en el texto + }, + child: Text('Reenviar código'), + ), + ], + ), + ), + Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text('Codigo', + textAlign: TextAlign.left, + style: + TextStyle(fontSize: 18.0, color: Color(0xFF65676B))), + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 20), + child: OtpTextField( + numberOfFields: 6, + focusedBorderColor: Colors.blue, + fillColor: Colors.black.withOpacity(0.1), + filled: true, + keyboardType: TextInputType.number, + onSubmit: (code) { + otp = code; + OTPController.instance.verifyOTP(otp); + }, + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 40), + child: Center( + child: ElevatedButton( + onPressed: () { + OTPController.instance.verifyOTP(otp); + }, + child: Text( + 'Validar código', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + style: ElevatedButton.styleFrom( + primary: Color(0xFF2BA4EC), // Color del botón + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(50), // Bordes redondeados + ), + elevation: 0, + minimumSize: Size(230, 60), // Tamaño mínimo del botón + ), + )), + ), + ]), + ), + ], + ), + )); + } +} diff --git a/lib/src/screens/profile.dart b/lib/src/screens/profile.dart index aae3030..b1ee8ce 100644 --- a/lib/src/screens/profile.dart +++ b/lib/src/screens/profile.dart @@ -414,8 +414,6 @@ class _ProfileScreenState extends State { margin: EdgeInsets.only(top: 170), child: ElevatedButton( onPressed: () { - String newName = _nameController.text; - String newEmail = _emailController.text; updateInfo(); }, child: Text( @@ -427,7 +425,7 @@ class _ProfileScreenState extends State { ), ), style: ElevatedButton.styleFrom( - primary: Color(0xFF2BA4EC), + backgroundColor: Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), diff --git a/lib/src/screens/welcome.dart b/lib/src/screens/welcome.dart index 38410be..ff1f65d 100644 --- a/lib/src/screens/welcome.dart +++ b/lib/src/screens/welcome.dart @@ -17,7 +17,6 @@ class _WelcomeScreenState extends State { final uid = AuthenticationRepository.instance.getCurrentUserUid(); final _formKey = GlobalKey(); final controller = Get.put(NameEmailCityController()); - var _nombre = '...'; var _ciudad = ''; @override @@ -65,7 +64,7 @@ class _WelcomeScreenState extends State { style: TextStyle(fontSize: 12), ), Text( - '${city ?? "a"}', + '${city ?? ""}', style: TextStyle(fontSize: 12), ), ],