Files
tripz-llc/dashboards/admin/lib/views/transit/org_create_page.dart
T
Hamza-AyedandClaude Opus 5 4d8414c96b feat: استيراد كود سيرو إلى تريبز (سيرو @ecfe7568) — بلا تعديل
قرار المالك 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>
2026-07-27 05:14:13 +03:00

144 lines
5.2 KiB
Dart

// org_create_page.dart — إضافة مؤسسة جديدة (لوحة إدارة سيرو)
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../controller/transit/transit_admin_controller.dart';
class TransitOrgCreatePage extends StatefulWidget {
const TransitOrgCreatePage({super.key});
@override
State<TransitOrgCreatePage> createState() => _TransitOrgCreatePageState();
}
class _TransitOrgCreatePageState extends State<TransitOrgCreatePage> {
final _nameAr = TextEditingController();
final _nameEn = TextEditingController();
final _city = TextEditingController();
final _adminName = TextEditingController();
final _adminPhone = TextEditingController();
String _type = 'university';
String _country = 'JO';
final _types = const {
'university': 'جامعة',
'school': 'مدرسة',
'hotel': 'فندق',
'company': 'شركة',
'transporter': 'ناقل',
};
final _countries = const {'JO': 'الأردن', 'SY': 'سوريا', 'EG': 'مصر'};
@override
Widget build(BuildContext context) {
return GetBuilder<TransitAdminController>(
builder: (c) => Scaffold(
backgroundColor: AppColor.bg,
appBar: AppBar(
backgroundColor: AppColor.bg,
elevation: 0,
title: const Text('إضافة مؤسسة', style: TextStyle(color: AppColor.textPrimary)),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_dropdown('نوع المؤسسة', _type, _types, (v) => setState(() => _type = v!)),
const SizedBox(height: 12),
_dropdown('الدولة', _country, _countries, (v) => setState(() => _country = v!)),
const SizedBox(height: 12),
_field(_nameAr, 'اسم المؤسسة (عربي)'),
const SizedBox(height: 12),
_field(_nameEn, 'اسم المؤسسة (إنجليزي)'),
const SizedBox(height: 12),
_field(_city, 'المدينة'),
const SizedBox(height: 20),
const Divider(color: AppColor.surfaceElevated),
const SizedBox(height: 8),
const Text('أول مشرف (owner) لهذه المؤسسة',
style: TextStyle(color: AppColor.textSecondary)),
const SizedBox(height: 12),
_field(_adminName, 'اسم المشرف'),
const SizedBox(height: 12),
_field(_adminPhone, 'هاتف المشرف', keyboardType: TextInputType.phone),
const SizedBox(height: 24),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.accent,
minimumSize: const Size.fromHeight(50),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
onPressed: c.isCreating ? null : _submit,
child: c.isCreating
? const SizedBox(
height: 20, width: 20,
child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white))
: const Text('إنشاء', style: TextStyle(color: Colors.white)),
),
],
),
),
);
}
Widget _field(TextEditingController ctrl, String label, {TextInputType? keyboardType}) {
return TextField(
controller: ctrl,
keyboardType: keyboardType,
style: const TextStyle(color: AppColor.textPrimary),
decoration: InputDecoration(
labelText: label,
labelStyle: const TextStyle(color: AppColor.textSecondary),
filled: true,
fillColor: AppColor.surface,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none),
),
);
}
Widget _dropdown(String label, String value, Map<String, String> options,
void Function(String?) onChanged) {
return DropdownButtonFormField<String>(
initialValue: value,
dropdownColor: AppColor.surface,
style: const TextStyle(color: AppColor.textPrimary),
decoration: InputDecoration(
labelText: label,
labelStyle: const TextStyle(color: AppColor.textSecondary),
filled: true,
fillColor: AppColor.surface,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none),
),
items: options.entries
.map((e) => DropdownMenuItem(value: e.key, child: Text(e.value)))
.toList(),
onChanged: onChanged,
);
}
Future<void> _submit() async {
if (_nameAr.text.trim().isEmpty ||
_nameEn.text.trim().isEmpty ||
_city.text.trim().isEmpty ||
_adminName.text.trim().isEmpty ||
_adminPhone.text.trim().isEmpty) {
Get.snackbar('مواصلاتي', 'الرجاء تعبئة كل الحقول');
return;
}
final c = Get.find<TransitAdminController>();
final ok = await c.createOrg(
type: _type,
country: _country,
city: _city.text.trim(),
nameAr: _nameAr.text.trim(),
nameEn: _nameEn.text.trim(),
adminName: _adminName.text.trim(),
adminPhone: _adminPhone.text.trim(),
);
if (ok && mounted) Get.back(result: true);
}
}