FarisaRahmaSari_E31222327/BBS/lib/services/auth_service.dart

219 lines
6.1 KiB
Dart

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:qyuota/config/api_config.dart';
import 'dart:io';
import 'package:flutter/material.dart';
class AuthService {
static const String tokenKey = 'auth_token';
static const String userKey = 'user_data';
static final AuthService _instance = AuthService._internal();
factory AuthService() => _instance;
AuthService._internal();
Future<Map<String, dynamic>?> login(String email, String password) async {
try {
print('Login attempt with: $email'); // Debug log
final response = await http.post(
Uri.parse(ApiConfig.login),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'email': email,
'password': password,
}),
);
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
await _saveAuthData(
data['access_token'],
data['user'],
);
final prefs = await SharedPreferences.getInstance();
await prefs.setString('user_id', data['user']['id'].toString());
return data;
}
final errorData = jsonDecode(response.body);
throw Exception(errorData['message'] ?? errorData['error'] ?? 'Login failed');
} catch (e) {
print('Login error details: $e');
if (e is HandshakeException) {
throw Exception('Tidak dapat terhubung ke server. Pastikan server berjalan.');
}
rethrow;
}
}
Future<void> logout() async {
try {
final token = await getToken();
if (token != null) {
await http.post(
Uri.parse(ApiConfig.logout),
headers: ApiConfig.authHeaders(token),
);
}
} catch (e) {
print('Logout error: $e');
} finally {
await _clearAuthData();
}
}
Future<Map<String, dynamic>?> refreshToken() async {
try {
final token = await getToken();
if (token == null) throw Exception('No token found');
final response = await http.post(
Uri.parse(ApiConfig.refresh),
headers: ApiConfig.authHeaders(token),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
await _saveAuthData(
data['access_token'],
data['user'],
);
return data;
}
throw Exception('Token refresh failed');
} catch (e) {
print('Refresh token error: $e');
await _clearAuthData();
rethrow;
}
}
Future<void> _saveAuthData(
String token,
Map<String, dynamic> userData,
) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(tokenKey, token);
await prefs.setString(userKey, jsonEncode(userData));
}
Future<void> _clearAuthData() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(tokenKey);
await prefs.remove(userKey);
}
Future<String?> getToken() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(tokenKey);
}
Future<String?> getUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('user_id');
}
Future<Map<String, dynamic>?> getUserData() async {
final prefs = await SharedPreferences.getInstance();
final userStr = prefs.getString(userKey);
if (userStr != null) {
return jsonDecode(userStr);
}
return null;
}
Future<bool> isLoggedIn() async {
final token = await getToken();
return token != null;
}
Future<bool> checkSession(BuildContext context) async {
final token = await getToken();
if (token == null) {
// Jika tidak ada token, arahkan ke halaman login
Navigator.of(context).pushNamedAndRemoveUntil('/login', (route) => false);
return false;
}
try {
final response = await http.get(
Uri.parse(ApiConfig.profile),
headers: ApiConfig.authHeaders(token),
);
if (response.statusCode == 401) {
// Token tidak valid atau expired
await _clearAuthData();
Navigator.of(context).pushNamedAndRemoveUntil('/login', (route) => false);
return false;
}
return true;
} catch (e) {
print('Error checking session: $e');
return false;
}
}
Future<void> changePassword({
required String currentPassword,
required String newPassword,
required String confirmPassword,
}) async {
try {
final token = await getToken();
if (token == null) {
throw Exception('Token tidak ditemukan');
}
print('Attempting to change password...');
print('Endpoint: ${ApiConfig.changePassword}');
final response = await http.post(
Uri.parse(ApiConfig.changePassword),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'current_password': currentPassword,
'new_password': newPassword,
'confirm_password': confirmPassword,
}),
);
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
if (response.statusCode == 200) {
return;
}
final data = jsonDecode(response.body);
if (data['errors'] != null) {
final errors = data['errors'] as Map<String, dynamic>;
final firstError = errors.values.first;
if (firstError is List && firstError.isNotEmpty) {
throw Exception(firstError[0]);
}
throw Exception(firstError.toString());
}
throw Exception(data['message'] ?? 'Gagal mengubah password');
} catch (e) {
print('Change password error: $e');
if (e is SocketException) {
throw Exception('Tidak dapat terhubung ke server. Periksa koneksi internet Anda.');
}
rethrow;
}
}
}