import 'package:flutter/material.dart'; import './services/auth_service.dart'; import './config/theme_colors.dart'; import './login_page.dart'; class ResetPasswordPage extends StatefulWidget { final String email; final String? initialToken; const ResetPasswordPage({ Key? key, required this.email, this.initialToken, }) : super(key: key); @override _ResetPasswordPageState createState() => _ResetPasswordPageState(); } class _ResetPasswordPageState extends State { final GlobalKey _formKey = GlobalKey(); final TextEditingController _tokenController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final TextEditingController _confirmPasswordController = TextEditingController(); final _authService = AuthService(); bool _isLoading = false; bool _isPasswordVisible = false; bool _isConfirmPasswordVisible = false; @override void initState() { super.initState(); if (widget.initialToken != null && widget.initialToken!.isNotEmpty) { _tokenController.text = widget.initialToken!; } } Future _resetPassword() async { if (!_formKey.currentState!.validate()) { return; } setState(() => _isLoading = true); try { final result = await _authService.resetPassword( token: _tokenController.text, password: _passwordController.text, passwordConfirmation: _confirmPasswordController.text, ); if (!mounted) return; setState(() => _isLoading = false); if (result['success']) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ Icon(Icons.check_circle, color: Colors.white), SizedBox(width: 8), Expanded( child: Text('Password berhasil diperbarui. Silakan login dengan password baru Anda.'), ), ], ), backgroundColor: Colors.green, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), duration: Duration(seconds: 4), ), ); // Kembali ke halaman login Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => LoginPage()), (Route route) => false, ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ Icon(Icons.error_outline, color: Colors.white), SizedBox(width: 8), Expanded( child: Text(result['message'] ?? 'Gagal memperbarui password.'), ), ], ), backgroundColor: Colors.red, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), duration: Duration(seconds: 4), ), ); } } catch (e) { if (!mounted) return; setState(() => _isLoading = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ Icon(Icons.warning, color: Colors.white), SizedBox(width: 8), Expanded( child: Text('Terjadi kesalahan: Tidak dapat terhubung ke server'), ), ], ), backgroundColor: Colors.orange, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), duration: Duration(seconds: 3), action: SnackBarAction( label: 'COBA LAGI', textColor: Colors.white, onPressed: () { _resetPassword(); }, ), ), ); } } @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( backgroundColor: ThemeColors.primary(context), body: Stack( children: [ // Background image Positioned.fill( child: Image.asset( isDarkMode ? 'assets/images/background_dark.png' : 'assets/images/background_light.png', fit: BoxFit.cover, ), ), // Logo di bagian atas Positioned( top: 120, left: 0, right: 0, child: Column( children: [ Container( width: 150, height: 150, decoration: BoxDecoration( image: DecorationImage( image: AssetImage( isDarkMode ? 'assets/images/logo_dark.png' : 'assets/images/logo_light.png' ), fit: BoxFit.contain, ), ), ), ], ), ), // Form container di bagian bawah Positioned( bottom: 0, left: 0, right: 0, child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: ThemeColors.background(context), borderRadius: BorderRadius.only( topLeft: Radius.circular(30), topRight: Radius.circular(30), ), boxShadow: [ BoxShadow( color: ThemeColors.shadowColor(context), spreadRadius: 5, blurRadius: 15, ), ], ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Reset Password', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: ThemeColors.text(context), ), ), SizedBox(height: 10), Text( 'Masukkan token dari email dan password baru Anda', style: TextStyle( fontSize: 14, color: ThemeColors.textGrey(context), ), ), SizedBox(height: 20), Form( key: _formKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: Column( children: [ // TextFormField( // controller: _tokenController, // enabled: !_isLoading, // decoration: InputDecoration( // hintText: 'Masukkan token dari email', // prefixIcon: Icon(Icons.vpn_key, color: ThemeColors.inputIcon(context)), // border: OutlineInputBorder( // borderRadius: BorderRadius.circular(12), // borderSide: BorderSide.none, // ), // filled: true, // fillColor: ThemeColors.inputFill(context), // errorStyle: TextStyle( // color: ThemeColors.error, // fontSize: 12, // ), // ), // validator: (value) { // if (value == null || value.isEmpty) { // return 'Token tidak boleh kosong'; // } // return null; // }, // ), SizedBox(height: 20), TextFormField( controller: _passwordController, enabled: !_isLoading, obscureText: !_isPasswordVisible, decoration: InputDecoration( hintText: 'Masukkan password baru', prefixIcon: Icon(Icons.lock, color: ThemeColors.inputIcon(context)), suffixIcon: IconButton( icon: Icon( _isPasswordVisible ? Icons.visibility_off : Icons.visibility, color: ThemeColors.inputIcon(context), ), onPressed: () { setState(() { _isPasswordVisible = !_isPasswordVisible; }); }, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), filled: true, fillColor: ThemeColors.inputFill(context), errorStyle: TextStyle( color: ThemeColors.error, fontSize: 12, ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Password tidak boleh kosong'; } if (value.length < 6) { return 'Password minimal 6 karakter'; } return null; }, ), SizedBox(height: 20), TextFormField( controller: _confirmPasswordController, enabled: !_isLoading, obscureText: !_isConfirmPasswordVisible, decoration: InputDecoration( hintText: 'Konfirmasi password baru', prefixIcon: Icon(Icons.lock_outline, color: ThemeColors.inputIcon(context)), suffixIcon: IconButton( icon: Icon( _isConfirmPasswordVisible ? Icons.visibility_off : Icons.visibility, color: ThemeColors.inputIcon(context), ), onPressed: () { setState(() { _isConfirmPasswordVisible = !_isConfirmPasswordVisible; }); }, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), filled: true, fillColor: ThemeColors.inputFill(context), errorStyle: TextStyle( color: ThemeColors.error, fontSize: 12, ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Konfirmasi password tidak boleh kosong'; } if (value != _passwordController.text) { return 'Konfirmasi password tidak sesuai'; } return null; }, ), SizedBox(height: 30), SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _isLoading ? null : _resetPassword, style: ElevatedButton.styleFrom( backgroundColor: ThemeColors.accent(context), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), disabledBackgroundColor: ThemeColors.buttonDisabled(context), ), child: _isLoading ? SizedBox( width: 24, height: 24, child: CircularProgressIndicator( color: ThemeColors.buttonText(context), strokeWidth: 2, ), ) : Text( 'RESET PASSWORD', style: TextStyle( color: ThemeColors.buttonText(context), fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), SizedBox(height: 20), ], ), ), ], ), ), ), ), ], ), ); } @override void dispose() { _tokenController.dispose(); _passwordController.dispose(); _confirmPasswordController.dispose(); super.dispose(); } }