import 'package:flutter/material.dart'; import '../services/supabase_service.dart'; class ForgotPasswordScreen extends StatefulWidget { const ForgotPasswordScreen({super.key}); @override State createState() => _ForgotPasswordScreenState(); } class _ForgotPasswordScreenState extends State { final _emailController = TextEditingController(); final _otpController = TextEditingController(); bool _isLoading = false; bool _otpSent = false; // step 2: input OTP String _email = ''; @override void dispose() { _emailController.dispose(); _otpController.dispose(); super.dispose(); } // Step 1 — kirim OTP ke email Future _handleKirimOTP() async { final email = _emailController.text.trim(); if (email.isEmpty) { _showSnackBar('Email tidak boleh kosong!', isError: true); return; } if (!email.contains('@') || !email.contains('.')) { _showSnackBar('Format email tidak valid!', isError: true); return; } setState(() => _isLoading = true); try { await SupabaseService().resetPassword(email); if (mounted) { setState(() { _otpSent = true; _email = email; }); } } catch (e) { if (mounted) { final err = e.toString().toLowerCase(); String pesan = 'Gagal mengirim kode, coba lagi.'; if (err.contains('network') || err.contains('socket')) { pesan = 'Tidak ada koneksi internet.'; } else if (err.contains('rate limit') || err.contains('too many')) { pesan = 'Terlalu banyak percobaan, tunggu beberapa menit.'; } else if (err.contains('user not found') || err.contains('invalid')) { pesan = 'Email tidak terdaftar di sistem.'; } _showSnackBar(pesan, isError: true); } } finally { if (mounted) setState(() => _isLoading = false); } } // Step 2 — verifikasi OTP dan masuk ke halaman ganti password Future _handleVerifikasiOTP() async { final otp = _otpController.text.trim(); if (otp.isEmpty || otp.length != 6) { _showSnackBar('Masukkan kode 6 angka dari email!', isError: true); return; } setState(() => _isLoading = true); try { await SupabaseService().verifyOTP(_email, otp); if (mounted) { // OTP valid — langsung ke halaman ganti password Navigator.pushReplacementNamed( context, '/change_password', arguments: {'dari_reset': true}, ); } } catch (e) { if (mounted) { final err = e.toString().toLowerCase(); String pesan = 'Kode tidak valid atau sudah kadaluarsa.'; if (err.contains('expired')) { pesan = 'Kode sudah kadaluarsa. Kirim ulang kode baru.'; } else if (err.contains('invalid')) { pesan = 'Kode salah. Periksa kembali kode di email.'; } _showSnackBar(pesan, isError: true); } } finally { if (mounted) setState(() => _isLoading = false); } } void _showSnackBar(String pesan, {required bool isError}) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row(children: [ Icon( isError ? Icons.error_outline : Icons.check_circle_outline, color: Colors.white, ), const SizedBox(width: 10), Expanded( child: Text(pesan, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold)), ), ]), backgroundColor: isError ? Colors.red.shade700 : Colors.green.shade700, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), margin: const EdgeInsets.all(16), duration: const Duration(seconds: 4), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.green), onPressed: () => Navigator.pop(context), ), ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 30.0), child: _otpSent ? _buildStepOTP() : _buildStepEmail(), ), ), ); } // ── Step 1: Input Email ── Widget _buildStepEmail() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Lupa Password?', style: TextStyle( color: Colors.green, fontSize: 32, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), const Text( 'Masukkan email akun kamu. Kami akan kirim kode verifikasi 6 angka ke inbox kamu.', style: TextStyle(color: Colors.grey, fontSize: 14), ), const SizedBox(height: 50), // Field email Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: const Color(0xFF1A1A1A), borderRadius: BorderRadius.circular(25), border: Border.all(color: Colors.grey.withOpacity(0.3)), ), child: TextField( controller: _emailController, keyboardType: TextInputType.emailAddress, style: const TextStyle(color: Colors.white), decoration: const InputDecoration( prefixIcon: Icon(Icons.email, color: Colors.green), hintText: 'Email', hintStyle: TextStyle(color: Colors.grey), border: InputBorder.none, ), ), ), const SizedBox(height: 30), // Tombol kirim SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: _isLoading ? null : _handleKirimOTP, style: ElevatedButton.styleFrom( backgroundColor: Colors.green, disabledBackgroundColor: Colors.green.withOpacity(0.3), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15)), ), child: _isLoading ? const CircularProgressIndicator(color: Colors.white) : const Text( 'Kirim Kode Verifikasi', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), const SizedBox(height: 20), Center( child: TextButton( onPressed: () => Navigator.pop(context), child: const Text('Kembali ke Login', style: TextStyle(color: Colors.green)), ), ), ], ); } // ── Step 2: Input OTP ── Widget _buildStepOTP() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const CircleAvatar( radius: 40, backgroundColor: Color(0xFF1A1A1A), child: Icon(Icons.mark_email_read, size: 40, color: Colors.green), ), const SizedBox(height: 24), const Text( 'Cek Email Kamu', style: TextStyle( color: Colors.green, fontSize: 28, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text( 'Kode verifikasi 6 angka sudah dikirim ke:\n$_email\n\nMasukkan kode tersebut di bawah ini.', style: const TextStyle(color: Colors.grey, fontSize: 14), ), const SizedBox(height: 40), // Field OTP Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: const Color(0xFF1A1A1A), borderRadius: BorderRadius.circular(25), border: Border.all(color: Colors.green.withOpacity(0.5)), ), child: TextField( controller: _otpController, keyboardType: TextInputType.number, maxLength: 6, textAlign: TextAlign.center, style: const TextStyle( color: Colors.white, fontSize: 28, letterSpacing: 12), decoration: const InputDecoration( prefixIcon: Icon(Icons.lock_open, color: Colors.green), hintText: '000000', hintStyle: TextStyle(color: Colors.grey, letterSpacing: 8), border: InputBorder.none, counterText: '', // sembunyikan counter maxLength ), ), ), const SizedBox(height: 30), // Tombol verifikasi SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: _isLoading ? null : _handleVerifikasiOTP, style: ElevatedButton.styleFrom( backgroundColor: Colors.green, disabledBackgroundColor: Colors.green.withOpacity(0.3), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15)), ), child: _isLoading ? const CircularProgressIndicator(color: Colors.white) : const Text( 'Verifikasi Kode', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), const SizedBox(height: 16), // Kirim ulang kode Center( child: TextButton( onPressed: _isLoading ? null : () => setState(() { _otpSent = false; _otpController.clear(); }), child: const Text( 'Kirim ulang kode', style: TextStyle(color: Colors.green), ), ), ), ], ); } }