TTK_E32222585_flutter/lib/login_screen.dart

280 lines
9.3 KiB
Dart

import 'dart:convert';
import 'package:absen/config/config.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dashboard_screen.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
bool _obscurePassword = true;
bool _isLoading = false;
Future<void> _login() async {
setState(() {
_isLoading = true;
});
final url = Uri.parse('${AppConfig.baseUrl}/api/login');
try {
final response = await http.post(
url,
headers: {
'Content-Type': 'application/json',
'X-Platform': 'mobile', // ✅ penting!
},
body: jsonEncode({
'email': _emailController.text.trim(),
'password': _passwordController.text,
}),
);
// final response = await http.post(
// url,
// headers: {'Content-Type': 'application/json'},
// body: jsonEncode({
// 'email': _emailController.text.trim(),
// 'password': _passwordController.text,
// }),
// );
final data = jsonDecode(response.body);
if (response.statusCode == 200) {
// Login berhasil
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(data['message'] ?? 'Login berhasil.')),
);
// Navigasi ke dashboard dengan nama user dan token
await Future.delayed(const Duration(milliseconds: 500));
if (mounted) {
final token = data['data']?['token'] ?? '';
String userName = '';
if (token.isNotEmpty) {
userName = await fetchUserNameByToken(token);
}
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder:
(context) =>
DashboardScreen(userName: userName, token: token),
),
);
}
} else {
// Login gagal
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(data['message'] ?? 'Login gagal.')),
);
}
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Terjadi kesalahan. Coba lagi nanti.')),
);
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
// Future<String> fetchUserNameByToken(String token) async {
// final url = Uri.parse('http://192.168.1.130:8000/api/user-by-token/$token');
// final response = await http.get(
// url,
// headers: {'Authorization': 'Bearer $token', 'Accept': 'application/json'},
// );
// if (response.statusCode == 200) {
// final data = jsonDecode(response.body);
// return data['data']?['name'] ?? '';
// } else {
// return '';
// }
// }
Future<String> fetchUserNameByToken(String token) async {
final url = Uri.parse('${AppConfig.baseUrl}/api/user-by-token/$token');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'X-Platform': 'mobile',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['data']?['name'] ?? '';
} else {
return '';
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
ClipRRect(
borderRadius: BorderRadius.circular(
16,
), // Ubah sesuai keinginan
child: Image.asset(
'assets/logom.png',
height: 80,
fit: BoxFit.contain,
),
),
const SizedBox(height: 12),
const Text(
'Welcome back! Please login to your account',
style: TextStyle(fontSize: 16, color: Colors.black54),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Email',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
),
const SizedBox(height: 8),
TextField(
controller: _emailController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.email_outlined),
hintText: 'Enter your email',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Password',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
TextButton(
onPressed: () {},
child: const Text('Forgot Password?'),
style: TextButton.styleFrom(padding: EdgeInsets.zero),
),
],
),
TextField(
controller: _passwordController,
obscureText: _obscurePassword,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock_outline),
hintText: 'Enter your password',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
),
),
const SizedBox(height: 28),
SizedBox(
height: 48,
child: ElevatedButton(
onPressed: _isLoading ? null : _login,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child:
_isLoading
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Text(
'Login',
style: TextStyle(
fontSize: 18,
color: Colors.white,
),
),
),
),
const SizedBox(height: 24),
// Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// const Text("Don't have an account? "),
// GestureDetector(
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const RegisterScreen(),
// ),
// );
// },
// child: const Text(
// 'Sign up',
// style: TextStyle(
// color: Colors.blue,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
// ],
// ),
// const SizedBox(height: 24),
],
),
),
),
),
);
}
}