قرار المالك 2026-07-27: باك إند سيرو PHP هو المعتمد، وتطبيقاته المجرّبة ميدانياً تحل محل إعادة البناء المؤرشفة. سيرو نفسه لم يُمسّ. الخريطة: backend · payment_server · loction_server · ride_server · passenger_server · docker · dashboard · stress_test → الجذر siro_rider → apps/rider siro_driver → apps/driver siro_admin → dashboards/admin siro_service → dashboards/service android_bot → apps/android_bot socialBot → apps/socialBot نُسخ المتعقَّب في git سيرو فقط عبر `git archive` (3,198 ملفاً / ~169 م.ب) لا `cp -r` — فاستُثنيت مخلفات البناء تلقائياً. بلا أي تعديل محتوى عمداً: كل ما يلي يصير فرقاً مقروءاً مقابل المصدر. لم يُستورد وسببه: siromove.com (الموقع التسويقي يبقى marketing/ في تريبز، سيرو فيه 8 ملفات) · docs و planning (تريبز له docs/ الخاص) · deploy.sh (ليس نشراً على سيرفر بل `git add . && git push origin --all` — فخّ في مستودع آخر) · transit_dashboard (بانتظار قرار مصير backend-transit و dashboards/transit-web). ⚠️ لا يبني بعد — ثلاثة نواقص متوقعة ومقصودة: 1. `.env` و `lib/env/env.g.dart` غير متعقَّبين في سيرو (أسرار لكل مستأجر): كل تطبيق فلاتر يحتاج .env خاصاً ثم توليد env.g.dart بـ build_runner. 2. إعدادات Firebase (9 ملفات google-services.json و GoogleService-Info.plist) يستبعدها .gitignore تريبز — ولكل مستأجر مشروع Firebase خاص أصلاً. 3. apps/driver في سيرو يشير إلى `../../Intaleq/packages/get` خارج المستودع → يجب ضمّ الحزم داخله أسوة بـ apps/rider. 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;
|
|
}
|
|
}
|