Update: 2026-07-12 05:40:28
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
// transit_admin_controller.dart — تحكم شاشات مواصلاتي (لوحة إدارة سيرو)
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'transit_admin_models.dart';
|
||||
import 'transit_admin_service.dart';
|
||||
|
||||
class TransitAdminController extends GetxController {
|
||||
bool isLoadingList = false;
|
||||
List<TransitOrgSummary> orgs = [];
|
||||
String? filterCountry;
|
||||
String? filterType;
|
||||
String? filterStatus;
|
||||
String searchQuery = '';
|
||||
|
||||
bool isLoadingDetails = false;
|
||||
TransitOrgDetails? selectedOrgDetails;
|
||||
|
||||
bool isCreating = false;
|
||||
|
||||
// ── مشرفو المؤسسة ────────────────────────────────────────────
|
||||
bool isLoadingAdmins = false;
|
||||
List<Map<String, dynamic>> orgAdmins = [];
|
||||
bool isSavingAdmin = false;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
fetchOrgs();
|
||||
}
|
||||
|
||||
Future<void> fetchOrgs() async {
|
||||
isLoadingList = true;
|
||||
update();
|
||||
|
||||
final res = await TransitAdminService.listOrgs(
|
||||
country: filterCountry,
|
||||
type: filterType,
|
||||
contractStatus: filterStatus,
|
||||
search: searchQuery,
|
||||
);
|
||||
if (res.success) orgs = res.data ?? [];
|
||||
isLoadingList = false;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> loadOrgDetails(int orgId) async {
|
||||
isLoadingDetails = true;
|
||||
selectedOrgDetails = null;
|
||||
update();
|
||||
|
||||
final res = await TransitAdminService.getOrgDetails(orgId);
|
||||
if (res.success) selectedOrgDetails = res.data;
|
||||
isLoadingDetails = false;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<bool> createOrg({
|
||||
required String type,
|
||||
required String country,
|
||||
required String city,
|
||||
required String nameAr,
|
||||
required String nameEn,
|
||||
required String adminName,
|
||||
required String adminPhone,
|
||||
}) async {
|
||||
isCreating = true;
|
||||
update();
|
||||
|
||||
final res = await TransitAdminService.createOrg(
|
||||
type: type,
|
||||
country: country,
|
||||
city: city,
|
||||
nameAr: nameAr,
|
||||
nameEn: nameEn,
|
||||
adminName: adminName,
|
||||
adminPhone: adminPhone,
|
||||
);
|
||||
|
||||
isCreating = false;
|
||||
update();
|
||||
|
||||
if (res.success) {
|
||||
await fetchOrgs();
|
||||
return true;
|
||||
}
|
||||
Get.snackbar('مواصلاتي', res.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> fetchOrgAdmins(int orgId) async {
|
||||
isLoadingAdmins = true;
|
||||
update();
|
||||
final res = await TransitAdminService.listOrgAdmins(orgId);
|
||||
if (res.success) orgAdmins = res.data ?? [];
|
||||
isLoadingAdmins = false;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<bool> addOrgAdmin({
|
||||
required int orgId,
|
||||
required String name,
|
||||
required String phone,
|
||||
required String role,
|
||||
}) async {
|
||||
isSavingAdmin = true;
|
||||
update();
|
||||
|
||||
final res = await TransitAdminService.addOrgAdmin(
|
||||
orgId: orgId,
|
||||
name: name,
|
||||
phone: phone,
|
||||
role: role,
|
||||
);
|
||||
|
||||
isSavingAdmin = false;
|
||||
update();
|
||||
|
||||
if (res.success) {
|
||||
await fetchOrgAdmins(orgId);
|
||||
return true;
|
||||
}
|
||||
Get.snackbar('مواصلاتي', res.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> toggleOrgAdmin(int orgId, int adminId, bool isActive) async {
|
||||
final res = await TransitAdminService.toggleOrgAdmin(adminId: adminId, isActive: isActive);
|
||||
if (res.success) {
|
||||
await fetchOrgAdmins(orgId);
|
||||
} else {
|
||||
Get.snackbar('مواصلاتي', res.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// transit_admin_models.dart — نماذج بيانات مواصلاتي (لوحة إدارة سيرو)
|
||||
|
||||
class TransitOrgSummary {
|
||||
final int id;
|
||||
final String type;
|
||||
final String country;
|
||||
final String city;
|
||||
final String nameAr;
|
||||
final String nameEn;
|
||||
final String? logoUrl;
|
||||
final String contractStatus;
|
||||
final String? trialEndsAt;
|
||||
final int driversCount;
|
||||
final int vehiclesCount;
|
||||
final int activeRoutes;
|
||||
final int activeEnrollments;
|
||||
|
||||
TransitOrgSummary({
|
||||
required this.id,
|
||||
required this.type,
|
||||
required this.country,
|
||||
required this.city,
|
||||
required this.nameAr,
|
||||
required this.nameEn,
|
||||
required this.contractStatus,
|
||||
this.logoUrl,
|
||||
this.trialEndsAt,
|
||||
this.driversCount = 0,
|
||||
this.vehiclesCount = 0,
|
||||
this.activeRoutes = 0,
|
||||
this.activeEnrollments = 0,
|
||||
});
|
||||
|
||||
factory TransitOrgSummary.fromJson(Map<String, dynamic> j) => TransitOrgSummary(
|
||||
id: int.tryParse(j['id'].toString()) ?? 0,
|
||||
type: j['type']?.toString() ?? '',
|
||||
country: j['country']?.toString() ?? '',
|
||||
city: j['city']?.toString() ?? '',
|
||||
nameAr: j['name_ar']?.toString() ?? '',
|
||||
nameEn: j['name_en']?.toString() ?? '',
|
||||
logoUrl: j['logo_url']?.toString(),
|
||||
contractStatus: j['contract_status']?.toString() ?? '',
|
||||
trialEndsAt: j['trial_ends_at']?.toString(),
|
||||
driversCount: int.tryParse(j['drivers_count']?.toString() ?? '0') ?? 0,
|
||||
vehiclesCount: int.tryParse(j['vehicles_count']?.toString() ?? '0') ?? 0,
|
||||
activeRoutes: int.tryParse(j['active_routes']?.toString() ?? '0') ?? 0,
|
||||
activeEnrollments: int.tryParse(j['active_enrollments']?.toString() ?? '0') ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
class TransitOrgDetails {
|
||||
final Map<String, dynamic> org;
|
||||
final Map<String, dynamic> counts;
|
||||
final Map<String, dynamic> trips;
|
||||
final List<dynamic> routes;
|
||||
|
||||
TransitOrgDetails({
|
||||
required this.org,
|
||||
required this.counts,
|
||||
required this.trips,
|
||||
required this.routes,
|
||||
});
|
||||
|
||||
factory TransitOrgDetails.fromJson(Map<String, dynamic> j) => TransitOrgDetails(
|
||||
org: Map<String, dynamic>.from(j['org'] ?? {}),
|
||||
counts: Map<String, dynamic>.from(j['counts'] ?? {}),
|
||||
trips: Map<String, dynamic>.from(j['trips'] ?? {}),
|
||||
routes: (j['routes'] is List) ? List<dynamic>.from(j['routes']) : [],
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// transit_admin_service.dart — طبقة الاتصال بـ backend/Admin/transit (لوحة إدارة سيرو)
|
||||
import '../functions/crud.dart';
|
||||
import '../../constant/links.dart';
|
||||
import 'transit_admin_models.dart';
|
||||
|
||||
class TransitApiResult<T> {
|
||||
final bool success;
|
||||
final T? data;
|
||||
final String message;
|
||||
TransitApiResult(this.success, this.data, this.message);
|
||||
}
|
||||
|
||||
class TransitAdminService {
|
||||
static String get _base => '${AppLink.server}/Admin/transit';
|
||||
|
||||
static String _errMsg(dynamic res) {
|
||||
if (res == 'no_internet') return 'تحقق من اتصالك بالإنترنت';
|
||||
if (res == 'token_expired') return 'انتهت الجلسة، حاول مجدداً';
|
||||
if (res is Map && res['message'] is String) return res['message'];
|
||||
return 'حدث خطأ، حاول مجدداً';
|
||||
}
|
||||
|
||||
static Future<TransitApiResult<List<TransitOrgSummary>>> listOrgs({
|
||||
String? country,
|
||||
String? type,
|
||||
String? contractStatus,
|
||||
String? search,
|
||||
}) async {
|
||||
final payload = <String, dynamic>{};
|
||||
if (country != null && country.isNotEmpty) payload['country'] = country;
|
||||
if (type != null && type.isNotEmpty) payload['type'] = type;
|
||||
if (contractStatus != null && contractStatus.isNotEmpty) {
|
||||
payload['contract_status'] = contractStatus;
|
||||
}
|
||||
if (search != null && search.isNotEmpty) payload['search'] = search;
|
||||
|
||||
final res = await CRUD().post(link: '$_base/org/list.php', payload: payload);
|
||||
|
||||
if (res is Map && res['status'] == 'success' && res['message'] is Map) {
|
||||
final msg = res['message'] as Map;
|
||||
final list = (msg['orgs'] is List)
|
||||
? (msg['orgs'] as List)
|
||||
.map((o) => TransitOrgSummary.fromJson(Map<String, dynamic>.from(o)))
|
||||
.toList()
|
||||
: <TransitOrgSummary>[];
|
||||
return TransitApiResult(true, list, 'ok');
|
||||
}
|
||||
return TransitApiResult(false, null, _errMsg(res));
|
||||
}
|
||||
|
||||
static Future<TransitApiResult<TransitOrgDetails>> getOrgDetails(int orgId) async {
|
||||
final res = await CRUD().post(
|
||||
link: '$_base/org/details.php',
|
||||
payload: {'org_id': orgId.toString()},
|
||||
);
|
||||
if (res is Map && res['status'] == 'success' && res['message'] is Map) {
|
||||
return TransitApiResult(
|
||||
true, TransitOrgDetails.fromJson(Map<String, dynamic>.from(res['message'])), 'ok');
|
||||
}
|
||||
return TransitApiResult(false, null, _errMsg(res));
|
||||
}
|
||||
|
||||
static Future<TransitApiResult<Map<String, dynamic>>> createOrg({
|
||||
required String type,
|
||||
required String country,
|
||||
required String city,
|
||||
required String nameAr,
|
||||
required String nameEn,
|
||||
required String adminName,
|
||||
required String adminPhone,
|
||||
String? contactPhone,
|
||||
String? contactEmail,
|
||||
String? website,
|
||||
}) async {
|
||||
final res = await CRUD().post(link: '$_base/org/create.php', payload: {
|
||||
'type': type,
|
||||
'country': country,
|
||||
'city': city,
|
||||
'name_ar': nameAr,
|
||||
'name_en': nameEn,
|
||||
'admin_name': adminName,
|
||||
'admin_phone': adminPhone,
|
||||
if (contactPhone != null) 'contact_phone': contactPhone,
|
||||
if (contactEmail != null) 'contact_email': contactEmail,
|
||||
if (website != null) 'website': website,
|
||||
});
|
||||
|
||||
if (res is Map && res['status'] == 'success') {
|
||||
return TransitApiResult(true, Map<String, dynamic>.from(res['message'] ?? {}), 'ok');
|
||||
}
|
||||
return TransitApiResult(false, null, _errMsg(res));
|
||||
}
|
||||
|
||||
// ── مشرفو المؤسسة ────────────────────────────────────────────
|
||||
|
||||
static Future<TransitApiResult<List<Map<String, dynamic>>>> listOrgAdmins(
|
||||
int orgId) async {
|
||||
final res = await CRUD().post(
|
||||
link: '$_base/org/admins_list.php',
|
||||
payload: {'org_id': orgId.toString()},
|
||||
);
|
||||
if (res is Map && res['status'] == 'success' && res['message'] is Map) {
|
||||
final msg = res['message'] as Map;
|
||||
final list = (msg['admins'] is List)
|
||||
? (msg['admins'] as List).map((a) => Map<String, dynamic>.from(a)).toList()
|
||||
: <Map<String, dynamic>>[];
|
||||
return TransitApiResult(true, list, 'ok');
|
||||
}
|
||||
return TransitApiResult(false, null, _errMsg(res));
|
||||
}
|
||||
|
||||
static Future<TransitApiResult<void>> addOrgAdmin({
|
||||
required int orgId,
|
||||
required String name,
|
||||
required String phone,
|
||||
required String role,
|
||||
}) async {
|
||||
final res = await CRUD().post(link: '$_base/org/admin_add.php', payload: {
|
||||
'org_id': orgId.toString(),
|
||||
'name': name,
|
||||
'phone': phone,
|
||||
'role': role,
|
||||
});
|
||||
if (res is Map && res['status'] == 'success') return TransitApiResult(true, null, 'ok');
|
||||
return TransitApiResult(false, null, _errMsg(res));
|
||||
}
|
||||
|
||||
static Future<TransitApiResult<void>> toggleOrgAdmin({
|
||||
required int adminId,
|
||||
required bool isActive,
|
||||
}) async {
|
||||
final res = await CRUD().post(link: '$_base/org/admin_toggle.php', payload: {
|
||||
'admin_id': adminId.toString(),
|
||||
'is_active': isActive ? '1' : '0',
|
||||
});
|
||||
if (res is Map && res['status'] == 'success') return TransitApiResult(true, null, 'ok');
|
||||
return TransitApiResult(false, null, _errMsg(res));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user