TKK-E32222341/lib/screens/auth/login_page.dart

171 lines
5.3 KiB
Dart

import 'package:flutter/material.dart';
import '../../services/auth_service.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final AuthService _authService = AuthService();
bool _isLoading = false;
String? _errorMessage;
Future<void> _handleLogin() async {
setState(() {
_isLoading = true;
_errorMessage = null;
});
try {
final user = await _authService.login(
_emailController.text.trim(),
_passwordController.text.trim(),
);
if (user != null) {
Navigator.pushReplacementNamed(context, '/main');
}
} catch (e) {
setState(() {
_errorMessage = e.toString().replaceAll('Exception:', '').trim();
});
} finally {
setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: [
// Background ungu di atas
Container(
height: MediaQuery.of(context).size.height * 0.20,
decoration: const BoxDecoration(
color: Color(0xFF6B4EFF),
),
),
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
children: [
const SizedBox(height: 80),
// Kartu besar logo + teks horizontal
Container(
width: screenWidth * 0.8,
padding: const EdgeInsets.symmetric(
vertical: 60,
horizontal: 32,
),
decoration: BoxDecoration(
color: const Color(0xFF8B70FF),
borderRadius: BorderRadius.circular(30),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.15),
blurRadius: 15,
offset: const Offset(0, 10),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/logo.png',
height: 40,
width: 40,
),
const SizedBox(width: 12),
const Text(
'AntiSpy',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
),
const SizedBox(height: 48),
// Email
TextField(
controller: _emailController,
decoration: const InputDecoration(
hintText: 'Email',
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
),
),
const SizedBox(height: 16),
// Password
TextField(
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(
hintText: 'Password',
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
),
),
const SizedBox(height: 24),
// Error
if (_errorMessage != null)
Text(
_errorMessage!,
style: const TextStyle(color: Colors.red),
),
const SizedBox(height: 16),
// Tombol Login
ElevatedButton(
onPressed: _isLoading ? null : _handleLogin,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF6B4EFF),
padding: const EdgeInsets.symmetric(
horizontal: 40, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Text('Login',
style: TextStyle(color: Colors.white)),
),
const SizedBox(height: 40),
],
),
),
],
),
);
}
}