import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:monitoring/config.dart'; class ChangePasswordScreen extends StatefulWidget { final String token; const ChangePasswordScreen({super.key, required this.token}); @override State createState() => _ChangePasswordScreenState(); } class _ChangePasswordScreenState extends State { final _formKey = GlobalKey(); final _oldPassController = TextEditingController(); final _newPassController = TextEditingController(); final _confirmPassController = TextEditingController(); bool _loading = false; bool _obscureOld = true; bool _obscureNew = true; bool _obscureConfirm = true; Future _submit() async { if (!_formKey.currentState!.validate()) return; setState(() => _loading = true); try { final dio = Dio( BaseOptions( headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, ), ); final response = await dio.post( '$baseUrl/password', data: { 'old_password': _oldPassController.text.trim(), 'new_password': _newPassController.text.trim(), 'confirm_password': _confirmPassController.text.trim(), }, ); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(response.data['message'] ?? 'Berhasil')), ); Navigator.pop(context); } } on DioException catch (e) { final msg = e.response?.data['message'] ?? e.response?.data.toString() ?? 'Gagal mengganti password'; ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg))); } catch (_) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Terjadi kesalahan saat mengganti password'), ), ); } finally { setState(() => _loading = false); } } @override void dispose() { _oldPassController.dispose(); _newPassController.dispose(); _confirmPassController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { const fieldPadding = EdgeInsets.symmetric(vertical: 8); return Scaffold( appBar: AppBar(title: const Text('Ganti Password')), body: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Form( key: _formKey, child: Column( children: [ const Text( 'Untuk alasan keamanan, gunakan password baru yang kuat dan mudah diingat.', style: TextStyle(fontSize: 14, color: Colors.black87), ), const SizedBox(height: 16), /// Old password Padding( padding: fieldPadding, child: TextFormField( controller: _oldPassController, obscureText: _obscureOld, decoration: InputDecoration( labelText: 'Password Saat Ini', border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon( _obscureOld ? Icons.visibility_off : Icons.visibility, ), onPressed: () => setState(() => _obscureOld = !_obscureOld), ), ), validator: (val) => val == null || val.isEmpty ? 'Wajib diisi' : null, ), ), /// New password Padding( padding: fieldPadding, child: TextFormField( controller: _newPassController, obscureText: _obscureNew, decoration: InputDecoration( labelText: 'Password Baru', border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon( _obscureNew ? Icons.visibility_off : Icons.visibility, ), onPressed: () => setState(() => _obscureNew = !_obscureNew), ), ), validator: (val) { if (val == null || val.isEmpty) return 'Wajib diisi'; if (val.length < 6) return 'Minimal 6 karakter'; return null; }, ), ), /// Confirm password Padding( padding: fieldPadding, child: TextFormField( controller: _confirmPassController, obscureText: _obscureConfirm, decoration: InputDecoration( labelText: 'Konfirmasi Password Baru', border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon( _obscureConfirm ? Icons.visibility_off : Icons.visibility, ), onPressed: () => setState( () => _obscureConfirm = !_obscureConfirm, ), ), ), validator: (val) => val != _newPassController.text ? 'Password tidak cocok' : null, ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _loading ? null : _submit, icon: const Icon(Icons.lock_open), label: _loading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text('Simpan Password'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), backgroundColor: Colors.green, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ), ), ], ), ), ), ); } }