MIF_E31221388/salonbooking/lib/page/login_page.dart

184 lines
6.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
class LoginPage extends StatefulWidget {
final Function(String token, Map user) onLoginSuccess;
LoginPage({required this.onLoginSuccess});
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
final _email = TextEditingController();
final _password = TextEditingController();
bool _obscurePassword = true;
Future<void> login() async {
if (!_formKey.currentState!.validate()) return;
final response = await http.post(
Uri.parse('http://angeliasalon.my.id/api/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': _email.text.trim(),
'password': _password.text,
}),
);
if (response.statusCode == 200) {
final body = jsonDecode(response.body);
final user = body['user'];
// ✅ Cek hanya jika user adalah karyawan
if (user['role'] == 'karyawan' && user['is_approved'] == 0) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Akun Anda belum disetujui oleh pemilik.'),
backgroundColor: Colors.orange,
),
);
return;
}
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', body['access_token']);
widget.onLoginSuccess(body['access_token'], body['user']);
} else {
try {
final body = jsonDecode(response.body);
String message = 'Login gagal.';
if (body['message'] != null) {
message = body['message'];
} else if (response.statusCode == 401) {
message = 'Email atau password salah';
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), backgroundColor: Colors.red),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Terjadi kesalahan. Silakan coba login kembali.'),
backgroundColor: Colors.red,
),
);
}
}
}
@override
Widget build(BuildContext context) {
final primaryColor = const Color(0xFFF06292);
final backgroundColor = const Color(0xFFFFF6F9);
final inputFillColor = const Color(0xFFFADADD);
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
title: const Text('Login'),
backgroundColor: const Color(0xFFF48FB1),
elevation: 2,
),
body: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 24),
child: Form(
key: _formKey,
child: Column(
children: [
Text(
'Welcome Back',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: primaryColor,
),
),
const SizedBox(height: 32),
TextFormField(
controller: _email,
decoration: InputDecoration(
labelText: 'Email',
filled: true,
fillColor: inputFillColor,
prefixIcon: const Icon(Icons.email, color: Colors.pinkAccent),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide.none,
),
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) return 'Please enter your email';
final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
if (!emailRegex.hasMatch(value)) return 'Please enter a valid email';
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _password,
decoration: InputDecoration(
labelText: 'Password',
filled: true,
fillColor: inputFillColor,
prefixIcon: const Icon(Icons.lock, color: Colors.pinkAccent),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword ? Icons.visibility_off : Icons.visibility,
color: Colors.pinkAccent,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide.none,
),
),
obscureText: _obscurePassword,
validator: (value) =>
(value == null || value.isEmpty) ? 'Please enter your password' : null,
),
const SizedBox(height: 32),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: login,
style: ElevatedButton.styleFrom(
backgroundColor: primaryColor,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
textStyle: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
elevation: 5,
),
child: const Text('Login'),
),
),
],
),
),
),
);
}
}