TKK_E32230206/lib/features/auth/login_page.dart

175 lines
5.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/app_theme.dart';
import '../../core/routes.dart';
import '../../core/widgets/auth_primary_button.dart';
import '../../core/widgets/auth_password_field.dart';
import '../../core/widgets/auth_scaffold.dart';
import '../../core/widgets/auth_text_field.dart';
import 'auth_notifier.dart';
import 'auth_state.dart';
class LoginPage extends ConsumerStatefulWidget {
const LoginPage({super.key});
@override
ConsumerState<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends ConsumerState<LoginPage> {
final _formKey = GlobalKey<FormState>();
final _emailCtrl = TextEditingController();
final _passwordCtrl = TextEditingController();
AutovalidateMode _autoValidate = AutovalidateMode.disabled;
bool _isButtonEnabled = false;
@override
void initState() {
super.initState();
_emailCtrl.addListener(_checkButton);
_passwordCtrl.addListener(_checkButton);
}
void _checkButton() {
final filled = _emailCtrl.text.isNotEmpty &&
_passwordCtrl.text.isNotEmpty;
if (filled != _isButtonEnabled) {
setState(() => _isButtonEnabled = filled);
}
}
@override
void dispose() {
_emailCtrl.dispose();
_passwordCtrl.dispose();
super.dispose();
}
Future<void> _submit() async {
setState(() => _autoValidate = AutovalidateMode.onUserInteraction);
if (!_formKey.currentState!.validate()) return;
await ref.read(authProvider.notifier).login(
_emailCtrl.text,
_passwordCtrl.text,
);
if (!mounted) return;
final state = ref.read(authProvider);
if (state is AuthSuccess) {
Navigator.pushNamedAndRemoveUntil(context, AppRoutes.main, (route) => false);
} else if (state is AuthError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.message),
backgroundColor: AppTheme.statusDanger,
),
);
ref.read(authProvider.notifier).resetError();
}
}
@override
Widget build(BuildContext context) {
final authState = ref.watch(authProvider);
final isLoading = authState is AuthLoading;
return AuthScaffold(
title: 'Log in',
subtitle: 'Masukkan email & password yang telah terdaftar',
child: Form(
key: _formKey,
autovalidateMode: _autoValidate,
child: Column(
children: [
AuthTextField(
controller: _emailCtrl,
label: 'Email',
keyboardType: TextInputType.emailAddress,
prefixIcon: Icons.email_outlined,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email tidak boleh kosong';
}
if (!value.contains('@') || !value.contains('.')) {
return 'Format email tidak valid';
}
return null;
},
),
const SizedBox(height: 20),
AuthPasswordField(
controller: _passwordCtrl,
label: 'Password',
validator: (value) {
if (value == null || value.isEmpty) {
return 'Password tidak boleh kosong';
}
if (value.length < 6) {
return 'Minimal 6 karakter';
}
return null;
},
),
const SizedBox(height: 12),
Align(
alignment: Alignment.centerRight,
child: TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
minimumSize: Size.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
onPressed: () {},
child: const Text(
'Lupa password?',
style: TextStyle(color: AppTheme.primary, fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 40),
AuthPrimaryButton(
text: 'Masuk',
enabled: _isButtonEnabled,
isLoading: isLoading,
onPressed: _submit,
),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Belum punya akun? ',
style: TextStyle(color: AppTheme.textSecondary),
),
GestureDetector(
onTap: () => Navigator.pushReplacementNamed(context, AppRoutes.register),
child: const Text(
'Daftar di sini',
style: TextStyle(
color: AppTheme.primary,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
),
);
}
}