This commit is contained in:
Juan Felipe Duarte
2023-04-03 14:28:58 -05:00
parent 210b479cde
commit 9656a85090
6 changed files with 266 additions and 82 deletions
+2
View File
@@ -5,6 +5,7 @@ import 'package:prosappco/src/screens/city.dart';
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/profile.dart';
import 'package:prosappco/src/screens/register.dart';
import 'package:prosappco/src/screens/welcome.dart';
@@ -35,6 +36,7 @@ class MyApp extends StatelessWidget {
'/profile': (context) => ProfileScreen(),
'/register': (context) => RegisterScreen(),
'/city': (context) => CityScreen(),
'/newNumber': (context) => NewNumberScreen(),
},
onGenerateRoute: (settings) {
throw Exception('Ruta desconocida: ${settings.name}');
@@ -27,9 +27,7 @@ class AuthenticationRepository extends GetxController {
}
_setInitialScreen(User? user) {
user == null
? Get.offAll(() => const LoginScreen())
: Get.offAll(() => const WelcomeScreen());
user == null ? Get.offAll(LoginScreen()) : Get.offAll(WelcomeScreen());
}
Future<void> phoneAuthentication(String phoneNo) async {
@@ -76,8 +74,8 @@ class AuthenticationRepository extends GetxController {
email: email, password: password);
firebaseUser.value != null
? Get.offAll(() => WelcomeScreen())
: Get.to(() => LoginScreen());
? Get.offAll(WelcomeScreen())
: Get.to(LoginScreen());
} on FirebaseAuthException catch (e) {
final ex = SignUpWithEmailAndPasswordFailure.code(e.code);
print('FIREBASE AUTH EXCEPTION - ${ex.message}');
@@ -122,36 +120,13 @@ class AuthenticationRepository extends GetxController {
return user?.uid;
}
Future<void> addNameAndEmail(
uid, String name, String email, String city) async {
final usersCollection = FirebaseFirestore.instance.collection('users');
await usersCollection.doc(uid).set({
'name': name,
'email': email,
'city': city,
});
}
Future<String> getName(String uid) async {
String name = '...';
try {
final snapshot =
await FirebaseFirestore.instance.collection('users').doc(uid).get();
final Map<String, dynamic>? data = snapshot.data();
name = data?['name'] ?? '...';
} catch (e) {
print('Error getting name: $e');
}
return name;
}
Future<String> getCity(String uid) async {
String city = '...';
String city = '';
try {
final snapshot =
await FirebaseFirestore.instance.collection('users').doc(uid).get();
final Map<String, dynamic>? data = snapshot.data();
city = data?['city'] ?? '...';
city = data?['city'] ?? '';
} catch (e) {
print('Error getting city: $e');
}
+38 -2
View File
@@ -1,5 +1,8 @@
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';
class CityScreen extends StatefulWidget {
const CityScreen({super.key});
@@ -139,7 +142,6 @@ List<String> cities = [
class City {
final String name;
City({required this.name});
}
@@ -147,7 +149,12 @@ List<City> citiesList = cities.map((city) => City(name: city)).toList();
class _CityScreenState extends State<CityScreen> {
List<City> filteredCities = citiesList;
TextEditingController searchController = TextEditingController();
final User? user = FirebaseAuth.instance.currentUser;
late final FirebaseAuth _auth;
final uid = AuthenticationRepository.instance.getCurrentUserUid();
@override
void initState() {
@@ -162,12 +169,40 @@ class _CityScreenState extends State<CityScreen> {
});
}
Future<void> updateCity(String cityName) async {
try {
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.update({'city': cityName});
print('Ciudad actualizada correctamente');
} catch (e) {
try {
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.set({'city': cityName});
} catch (e) {
print('Error al agregar la ciudad: $e');
}
print('Error al actualizar la ciudad: $e');
}
}
@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, '/profile');
},
),
iconTheme: IconThemeData(
color: Colors.black,
),
@@ -196,7 +231,8 @@ class _CityScreenState extends State<CityScreen> {
return ListTile(
title: Text(filteredCities[index].name),
onTap: () {
print(filteredCities[index].name);
updateCity(filteredCities[index].name);
Navigator.pushReplacementNamed(context, '/profile');
},
);
},
+106
View File
@@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:intl_phone_field/intl_phone_field.dart';
class NewNumberScreen extends StatefulWidget {
const NewNumberScreen({super.key});
@override
State<NewNumberScreen> createState() => _NewNumberScreenState();
}
class _NewNumberScreenState extends State<NewNumberScreen> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(
color: Colors.black,
),
title: Text(
'Añadir numero',
style: TextStyle(
color: Colors.black,
),
)),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 20),
margin: const EdgeInsets.only(top: 30, 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))),
)),
Form(
// key: _formKey,
child: Padding(
padding: EdgeInsets.only(bottom: 5),
child: IntlPhoneField(
// controller: controller.phoneNo,
initialCountryCode: 'CO',
// onChanged: (phoneNo) {
// completePhoneNumber = phoneNo.completeNumber;
// },
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xFFECECEC)),
borderRadius: BorderRadius.all(
Radius.circular(50),
)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xFFECECEC)),
borderRadius: BorderRadius.all(
Radius.circular(50),
)),
fillColor: Color.fromARGB(255, 239, 239, 239),
filled: true,
),
),
),
),
const Padding(
padding: EdgeInsets.only(bottom: 30),
child: Text('Un código será enviado a este numero de celular.',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 13.0, color: Color(0xFF65676B))),
),
Padding(
padding: EdgeInsets.only(bottom: 30),
child: Center(
child: ElevatedButton(
onPressed: () {
// if (_formKey.currentState!.validate()) {
// PhoneAuthController.instance.phoneAuthentication(
// completePhoneNumber.trim(),
// );
// Get.to(() => const CodeValidationScreen());
// }
},
child: Text(
'Enviar 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
),
)),
),
]),
),
));
}
}
+100 -26
View File
@@ -1,3 +1,5 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl_phone_field/countries.dart';
@@ -6,7 +8,7 @@ import 'package:prosappco/src/controllers/add_name_email_city.dart';
import 'package:prosappco/src/screens/welcome.dart';
class ProfileScreen extends StatefulWidget {
const ProfileScreen({super.key});
ProfileScreen({Key? key}) : super(key: key);
@override
State<ProfileScreen> createState() => _ProfileScreenState();
@@ -16,20 +18,31 @@ class _ProfileScreenState extends State<ProfileScreen> {
final uid = AuthenticationRepository.instance.getCurrentUserUid();
final _formKey = GlobalKey<FormState>();
final controller = Get.put(NameEmailCityController());
final _phoneNumberController = TextEditingController();
final _nameController = TextEditingController();
final _emailController = TextEditingController();
late final FirebaseAuth _auth;
var _nombre = '...';
var _ciudad = '...';
@override
void initState() {
super.initState();
if (_nombre == '...') {
AuthenticationRepository.instance
.getName(uid.toString())
.then((String s) => setState(() {
_nombre = s;
}));
_auth = FirebaseAuth.instance;
final currentUser = _auth.currentUser;
if (currentUser != null && currentUser.phoneNumber != null) {
_phoneNumberController.text = currentUser.phoneNumber!;
}
if (currentUser != null && currentUser.displayName != null) {
_nameController.text = currentUser.displayName!;
}
if (currentUser != null && currentUser.email != null) {
_emailController.text = currentUser.email!;
}
if (_ciudad == '...') {
AuthenticationRepository.instance
.getCity(uid.toString())
@@ -39,9 +52,73 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
}
Future<void> updateInfo() async {
String newName = _nameController.text.trim();
String newEmail = _emailController.text.trim();
if (newName.isEmpty) {
// Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Ingrese un nombre válido')),
);
return;
}
if (newEmail.isEmpty) {
// Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Ingrese un email válido')),
);
return;
}
try {
await FirebaseAuth.instance.currentUser!.updateDisplayName(newName);
await FirebaseFirestore.instance.collection('users').doc(uid).update({
'name': newName,
});
print('Nombre actualizado correctamente');
} catch (e) {
print('Error al actualizar el nombre: $e');
}
try {
await FirebaseAuth.instance.currentUser!.updateEmail(newEmail);
await FirebaseFirestore.instance.collection('users').doc(uid).update({
'email': newEmail,
});
print('Correo electrónico actualizado correctamente');
} catch (e) {
print('Error al actualizar el correo electrónico: $e');
}
AuthCredential credential =
EmailAuthProvider.credential(email: newEmail, password: '654321');
try {
// Reautentica al usuario con las credenciales proporcionadas
await FirebaseAuth.instance.currentUser!
.reauthenticateWithCredential(credential);
// Actualiza el correo electrónico del usuario
await FirebaseAuth.instance.currentUser!.updateEmail(newEmail);
// Actualiza los datos del usuario en tu base de datos
await FirebaseFirestore.instance.collection('users').doc(uid).update({
'email': newEmail,
});
print('Correo electrónico actualizado correctamente');
} catch (e) {
print('Error al actualizar el correo electrónico: $e');
}
}
@override
Widget build(BuildContext context) {
String name = _nombre.toString();
final User? user = FirebaseAuth.instance.currentUser;
String city = _ciudad.toString();
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
@@ -70,15 +147,13 @@ class _ProfileScreenState extends State<ProfileScreen> {
onTap: () {
Scaffold.of(context).openEndDrawer();
},
title: Text('$name',
title: Text('${user?.displayName}',
style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AuthenticationRepository.instance
.getCurrentUserPhone()
.toString(),
'${user?.phoneNumber}',
style: TextStyle(fontSize: 12),
),
Text(
@@ -287,7 +362,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
child: Column(
children: [
TextFormField(
controller: controller.name,
controller: _nameController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.person_outline),
hintText: 'Nombre'),
@@ -297,7 +372,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
20.0), // Agrega espacio vertical entre los TextFormFields
TextFormField(
controller: controller.email,
controller: _emailController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
hintText: 'Email'),
@@ -306,24 +381,26 @@ class _ProfileScreenState extends State<ProfileScreen> {
height:
20.0), // Agrega espacio vertical entre los TextFormFields
TextFormField(
controller: controller.city,
readOnly: true,
onTap: () {
Navigator.pushNamed(context, '/city');
Navigator.pushReplacementNamed(context, '/city');
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.near_me),
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Ciudad',
hintText: city == '' ? 'Ciudad' : '$city',
),
),
SizedBox(
height:
20.0), // Agrega espacio vertical entre los TextFormFields
TextFormField(
controller: controller.name,
controller: _phoneNumberController,
readOnly: true,
onTap: () {
Navigator.pushNamed(context, '/newNumber');
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.phone_android),
suffixIcon: Icon(Icons.edit_outlined),
@@ -337,12 +414,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
margin: EdgeInsets.only(top: 170),
child: ElevatedButton(
onPressed: () {
// AuthenticationRepository.instance.addNameAndEmail(
// uid,
// controller.name.text.trim(),
// controller.email.text.trim(),
// controller.city.text.trim(),
// );
String newName = _nameController.text;
String newEmail = _emailController.text;
updateInfo();
},
child: Text(
'Guardar',
+15 -24
View File
@@ -18,33 +18,27 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
final _formKey = GlobalKey<FormState>();
final controller = Get.put(NameEmailCityController());
var _nombre = '...';
var _ciudad = '...';
var _ciudad = '';
@override
void initState() {
super.initState();
// if (_nombre == '...') {
// AuthenticationRepository.instance
// .getName(uid.toString())
// .then((String s) => setState(() {
// _nombre = s;
// }));
// }
// if (_ciudad == '...') {
// AuthenticationRepository.instance
// .getCity(uid.toString())
// .then((String s) => setState(() {
// _ciudad = s;
// }));
// }
if (_ciudad == '') {
AuthenticationRepository.instance
.getCity(uid.toString())
.then((String s) => setState(() {
_ciudad = s;
}));
}
}
@override
Widget build(BuildContext context) {
String name = 'Felipe el du';
String city = 'Felipe el du';
final User? user = FirebaseAuth.instance.currentUser;
// String name = _nombre.toString();
// String city = _ciudad.toString();
String city = _ciudad.toString();
return SafeArea(
child: Scaffold(
@@ -61,20 +55,17 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
onTap: () {
Navigator.pushNamed(context, '/profile');
},
title: Text('$name',
title: Text('${user?.displayName ?? user?.email}',
style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'friki',
// AuthenticationRepository.instance
// .getCurrentUserPhone()
// .toString(),
'${user?.phoneNumber ?? ''}',
style: TextStyle(fontSize: 12),
),
Text(
'$city',
'${city ?? "a"}',
style: TextStyle(fontSize: 12),
),
],