import 'dart:typed_data'; import 'package:file_picker/file_picker.dart'; import 'package:prosapp_web_app/models/city.dart'; import 'package:prosapp_web_app/models/usuario.dart'; import 'package:prosapp_web_app/providers/auth_provider.dart'; import 'package:prosapp_web_app/providers/cities_provider.dart'; import 'package:prosapp_web_app/providers/profile_form_provider.dart'; import 'package:prosapp_web_app/router/router.dart'; import 'package:prosapp_web_app/services/navigation_service.dart'; import 'package:prosapp_web_app/services/notifications_service.dart'; import 'package:prosapp_web_app/ui/cards/white_card.dart'; import 'package:prosapp_web_app/ui/inputs/custom_inputs.dart'; import 'package:prosapp_web_app/ui/labels/custom_labels.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class ProfileView extends StatefulWidget { const ProfileView({super.key}); @override State createState() => _ProfileViewState(); } class _ProfileViewState extends State { Usuario? user; List cities = []; @override void initState() { super.initState(); final authProvider = Provider.of(context, listen: false); final profileFormProvider = Provider.of(context, listen: false); final citiesProvider = Provider.of(context, listen: false); profileFormProvider.user = authProvider.user; setState(() { cities = citiesProvider.cities; user = authProvider.user; }); } @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { if (constraints.maxWidth < 700) { return ListView( physics: const ClampingScrollPhysics(), children: const [SizedBox(height: 10), _ProfileViewBody()], ); } else { return Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), child: ListView( physics: const ClampingScrollPhysics(), children: const [SizedBox(height: 10), _ProfileViewBody()], ), ); } }); } } class _ProfileViewBody extends StatelessWidget { const _ProfileViewBody(); @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { if (constraints.maxWidth < 700) { return const Column( children: [ _AvatarContainer(containerFull: true), _ProfileViewForm(), ], ); } else { return Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 900), child: Table( columnWidths: const { 0: FixedColumnWidth(250), }, children: const [ TableRow( children: [ _AvatarContainer(containerFull: true), _ProfileViewForm(), ], ) ], ), ), ); } }); } } class _ProfileViewForm extends StatelessWidget { const _ProfileViewForm(); @override Widget build(BuildContext context) { final profileFormProvider = Provider.of(context); final citiesProvider = Provider.of(context); final cities = citiesProvider.cities; final user = profileFormProvider.user!; return WhiteCard( title: 'Información general', child: Form( key: profileFormProvider.formKey, autovalidateMode: AutovalidateMode.always, child: Column( children: [ const SizedBox(height: 10), TextFormField( initialValue: user.name, validator: (value) { if (value == null || value.isEmpty) { return 'El nombre es obligatorio'; } if (value.trim().length < 4) { return 'El nombre debe tener al menos 4 caracteres'; } return null; }, onChanged: (value) { profileFormProvider.copyUserWith(name: value); }, decoration: CustomInputs.formInputDecoration( hint: 'Nombre de usuario', label: 'Nombre', icon: Icons.person_outline, ), ), const SizedBox(height: 20), TextFormField( readOnly: true, onTap: user.phone == null || user.phone!.isEmpty ? () { NavigationService.navigateTo(Flurorouter.phoneRoute); } : null, initialValue: user.phone ?? '', decoration: CustomInputs.formInputDecoration( hint: 'Número de teléfono', label: 'Teléfono', icon: Icons.phone, ), ), const SizedBox(height: 20), TextFormField( readOnly: true, onTap: user.email == null || user.email!.isEmpty ? () { NavigationService.navigateTo(Flurorouter.emailRoute); } : null, initialValue: user.email ?? '', decoration: CustomInputs.formInputDecoration( hint: 'Correo del usuario', label: 'Correo', icon: Icons.email_outlined, ), ), const SizedBox(height: 20), DropdownButtonFormField( validator: (value) { if (value == null) { return 'La ciudad es obligatoria'; } return null; }, value: user.city == '' ? null : user.city, decoration: CustomInputs.formInputDecoration( hint: 'Selecciona tu ciudad', label: 'Ciudad', icon: Icons.location_city_outlined, ), items: cities.map((City ciudad) { return DropdownMenuItem( value: ciudad.cityName, child: Text('${ciudad.cityName} - ${ciudad.stateOfCity}', style: const TextStyle( color: Colors.black, fontWeight: FontWeight.normal, )), ); }).toList(), onChanged: (value) { profileFormProvider.copyUserWith(city: value!); }), const SizedBox(height: 20), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 130), child: ElevatedButton( onPressed: () async { await profileFormProvider.updateUserInfo(); Provider.of(context, listen: false) .refreshUser(); }, style: ButtonStyle( backgroundColor: WidgetStateProperty.all( Colors.blue.shade400, ), shape: WidgetStateProperty.all(const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(5)), )), shadowColor: WidgetStateProperty.all(Colors.transparent), ), child: const Text('Guardar', style: TextStyle(color: Colors.white)), ), ), const SizedBox(height: 10), ], ), ), ); } } class _AvatarContainer extends StatelessWidget { final bool containerFull; const _AvatarContainer({required this.containerFull}); @override Widget build(BuildContext context) { final user = Provider.of(context).user!; final profileFormProvider = Provider.of(context); final image = (profileFormProvider.user!.picture == '' || profileFormProvider.user!.picture == null) ? const Image(image: AssetImage('no-image.jpg')) : FadeInImage.assetNetwork( placeholder: 'loader.gif', fit: BoxFit.cover, image: profileFormProvider.user!.picture!, ); return WhiteCard( width: containerFull ? null : 250, child: SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( user.name, style: CustomLabels.h2, textAlign: TextAlign.center, ), const SizedBox(height: 10), SizedBox( width: 160, height: 160, child: Stack( children: [ SizedBox( width: 200, height: 200, child: ClipOval(child: image), ), Positioned( bottom: 5, right: 5, child: Container( width: 45, height: 45, decoration: BoxDecoration( borderRadius: BorderRadius.circular(100), border: Border.all(color: Colors.white, width: 5), ), child: FloatingActionButton( onPressed: () async { FilePickerResult? result = await FilePicker.platform.pickFiles( withData: true, ); if (result != null) { PlatformFile file = result.files.first; Uint8List? fileBytes = file.bytes; if (fileBytes != null) { NotificationsService.showBusyIndicator(context); await profileFormProvider .uploadPicture(fileBytes); Provider.of(context, listen: false) .refreshUser(); Navigator.pop(context); } } else {} }, backgroundColor: Colors.indigo, elevation: 0, child: const Icon( Icons.camera_alt_outlined, size: 20, color: Colors.white, ), ), ), ) ], ), ), const SizedBox(height: 20), ], ), ), ); } }