NIM_E31222534/Androidnya/lib/services/auth_service.dart

439 lines
15 KiB
Dart

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:async';
import 'api_service.dart';
import 'dart:math';
class AuthService {
// Gunakan ApiService untuk request
final ApiService _apiService = ApiService();
// Singleton pattern
static final AuthService _instance = AuthService._internal();
factory AuthService() {
return _instance;
}
AuthService._internal();
// Fungsi untuk login
Future<Map<String, dynamic>> login({
required String nik,
required String password,
}) async {
try {
print('Memulai proses login...');
// Login tidak menggunakan token, jadi kita gunakan http langsung
final response = await http.post(
Uri.parse('${ApiService.baseUrl}/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'nik': nik,
'password': password,
}),
);
final data = jsonDecode(response.body);
print('Response login: $data');
print('Response status code: ${response.statusCode}');
print('Response body raw: ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300 &&
(data['status'] == 'success' || data['success'] == true)) {
print('Login berhasil');
print('Full response: $data');
print('Full response keys: ${data.keys.toList()}');
// Mencari token di berbagai kemungkinan lokasi dalam respons
String? token;
// Periksa berbagai kemungkinan kunci token
if (data['token'] != null) {
token = data['token'];
print('Token ditemukan di kunci: token');
} else if (data['access_token'] != null) {
token = data['access_token'];
print('Token ditemukan di kunci: access_token');
} else if (data['bearer_token'] != null) {
token = data['bearer_token'];
print('Token ditemukan di kunci: bearer_token');
} else if (data['data'] != null && data['data']['token'] != null) {
token = data['data']['token'];
print('Token ditemukan di kunci: data.token');
}
print('Token ditemukan: ${token != null ? 'Ya' : 'Tidak'}');
// Pastikan token disimpan di SharedPreferences dan ApiService
if (token != null) {
// Simpan token menggunakan ApiService
await _apiService.setToken(token);
print('Token berhasil disimpan: ${token.substring(0, min(10, token.length))}...');
} else {
print('PERINGATAN: Tidak ada token dalam respons login!');
// Tanggal/waktu lokal sebagai tanda pengenal unik
String localIdentifier = DateTime.now().toIso8601String();
await _apiService.setToken('local_token_$localIdentifier');
print('Token lokal dibuat sebagai fallback');
}
final prefs = await SharedPreferences.getInstance();
// Navigasi di response JSON berdasarkan struktur
Map<String, dynamic> penggunaData;
if (data['pengguna'] != null) {
penggunaData = data['pengguna'];
} else if (data['user'] != null) {
penggunaData = data['user'];
} else if (data['data'] != null && data['data']['user'] != null) {
penggunaData = data['data']['user'];
} else if (data['data'] != null && data['data']['pengguna'] != null) {
penggunaData = data['data']['pengguna'];
} else {
print('PERINGATAN: Struktur respons tidak sesuai yang diharapkan');
print('Membuat data pengguna minimal');
penggunaData = {
'nik': nik,
'id': 0, // Default ID yang akan diganti nanti
'nama': 'User', // Default nama
};
}
print('Data pengguna dari API: $penggunaData');
// Store user data from API
await prefs.setString('nik', penggunaData['nik'] ?? nik);
await prefs.setString('nama_ibu', penggunaData['nama'] ?? 'User');
// Simpan user_id sebagai integer untuk digunakan di fitur lain
int userId;
if (penggunaData['id'] is String) {
userId = int.parse(penggunaData['id']);
} else if (penggunaData['id'] is int) {
userId = penggunaData['id'];
} else {
print('PERINGATAN: ID tidak ditemukan atau tidak valid, menggunakan 0');
userId = 0; // Nilai default jika tidak ada ID
}
await prefs.setInt('user_id', userId);
print('User ID yang disimpan: $userId');
// Simpan email dan no_telp jika tersedia
if (penggunaData['email'] != null) {
await prefs.setString('email', penggunaData['email']);
print('Email saved: ${penggunaData['email']}');
}
if (penggunaData['no_telp'] != null) {
await prefs.setString('no_telp', penggunaData['no_telp']);
print('Phone saved: ${penggunaData['no_telp']}');
} else if (penggunaData['telepon'] != null) {
await prefs.setString('no_telp', penggunaData['telepon']);
print('Phone saved (from telepon field): ${penggunaData['telepon']}');
}
if (penggunaData['alamat'] != null) {
await prefs.setString('alamat', penggunaData['alamat']);
}
if (penggunaData['usia'] != null) {
await prefs.setInt('usia', penggunaData['usia']);
}
// Verifikasi data tersimpan
final verifyUserId = prefs.getInt('user_id');
final verifyEmail = prefs.getString('email');
final verifyPhone = prefs.getString('no_telp');
final verifyToken = prefs.getString('token');
print('Verifikasi data tersimpan:');
print('- User ID: $verifyUserId');
print('- Email: $verifyEmail');
print('- Phone: $verifyPhone');
print('- Token tersimpan: ${verifyToken != null ? 'Ya' : 'Tidak'}');
return {
'success': true,
'message': data['message'] ?? 'Login berhasil',
'data': penggunaData,
};
} else {
print('Login gagal: ${data['message'] ?? 'NIK atau password salah'}');
return {
'success': false,
'message': data['message'] ?? 'NIK atau password salah',
};
}
} catch (e) {
print('Error during login: $e');
return {
'success': false,
'message': 'Terjadi kesalahan: $e',
};
}
}
// Fungsi untuk register
Future<Map<String, dynamic>> register({
required String nik,
required String nama,
required String alamat,
required String noTelp,
required String password,
String? email,
}) async {
try {
print('Memulai proses pendaftaran...');
// Debug: Tampilkan URL yang digunakan
print('API URL: ${ApiService.baseUrl}/register');
// Register tidak menggunakan token, jadi kita gunakan http langsung
final response = await http.post(
Uri.parse('${ApiService.baseUrl}/register'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'nik': nik,
'nama': nama,
'alamat': alamat,
'no_telp': noTelp,
'password': password,
'email': email,
'role': 'parent', // Default role
}),
);
// Debug: Tampilkan status code dan response body
print('Status Code: ${response.statusCode}');
print('Response headers: ${response.headers}');
print('Response body preview: ${response.body.substring(0, min(200, response.body.length))}...');
// Cek apakah response berupa JSON atau HTML
if (response.body.trim().startsWith('{') || response.body.trim().startsWith('[')) {
// Response adalah JSON
final data = jsonDecode(response.body);
if (response.statusCode == 200 || response.statusCode == 201) {
print('Pendaftaran berhasil');
// Simpan data pendaftaran ke SharedPreferences
final prefs = await SharedPreferences.getInstance();
// Save registration data
await prefs.setString('nik', nik);
await prefs.setString('nama_ibu', nama);
await prefs.setString('alamat', alamat);
await prefs.setString('no_telp', noTelp);
if (email != null && email.isNotEmpty) {
await prefs.setString('email', email);
print('Email saved from registration: $email');
}
// Jika ada ID pengguna di respons, simpan juga
if (data['id'] != null) {
await prefs.setInt('user_id', data['id']);
} else if (data['user_id'] != null) {
await prefs.setInt('user_id', data['user_id']);
} else if (data['pengguna'] != null && data['pengguna']['id'] != null) {
await prefs.setInt('user_id', data['pengguna']['id']);
}
print('Registration data saved to SharedPreferences:');
print('NIK: $nik');
print('Nama: $nama');
print('No Telp: $noTelp');
print('Email: $email');
return {
'success': true,
'message': data['message'] ?? 'Pendaftaran berhasil',
};
} else {
return {
'success': false,
'message': data['message'] ?? 'Pendaftaran gagal',
'errors': data['errors'],
'statusCode': response.statusCode
};
}
} else {
// Response bukan JSON (kemungkinan HTML error page)
return {
'success': false,
'message': 'Server mengembalikan format yang tidak valid (bukan JSON)',
'statusCode': response.statusCode,
'rawResponse': response.body.length > 100
? '${response.body.substring(0, 100)}...'
: response.body
};
}
} catch (e) {
print('Error during registration: $e');
return {
'success': false,
'message': 'Terjadi kesalahan: $e',
};
}
}
// Fungsi untuk mendapatkan data user yang sedang login
Future<Map<String, dynamic>> getCurrentUser() async {
try {
final prefs = await SharedPreferences.getInstance();
final nik = prefs.getString('nik');
final userId = prefs.getInt('user_id');
if (nik == null) {
return {
'success': false,
'message': 'User belum login',
};
}
// Baca data lokal terlebih dahulu
final localUserData = {
'nik': nik,
'id': userId,
'nama': prefs.getString('nama_ibu') ?? 'User',
'alamat': prefs.getString('alamat') ?? '',
'usia': prefs.getInt('usia') ?? 0,
'email': prefs.getString('email') ?? '',
'no_telp': prefs.getString('no_telp') ?? '',
};
print('Local data from SharedPreferences:');
print('Email: ${localUserData['email']}');
print('Phone: ${localUserData['no_telp']}');
try {
// Gunakan endpoint yang benar (user, user/profile, atau me)
print('Getting user data with token authentication');
// Coba beberapa endpoint yang mungkin ada di Laravel API
Map<String, dynamic> data = {};
bool apiSuccess = false;
try {
data = await _apiService.get('user');
apiSuccess = true;
} catch (e) {
print('Endpoint "user" failed: $e');
try {
data = await _apiService.get('me');
apiSuccess = true;
} catch (e) {
print('Endpoint "me" failed: $e');
try {
data = await _apiService.get('user/profile');
apiSuccess = true;
} catch (e) {
print('Endpoint "user/profile" failed: $e');
}
}
}
if (!apiSuccess || data.isEmpty) {
print('No API endpoint worked, using local data');
// Jika API tidak mengembalikan data, gunakan data lokal
return {
'success': true,
'message': 'Menggunakan data lokal',
'data': localUserData
};
}
// Debug: Check response structure
print('API response structure for getCurrentUser:');
print('Keys: ${data.keys.toList()}');
// Berdasarkan struktur response API
Map<String, dynamic> userData = data;
if (data['user'] != null) {
userData = data['user'];
} else if (data['pengguna'] != null) {
userData = data['pengguna'];
} else if (data['data'] != null) {
userData = data['data'];
}
// Gabungkan data API dengan data lokal jika ada field yang kosong di API
if (userData['email'] == null && localUserData['email'] != null && localUserData['email'] != '') {
userData['email'] = localUserData['email'];
}
if ((userData['no_telp'] == null && userData['telepon'] == null) &&
localUserData['no_telp'] != null && localUserData['no_telp'] != '') {
userData['no_telp'] = localUserData['no_telp'];
}
return {
'success': true,
'data': userData,
};
} catch (e) {
print('Error in getCurrentUser: $e');
// Jika API error, gunakan data lokal
return {
'success': true,
'message': 'Menggunakan data lokal karena API error: $e',
'data': localUserData
};
}
} catch (e) {
print('Error getting current user: $e');
return {
'success': false,
'message': 'Terjadi kesalahan: $e',
};
}
}
// Fungsi untuk cek status login
Future<bool> isLoggedIn() async {
try {
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('token');
return token != null;
} catch (e) {
print('Error checking login status: $e');
return false;
}
}
// Fungsi logout
Future<bool> logout() async {
try {
try {
// Gunakan ApiService untuk logout
await _apiService.post('logout', {});
print('User logged out successfully from API');
} catch (e) {
print('API logout failed, but will clear local data: $e');
}
// Hanya hapus token autentikasi, bukan semua data
final prefs = await SharedPreferences.getInstance();
await prefs.remove('token');
return true;
} catch (e) {
print('Logout error: $e');
// Tetap hapus token meskipun terjadi error
try {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('token');
} catch (clearError) {
print('Error removing token: $clearError');
}
return true;
}
}
}