439 lines
15 KiB
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;
|
|
}
|
|
}
|
|
}
|