import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:image_picker/image_picker.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/components/photo_view_web.dart'; import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/screens/city.dart'; import 'package:prosappco/src/screens/new_number.dart'; import 'package:prosappco/src/screens/new_password.dart'; import 'package:universal_html/html.dart' as html; class ProfileWebScreen extends StatefulWidget { const ProfileWebScreen({super.key}); @override State createState() => _ProfileWebScreenState(); } class _ProfileWebScreenState extends State { final uid = AuthenticationRepository.instance.getCurrentUserUid(); final FirebaseStorage storage = FirebaseStorage.instance; late final FirebaseAuth _auth; List? filteredCities; // variables imagen String selectedImage = ''; XFile? file; Uint8List? selectedImagInBytes; String photoTemp = ''; // controladores final _formKey = GlobalKey(); final TextEditingController _nameController = TextEditingController(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _phoneNumberController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); bool _obscureText = true; // variables String _ciudad = '...'; String _photo = '...'; String? _email = ''; @override void initState() { super.initState(); final uid = AuthenticationRepository.instance.getCurrentUserUid(); _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!; } _email = currentUser?.email; 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; })); } } _selectFile(bool imageFrom) async { FilePickerResult? fileResult = await FilePicker.platform.pickFiles(); if (fileResult != null) { setState(() { selectedImage = fileResult.files.first.name; selectedImagInBytes = fileResult.files.first.bytes; }); } } _uploadFile() async { try { final now = DateTime.now(); final formattedDate = DateFormat('HHmmssddMMyyyy').format(now); final milliseconds = (now.microsecondsSinceEpoch / 1000).round(); final random = '$formattedDate$milliseconds'; final Reference ref = FirebaseStorage.instance .ref() .child('users') .child(uid!) .child('profile') .child(random); final metaData = SettableMetadata(contentType: 'image/jpeg'); final UploadTask uploadTask = ref.putData(selectedImagInBytes!, metaData); final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true); photoTemp = ref.fullPath; if (snapshot.state == TaskState.success) { return true; } else { return false; } } catch (e) { print('web image error - $e'); } } Future updateInfo() async { final currentUser = _auth.currentUser; final currentPhoneNumber = _auth.currentUser!.phoneNumber; String newName = _nameController.text.trim(); String newEmail = _emailController.text.trim(); String newPassword = _passwordController.text.trim(); if (newName.isEmpty) { // Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario Get.snackbar( 'Nombre Invalido', 'Ingrese un nombre válido.', snackPosition: SnackPosition.BOTTOM, ); return; } else { try { await FirebaseAuth.instance.currentUser!.updateDisplayName(newName); await FirebaseFirestore.instance.collection('users').doc(uid).update({ 'name': newName, 'lowerName': newName.toLowerCase(), }); print('Nombre actualizado correctamente'); } catch (e) { print('Error al actualizar el nombre: $e'); } } if (newEmail.isEmpty) { // Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario Get.snackbar( 'Correo Invalido', 'Ingrese un email válido.', snackPosition: SnackPosition.BOTTOM, ); return; } if (currentUser?.displayName != newName) { try { await FirebaseAuth.instance.currentUser!.updateDisplayName(newName); await FirebaseFirestore.instance.collection('users').doc(uid).update({ 'name': newName, 'lowerName': newName.toLowerCase(), }); print('Nombre actualizado correctamente'); } catch (e) { print('Error al actualizar el nombre: $e'); } } if (currentUser?.email != newEmail) { if (newPassword.isNotEmpty) { await FirebaseFirestore.instance.collection('users').doc(uid).update({ 'email': newEmail, }); updateEmailAndPassword(newEmail, newPassword); } else { Get.snackbar( 'Contraseña Invalida', 'Porfavor ingrese una contraseña.', snackPosition: SnackPosition.BOTTOM, ); } } String? selectedCity = _ciudad; // Guardar la ciudad seleccionada en el documento del usuario try { await FirebaseFirestore.instance.collection('users').doc(uid).update({ 'city': selectedCity, }); print('Ciudad actualizada correctamente'); } catch (e) { print('Error al actualizar la ciudad: $e'); } try { await FirebaseFirestore.instance .collection('users') .doc(uid) .update({'phoneNumber': currentPhoneNumber}); } catch (e) { print('e'); } try { await FirebaseFirestore.instance .collection('users') .doc(uid) .update({'email': newEmail}); } catch (e) { print('e'); } try { if (selectedImagInBytes == null) { return; } else { await _uploadFile(); updateImage(photoTemp); } } catch (e) { print('Error al actualizar la imagen de perfil $e'); } } 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 updateEmailAndPassword(String email, String password) async { final User? user = FirebaseAuth.instance.currentUser; if (user != null) { try { await user.updateEmail(email); await user.updatePassword(password); } catch (e) { Get.snackbar( 'Agregar correo', 'Inicie sesión para asegurarnos de que seas tú .', snackPosition: SnackPosition.BOTTOM, ); AuthenticationRepository.instance.logout(uid!); } } } Future> _getCities() 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; Map cityData = Map.from(entry.value); states[key] = cityData; } for (var state in states.entries) { var citysState = state.value.entries.map((city) => City( cityName: city.key, coordsOfCity: city.value, stateOfCity: state.key, countryOfCity: countryName, )); citys.addAll(citysState); } } } catch (e) { print('Error obteniendo las ciudades: $e'); } return citys; } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFD6F4FF), appBar: PopAppbar( onPressed: () { Navigator.pop(context); }, label: 'Perfil'), body: Center( child: SizedBox( width: 300, height: 600, child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), color: Colors.white, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.only(top: 20, bottom: 20), child: (selectedImagInBytes != null) ? LocalPhotoWeb(file: selectedImagInBytes) : ReferencePhotoWeb(ref: storage.ref().child(_photo)), ), TextFormField( controller: _nameController, maxLength: 50, validator: (value) { if (value == null || value.isEmpty) { return 'Porfavor ingrese un nombre.'; } if (value.length < 5) { return 'Debe tener al menos 5 caracteres.'; } return null; }, decoration: const InputDecoration( prefixIcon: Icon(Icons.person_outline), hintText: 'Nombre (Obligatorio)', ), ), _email != null ? TextFormField( onTap: () { Navigator.push(context, CupertinoPageRoute( builder: (BuildContext context) { return NewPasswordScreen(); }, )); }, readOnly: true, controller: _emailController, decoration: const InputDecoration( prefixIcon: Icon(Icons.email_outlined), hintText: 'Email (Obligatorio)', ), ) : TextFormField( controller: _emailController, validator: (String? value) { if (value == null || value.isEmpty) { return 'Por favor ingrese un email'; } final RegExp emailRegExp = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); if (!emailRegExp.hasMatch(value)) { return 'Por favor ingrese un email válido'; } return null; }, decoration: const InputDecoration( prefixIcon: Icon(Icons.email_outlined), hintText: 'Email (Obligatorio)', ), ), const SizedBox(height: 20.0), _email != null ? const SizedBox.shrink() : TextFormField( controller: _passwordController, obscureText: _obscureText, validator: (value) { if (value == null || value.isEmpty) { return 'Porfavor ingrese una contraseña.'; } if (value.length < 5) { return 'Debe tener al menos 5 caracteres.'; } return null; }, decoration: InputDecoration( prefixIcon: const Icon(Icons.lock_outline), suffixIcon: IconButton( icon: Icon( _obscureText ? Icons.visibility : Icons.visibility_off, color: Colors.grey, ), onPressed: () { setState(() { _obscureText = !_obscureText; }); }, ), hintText: 'Contraseña (Obligatorio)', ), ), _email != null ? const SizedBox.shrink() : const SizedBox(height: 20.0), FutureBuilder>( future: _getCities(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center( child: CircularProgressIndicator(), ); } else if (snapshot.hasError) { return const Center( child: Text('Error al obtener las ciudades'), ); } else { List filteredCities = snapshot.data!; return DropdownButtonFormField( value: _ciudad, onChanged: (String? newValue) { setState(() { _ciudad = newValue!; }); }, items: filteredCities.map((City city) { return DropdownMenuItem( value: city.cityName, child: Text(city.cityName ?? ''), ); }).toList(), decoration: InputDecoration( prefixIcon: const Icon(Icons.near_me), hintText: _ciudad, ), ); } }, ), const SizedBox(height: 20.0), TextFormField( controller: _phoneNumberController, readOnly: true, onTap: () { Navigator.of(context).push( CupertinoPageRoute( builder: (BuildContext context) { return const NewNumberScreen(); }, ), ); }, decoration: const InputDecoration( prefixIcon: Icon(Icons.phone_android), suffixIcon: Icon(Icons.edit_outlined), hintText: '+57'), ), Container( alignment: Alignment.bottomCenter, margin: const EdgeInsets.only(top: 30), padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton( onPressed: () async { if (_formKey.currentState!.validate()) { await updateInfo().whenComplete(() { html.window.location.reload(); Get.snackbar( 'Perfil', 'Información actualizada correctamente.', snackPosition: SnackPosition.TOP, ); }); } }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2BA4EC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), elevation: 0, minimumSize: const Size(200, 50), ), child: const Text( 'Guardar', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 17, ), ), ), ), ], ), ), ), ), ), ), ); } }