import 'package:sysfarma_mobile/src/app/widgets/app_panel.dart'; import 'package:sysfarma_mobile/src/core/network/api_client.dart'; import 'package:sysfarma_mobile/src/core/theme/app_tokens.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class ChangePasswordScreen extends ConsumerStatefulWidget { const ChangePasswordScreen({super.key}); @override ConsumerState createState() => _ChangePasswordScreenState(); } class _ChangePasswordScreenState extends ConsumerState { final _formKey = GlobalKey(); final _currentCtrl = TextEditingController(); final _newCtrl = TextEditingController(); final _confirmCtrl = TextEditingController(); bool _obscureCurrent = true; bool _obscureNew = true; bool _obscureConfirm = true; bool _submitting = false; @override void dispose() { _currentCtrl.dispose(); _newCtrl.dispose(); _confirmCtrl.dispose(); super.dispose(); } Future _submit() async { if (!_formKey.currentState!.validate()) return; setState(() => _submitting = true); try { final response = await ref.read(apiClientProvider).changePassword( currentPassword: _currentCtrl.text, newPassword: _newCtrl.text, ); if (!mounted) return; if (response.success) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Contrasena actualizada'), backgroundColor: AppTokens.success, ), ); context.pop(); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(response.message ?? 'No se pudo actualizar.'), backgroundColor: AppTokens.danger, ), ); } } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Error: $e'), backgroundColor: AppTokens.danger, ), ); } finally { if (mounted) setState(() => _submitting = false); } } InputDecoration _dec(String label, {required VoidCallback onToggle, required bool obscure}) { return InputDecoration( labelText: label, border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppTokens.radiusSmall), ), suffixIcon: IconButton( icon: Icon( obscure ? Icons.visibility_off_rounded : Icons.visibility_rounded, color: AppTokens.secondary, ), onPressed: onToggle, ), ); } @override Widget build(BuildContext context) { return SafeArea( child: ListView( padding: AppTokens.pagePadding, children: [ AppPanel( title: 'Cambiar contrasena', child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Ingresa tu contrasena actual y define una nueva.', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: AppTokens.secondary, ), ), const SizedBox(height: 16), TextFormField( controller: _currentCtrl, obscureText: _obscureCurrent, decoration: _dec( 'Contrasena actual', obscure: _obscureCurrent, onToggle: () => setState( () => _obscureCurrent = !_obscureCurrent), ), validator: (v) => (v == null || v.isEmpty) ? 'Ingresa tu contrasena actual' : null, ), const SizedBox(height: 14), TextFormField( controller: _newCtrl, obscureText: _obscureNew, decoration: _dec( 'Nueva contrasena', obscure: _obscureNew, onToggle: () => setState(() => _obscureNew = !_obscureNew), ), validator: (v) { if (v == null || v.isEmpty) { return 'Ingresa una nueva contrasena'; } if (v.length < 6) { return 'Debe tener al menos 6 caracteres'; } return null; }, ), const SizedBox(height: 14), TextFormField( controller: _confirmCtrl, obscureText: _obscureConfirm, decoration: _dec( 'Confirmar nueva contrasena', obscure: _obscureConfirm, onToggle: () => setState( () => _obscureConfirm = !_obscureConfirm), ), validator: (v) { if (v == null || v.isEmpty) { return 'Confirma tu nueva contrasena'; } if (v != _newCtrl.text) { return 'Las contrasenas no coinciden'; } return null; }, ), const SizedBox(height: 20), FilledButton.icon( onPressed: _submitting ? null : _submit, icon: _submitting ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Icon(Icons.lock_reset_rounded), label: Text(_submitting ? 'Actualizando...' : 'Cambiar contrasena'), ), ], ), ), ), ], ), ); } }