Update Saqel Platform: 2026-08-31 01:52:23
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
import '../../core/config/app_config.dart';
|
||||
import '../../core/network/api_client.dart';
|
||||
import '../../core/services/storage_service.dart';
|
||||
import '../models/user_model.dart';
|
||||
import '../models/lesson_model.dart';
|
||||
|
||||
/// Authentication Repository (OTP, National ID, me, logout)
|
||||
class AuthRepository {
|
||||
final ApiClient _api;
|
||||
final StorageService _storage;
|
||||
|
||||
AuthRepository({ApiClient? api, StorageService? storage})
|
||||
: _api = api ?? ApiClient(),
|
||||
_storage = storage ?? StorageService();
|
||||
|
||||
Future<Map<String, dynamic>> requestOtp(String phoneNumber, {String role = 'student'}) async {
|
||||
final res = await _api.post(
|
||||
AppConfig.otpRequestEndpoint,
|
||||
body: {
|
||||
'phone_number': phoneNumber,
|
||||
'role': role,
|
||||
},
|
||||
requiresAuth: false,
|
||||
);
|
||||
return res is Map<String, dynamic> ? res : {};
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> verifyOtp(String phoneNumber, String otp, {String role = 'student'}) async {
|
||||
final res = await _api.post(
|
||||
AppConfig.otpVerifyEndpoint,
|
||||
body: {
|
||||
'phone_number': phoneNumber,
|
||||
'otp': otp,
|
||||
'role': role,
|
||||
},
|
||||
requiresAuth: false,
|
||||
);
|
||||
|
||||
if (res is Map<String, dynamic>) {
|
||||
final data = res['data'];
|
||||
if (data != null && data is Map) {
|
||||
if (data['token'] != null) {
|
||||
final token = data['token'].toString();
|
||||
await _storage.saveToken(token);
|
||||
await _storage.saveActiveRole(role);
|
||||
if (data['user'] != null) {
|
||||
final user = UserModel.fromJson(Map<String, dynamic>.from(data['user']));
|
||||
await _storage.saveUser(user);
|
||||
}
|
||||
} else if (data['identity_token'] != null) {
|
||||
await _storage.saveIdentityToken(data['identity_token'].toString());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> verifyNationalId(String identityToken, String nationalId) async {
|
||||
final res = await _api.post(
|
||||
AppConfig.loginNationalIdEndpoint,
|
||||
body: {
|
||||
'identity_token': identityToken,
|
||||
'national_id': nationalId,
|
||||
},
|
||||
requiresAuth: false,
|
||||
);
|
||||
|
||||
if (res is Map<String, dynamic> && res['data'] != null) {
|
||||
final data = res['data'];
|
||||
if (data['token'] != null) {
|
||||
final token = data['token'].toString();
|
||||
await _storage.saveToken(token);
|
||||
await _storage.saveActiveRole('student');
|
||||
if (data['user'] != null) {
|
||||
final user = UserModel.fromJson(Map<String, dynamic>.from(data['user']));
|
||||
await _storage.saveUser(user);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
throw ApiException('فشل التحقق من الرقم الوطني');
|
||||
}
|
||||
|
||||
Future<UserModel> setupStudentProfile({
|
||||
required String identityToken,
|
||||
required String fullName,
|
||||
required String nationalId,
|
||||
String gradeLevel = 'tawjihi_2008',
|
||||
String stream = 'scientific',
|
||||
}) async {
|
||||
final res = await _api.post(
|
||||
AppConfig.studentProfileSetupEndpoint,
|
||||
body: {
|
||||
'identity_token': identityToken,
|
||||
'full_name': fullName,
|
||||
'national_id': nationalId,
|
||||
'grade_level': gradeLevel,
|
||||
'stream': stream,
|
||||
},
|
||||
requiresAuth: false,
|
||||
);
|
||||
|
||||
if (res is Map<String, dynamic> && res['data'] != null) {
|
||||
final data = res['data'];
|
||||
if (data['token'] != null) {
|
||||
final token = data['token'].toString();
|
||||
await _storage.saveToken(token);
|
||||
await _storage.saveActiveRole('student');
|
||||
}
|
||||
if (data['user'] != null) {
|
||||
final user = UserModel.fromJson(Map<String, dynamic>.from(data['user']));
|
||||
await _storage.saveUser(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
throw ApiException('فشل استكمال فتح الملف الأكاديمي');
|
||||
}
|
||||
|
||||
Future<UserModel?> getMe() async {
|
||||
try {
|
||||
final res = await _api.get(AppConfig.meEndpoint);
|
||||
if (res is Map && res['data'] != null) {
|
||||
final user = UserModel.fromJson(Map<String, dynamic>.from(res['data']));
|
||||
await _storage.saveUser(user);
|
||||
return user;
|
||||
}
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
try {
|
||||
await _api.post(AppConfig.logoutEndpoint);
|
||||
} catch (_) {}
|
||||
await _storage.clearSession();
|
||||
}
|
||||
}
|
||||
|
||||
/// Student Repository (Lessons, Curriculum, Progress)
|
||||
class StudentRepository {
|
||||
final ApiClient _api;
|
||||
|
||||
StudentRepository({ApiClient? api}) : _api = api ?? ApiClient();
|
||||
|
||||
Future<List<LessonModel>> getLessons({String? gradeLevel, String? stream}) async {
|
||||
final queryParams = <String, dynamic>{};
|
||||
if (gradeLevel != null) queryParams['grade_level'] = gradeLevel;
|
||||
if (stream != null) queryParams['stream'] = stream;
|
||||
|
||||
final res = await _api.get(AppConfig.studentLessonsEndpoint, queryParams: queryParams);
|
||||
if (res is Map && res['data'] is List) {
|
||||
return (res['data'] as List)
|
||||
.map((item) => LessonModel.fromJson(Map<String, dynamic>.from(item)))
|
||||
.toList();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// Guardian Repository (Dashboard, Linked Children, Real Progress)
|
||||
class GuardianRepository {
|
||||
final ApiClient _api;
|
||||
|
||||
GuardianRepository({ApiClient? api}) : _api = api ?? ApiClient();
|
||||
|
||||
Future<List<GuardianChildModel>> getDashboardChildren() async {
|
||||
final res = await _api.get(AppConfig.guardianDashboardEndpoint);
|
||||
if (res is Map && res['data'] is List) {
|
||||
return (res['data'] as List)
|
||||
.map((item) => GuardianChildModel.fromJson(Map<String, dynamic>.from(item)))
|
||||
.toList();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user