amoriai/lib/screens/auth/forgot_password_screen.dart

261 lines
8.8 KiB
Dart

import 'package:flutter/material.dart';
import '../../core/theme/app_theme.dart';
import '../../services/firebase_service.dart';
// Same colors as LoginScreen for consistency
const Color primaryBrown = Color(0xFF4A3C3C);
const Color lightBrown = Color(0xFF6B5B5B);
const Color headerGradientStart = Color(0xFF5D4E4E);
const Color headerGradientEnd = Color(0xFF8B7B7B);
class ForgotPasswordScreen extends StatefulWidget {
const ForgotPasswordScreen({super.key});
@override
State<ForgotPasswordScreen> createState() => _ForgotPasswordScreenState();
}
class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
final _emailController = TextEditingController();
bool _isLoading = false;
@override
void dispose() {
_emailController.dispose();
super.dispose();
}
Future<void> _handleResetPassword() async {
if (_emailController.text.trim().isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Silakan masukkan email Anda')),
);
return;
}
setState(() => _isLoading = true);
try {
await FirebaseService().resetPassword(_emailController.text.trim());
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Email reset password telah dikirim'),
backgroundColor: AppTheme.success,
),
);
Navigator.pop(context); // Go back to login
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(e.toString()),
backgroundColor: AppTheme.error,
),
);
}
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: primaryBrown),
onPressed: () => Navigator.pop(context),
),
backgroundColor: Colors.white,
elevation: 0,
centerTitle: true,
title: const Text(
'Lupa Password',
style: TextStyle(
fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
color: primaryBrown,
),
),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
// Illustration (Optional, using a placeholder icon or image if available)
Icon(
Icons.lock_reset_rounded,
size: 80,
color: primaryBrown.withOpacity(0.5),
),
const SizedBox(height: 32),
const Text(
'Reset Kata Sandi',
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 24,
fontWeight: FontWeight.bold,
color: primaryBrown,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
'Masukkan email yang terdaftar akun Anda. Kami akan mengirimkan link untuk mereset kata sandi Anda.',
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
color: primaryBrown.withOpacity(0.6),
height: 1.5,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
// Email Input
Builder(
builder: (context) {
return TextField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
onTap: () {
Future.delayed(const Duration(milliseconds: 300), () {
if (context.mounted) {
Scrollable.ensureVisible(
context,
alignment: 0.5,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
});
},
style: const TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
color: primaryBrown,
),
decoration: InputDecoration(
labelText: 'Email',
hintText: 'nama@email.com',
labelStyle: TextStyle(
fontFamily: 'Poppins',
fontSize: 12,
color: primaryBrown.withOpacity(0.6),
),
hintStyle: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
color: primaryBrown.withOpacity(0.4),
),
prefixIcon: Icon(
Icons.email_outlined,
color: primaryBrown.withOpacity(0.5),
),
filled: true,
fillColor: Colors.grey[50], // Very light grey for input
contentPadding: const EdgeInsets.all(16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: primaryBrown.withOpacity(0.15),
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: primaryBrown.withOpacity(0.15),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color: primaryBrown.withOpacity(0.4),
),
),
),
);
},
),
const SizedBox(height: 32),
// Send Button (Gradient)
Stack(
clipBehavior: Clip.none,
children: [
// Shadow
Positioned(
top: -6,
left: 0,
right: -6,
bottom: 6,
child: Container(
decoration: BoxDecoration(
color: primaryBrown.withOpacity(0.3),
borderRadius: BorderRadius.circular(12),
),
),
),
// Button
Container(
height: 52,
width: double.infinity,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [lightBrown, headerGradientEnd],
),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: primaryBrown.withOpacity(0.2),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: ElevatedButton(
onPressed: _isLoading ? null : _handleResetPassword,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: _isLoading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Text(
'Kirim Link Reset',
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
],
),
],
),
),
);
}
}