Update Saqel Platform: 2026-09-08 18:55:21
This commit is contained in:
@@ -4,6 +4,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../core/config/app_config.dart';
|
||||
import '../../core/utils/app_logger.dart';
|
||||
import '../models/super_admin_models.dart';
|
||||
|
||||
class SuperAdminRepository {
|
||||
@@ -12,7 +13,8 @@ class SuperAdminRepository {
|
||||
|
||||
Future<Map<String, String>> _headers() async {
|
||||
final token = await _storage.read(key: _tokenKey);
|
||||
if (token == null || token.isEmpty) throw StateError('جلسة السوبر أدمن غير متوفرة.');
|
||||
if (token == null || token.isEmpty)
|
||||
throw StateError('جلسة السوبر أدمن غير متوفرة.');
|
||||
return {
|
||||
'Accept': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
@@ -21,34 +23,57 @@ class SuperAdminRepository {
|
||||
}
|
||||
|
||||
Map<String, dynamic> _decode(http.Response response) {
|
||||
final decoded = response.bodyBytes.isEmpty ? <String, dynamic>{} : json.decode(utf8.decode(response.bodyBytes));
|
||||
final data = decoded is Map ? Map<String, dynamic>.from(decoded) : <String, dynamic>{};
|
||||
AppLogger.response(
|
||||
method: response.request?.method ?? 'HTTP',
|
||||
uri: response.request?.url ?? Uri.parse(AppConfig.apiBaseUrl),
|
||||
statusCode: response.statusCode,
|
||||
body: response.body,
|
||||
);
|
||||
final decoded = response.bodyBytes.isEmpty
|
||||
? <String, dynamic>{}
|
||||
: json.decode(utf8.decode(response.bodyBytes));
|
||||
final data = decoded is Map
|
||||
? Map<String, dynamic>.from(decoded)
|
||||
: <String, dynamic>{};
|
||||
if (response.statusCode < 200 || response.statusCode >= 300) {
|
||||
throw StateError(data['message']?.toString() ?? 'فشل طلب الخادم (${response.statusCode}).');
|
||||
final error = StateError(data['message']?.toString() ??
|
||||
'فشل طلب الخادم (${response.statusCode}).');
|
||||
AppLogger.error('Super-admin API request failed', error);
|
||||
throw error;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<void> requestOtp(String phone) async {
|
||||
final response = await http.post(
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/auth/otp/request'),
|
||||
headers: const {'Accept': 'application/json', 'Content-Type': 'application/json'},
|
||||
body: json.encode({'phone_number': phone, 'role': 'super_admin'}),
|
||||
).timeout(const Duration(seconds: 30));
|
||||
final response = await http
|
||||
.post(
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/auth/otp/request'),
|
||||
headers: const {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: json.encode({'phone_number': phone, 'role': 'super_admin'}),
|
||||
)
|
||||
.timeout(const Duration(seconds: 30));
|
||||
_decode(response);
|
||||
}
|
||||
|
||||
Future<void> verifyOtp(String phone, String otp) async {
|
||||
final response = await http.post(
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/auth/otp/verify'),
|
||||
headers: const {'Accept': 'application/json', 'Content-Type': 'application/json'},
|
||||
body: json.encode({
|
||||
'phone_number': phone,
|
||||
'otp': otp,
|
||||
'role': 'super_admin',
|
||||
'device_fingerprint': 'saqel_super_admin_flutter',
|
||||
}),
|
||||
).timeout(const Duration(seconds: 30));
|
||||
final response = await http
|
||||
.post(
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/auth/otp/verify'),
|
||||
headers: const {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: json.encode({
|
||||
'phone_number': phone,
|
||||
'otp': otp,
|
||||
'role': 'super_admin',
|
||||
'device_fingerprint': 'saqel_super_admin_flutter',
|
||||
}),
|
||||
)
|
||||
.timeout(const Duration(seconds: 30));
|
||||
final body = _decode(response);
|
||||
final payload = Map<String, dynamic>.from(body['data'] as Map? ?? const {});
|
||||
final token = payload['token']?.toString() ?? '';
|
||||
@@ -58,10 +83,12 @@ class SuperAdminRepository {
|
||||
|
||||
Future<bool> hasValidSession() async {
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/auth/me'),
|
||||
headers: await _headers(),
|
||||
).timeout(const Duration(seconds: 15));
|
||||
final response = await http
|
||||
.get(
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/auth/me'),
|
||||
headers: await _headers(),
|
||||
)
|
||||
.timeout(const Duration(seconds: 15));
|
||||
_decode(response);
|
||||
return true;
|
||||
} catch (_) {
|
||||
@@ -70,48 +97,82 @@ class SuperAdminRepository {
|
||||
}
|
||||
|
||||
Future<dynamic> _get(String path) async {
|
||||
final response = await http.get(Uri.parse('${AppConfig.apiBaseUrl}$path'), headers: await _headers())
|
||||
final response = await http
|
||||
.get(Uri.parse('${AppConfig.apiBaseUrl}$path'),
|
||||
headers: await _headers())
|
||||
.timeout(const Duration(seconds: 20));
|
||||
return _decode(response)['data'];
|
||||
}
|
||||
|
||||
Future<dynamic> _post(String path, Map<String, dynamic> body) async {
|
||||
final response = await http.post(Uri.parse('${AppConfig.apiBaseUrl}$path'), headers: {
|
||||
...await _headers(), 'Content-Type': 'application/json',
|
||||
}, body: json.encode(body)).timeout(const Duration(seconds: 20));
|
||||
final response = await http
|
||||
.post(Uri.parse('${AppConfig.apiBaseUrl}$path'),
|
||||
headers: {
|
||||
...await _headers(),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(body))
|
||||
.timeout(const Duration(seconds: 20));
|
||||
return _decode(response)['data'];
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> getSchools() async =>
|
||||
(await _get('/api/super-admin/schools') as List).map((e) => Map<String, dynamic>.from(e as Map)).toList();
|
||||
(await _get('/api/super-admin/schools') as List)
|
||||
.map((e) => Map<String, dynamic>.from(e as Map))
|
||||
.toList();
|
||||
|
||||
Future<List<Map<String, dynamic>>> getStaff() async =>
|
||||
(await _get('/api/super-admin/staff') as List).map((e) => Map<String, dynamic>.from(e as Map)).toList();
|
||||
(await _get('/api/super-admin/staff') as List)
|
||||
.map((e) => Map<String, dynamic>.from(e as Map))
|
||||
.toList();
|
||||
|
||||
Future<void> saveSchool(Map<String, dynamic> body) async {
|
||||
await _post('/api/super-admin/schools/save', body);
|
||||
}
|
||||
|
||||
Future<void> toggleSchool(int id) async {
|
||||
await _post('/api/super-admin/schools/toggle', {'id': id});
|
||||
}
|
||||
|
||||
Future<void> saveStaff(Map<String, dynamic> body) async {
|
||||
await _post('/api/super-admin/staff/save', body);
|
||||
}
|
||||
|
||||
Future<void> toggleStaff(int id) async {
|
||||
await _post('/api/super-admin/staff/toggle', {'id': id});
|
||||
}
|
||||
|
||||
Future<void> saveSchool(Map<String, dynamic> body) async { await _post('/api/super-admin/schools/save', body); }
|
||||
Future<void> toggleSchool(int id) async { await _post('/api/super-admin/schools/toggle', {'id': id}); }
|
||||
Future<void> saveStaff(Map<String, dynamic> body) async { await _post('/api/super-admin/staff/save', body); }
|
||||
Future<void> toggleStaff(int id) async { await _post('/api/super-admin/staff/toggle', {'id': id}); }
|
||||
Future<List<Map<String, dynamic>>> getDirectorates() async =>
|
||||
(await _get('/api/super-admin/directorates') as List).map((e) => Map<String, dynamic>.from(e as Map)).toList();
|
||||
Future<void> saveDirectorate(Map<String, dynamic> body) async { await _post('/api/super-admin/directorates/save', body); }
|
||||
Future<void> toggleDirectorate(int id) async { await _post('/api/super-admin/directorates/toggle', {'id': id}); }
|
||||
(await _get('/api/super-admin/directorates') as List)
|
||||
.map((e) => Map<String, dynamic>.from(e as Map))
|
||||
.toList();
|
||||
Future<void> saveDirectorate(Map<String, dynamic> body) async {
|
||||
await _post('/api/super-admin/directorates/save', body);
|
||||
}
|
||||
|
||||
Future<void> toggleDirectorate(int id) async {
|
||||
await _post('/api/super-admin/directorates/toggle', {'id': id});
|
||||
}
|
||||
|
||||
Future<MacroTelemetryModel> getMacroTelemetry() async =>
|
||||
MacroTelemetryModel.fromJson(Map<String, dynamic>.from(await _get('/api/super-admin/overview') as Map));
|
||||
MacroTelemetryModel.fromJson(Map<String, dynamic>.from(
|
||||
await _get('/api/super-admin/overview') as Map));
|
||||
|
||||
Future<List<AiClusterNodeModel>> getAiClusterNodes() async =>
|
||||
(await _get('/api/super-admin/ai-nodes') as List)
|
||||
.map((item) => AiClusterNodeModel.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.map((item) => AiClusterNodeModel.fromJson(
|
||||
Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
|
||||
Future<List<PayoutQueueItemModel>> getPayoutQueue() async =>
|
||||
(await _get('/api/super-admin/payouts') as List)
|
||||
.map((item) => PayoutQueueItemModel.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.map((item) => PayoutQueueItemModel.fromJson(
|
||||
Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
|
||||
Future<List<SecurityIntegrityAlertModel>> getSecurityAlerts() async =>
|
||||
(await _get('/api/super-admin/security-alerts') as List)
|
||||
.map((item) => SecurityIntegrityAlertModel.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.map((item) => SecurityIntegrityAlertModel.fromJson(
|
||||
Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user