المجلدات وأسماء حزم dart واستيراداتها: siro_rider → intaleq_rider siro_driver → intaleq_driver siro_admin → intaleq_admin siro_service → intaleq_service شمل ذلك `name:` في كل pubspec وكل `package:siro_*` في الاستيرادات (115 ملفاً في rider وحده)، وإشارات أسماء المجلدات في docs/ وتعليق في backend/Admin/notifications/broadcast.php. لم تبقَ إشارة واحدة (تحقّقت). + ضُمّت حزم get و get_storage داخل intaleq_driver/packages/ وحُوّلت مساراتها الثلاثة من `../../Intaleq/packages/*` إلى `./packages/*`. كانت تُحل عرضاً إلى مجلد App/Intaleq القديم المجاور — تبعية خارج المستودع تنكسر بأول نقل. لم يبقَ في أي تطبيق تبعية مسار خارج الشجرة. ⚠️ لم تُمسّ بعد: هويات المتاجر (applicationId · PRODUCT_BUNDLE_IDENTIFIER · shorebird app_id) ولا الألوان ولا النصوص المرئية ولا النطاقات — كل منها كوميت منفصل، والهويات تحتاج قرار المالك. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
183 lines
4.9 KiB
Dart
183 lines
4.9 KiB
Dart
// 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);
|
|
}
|
|
}
|
|
|
|
// ── إدارة العقد ───────────────────────────────────────────────
|
|
bool isUpdatingContract = false;
|
|
|
|
Future<bool> updateContractStatus(int orgId, String contractStatus) async {
|
|
isUpdatingContract = true;
|
|
update();
|
|
final res = await TransitAdminService.updateContractStatus(
|
|
orgId: orgId, contractStatus: contractStatus);
|
|
isUpdatingContract = false;
|
|
if (res.success) {
|
|
await fetchOrgs();
|
|
return true;
|
|
}
|
|
Get.snackbar('مواصلاتي', res.message);
|
|
update();
|
|
return false;
|
|
}
|
|
|
|
// ── اعتماد الخطوط ──────────────────────────────────────────────
|
|
bool isLoadingPendingRoutes = false;
|
|
List<Map<String, dynamic>> pendingRoutes = [];
|
|
bool isApprovingRoute = false;
|
|
|
|
Future<void> fetchPendingRoutes({int? orgId}) async {
|
|
isLoadingPendingRoutes = true;
|
|
update();
|
|
final res = await TransitAdminService.listPendingRoutes(orgId: orgId);
|
|
if (res.success) pendingRoutes = res.data ?? [];
|
|
isLoadingPendingRoutes = false;
|
|
update();
|
|
}
|
|
|
|
Future<bool> approveRoute(int routeId, String action) async {
|
|
isApprovingRoute = true;
|
|
update();
|
|
final res = await TransitAdminService.approveRoute(
|
|
routeId: routeId, action: action);
|
|
isApprovingRoute = false;
|
|
if (res.success) {
|
|
pendingRoutes.removeWhere((r) => int.tryParse(r['id'].toString()) == routeId);
|
|
update();
|
|
return true;
|
|
}
|
|
Get.snackbar('مواصلاتي', res.message);
|
|
update();
|
|
return false;
|
|
}
|
|
}
|