Deploy: 2026-05-24 23:27:32

This commit is contained in:
Hamza-Ayed
2026-05-24 23:27:32 +03:00
parent 2ceffc47d9
commit b20f457eaf
156 changed files with 8308 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/dashboard_repository.dart';
import 'dashboard_state.dart';
// English: DashboardCubit manages the active tab and data fetching.
// Arabic: يدير ملف الكيوبيت الباب النشط وجلب البيانات المخصصة له.
//
// English: In the web client, AlpineJS switches active tabs and calls fetch functions.
// Arabic: في عميل الويب، تبدل مكتبة ألبين الباب النشط وتستدعي دوال الجلب.
//
// English: Here, this Cubit replicates that behavior by capturing changes and emitting updated states.
// Arabic: هنا، يكرر هذا الكيوبيت هذا السلوك من خلال رصد التغييرات وإرسال حالات محدثة.
class DashboardCubit extends Cubit<DashboardState> {
final DashboardRepository _repository;
DashboardCubit(this._repository)
: super(const DashboardState(
activeTab: DashboardTab.whatsapp,
isLoading: false,
));
// English: Switch the active dashboard view and fetch the required API data.
// Arabic: تبديل عرض لوحة التحكم النشط وجلب بيانات واجهة برمجة التطبيقات المطلوبة.
Future<void> changeTab(DashboardTab tab) async {
// English: Update tab state first to give instant visual feedback in UI.
// Arabic: تحديث حالة الباب أولاً لتقديم استجابة مرئية فورية في الواجهة.
emit(state.copyWith(activeTab: tab, isLoading: true));
try {
switch (tab) {
case DashboardTab.whatsapp:
final status = await _repository.getWhatsAppStatus();
emit(state.copyWith(whatsappStatus: status, isLoading: false));
break;
case DashboardTab.billing:
final plans = await _repository.getPlans();
emit(state.copyWith(plans: plans, isLoading: false));
break;
case DashboardTab.contacts:
final contacts = await _repository.getContacts();
emit(state.copyWith(contacts: contacts, isLoading: false));
break;
case DashboardTab.chatbot:
final rules = await _repository.getChatbotRules();
emit(state.copyWith(chatbotRules: rules, isLoading: false));
break;
case DashboardTab.superAdmin:
final adminStats = await _repository.getAdminStats();
emit(state.copyWith(superAdminStats: adminStats, isLoading: false));
break;
default:
// English: Placeholder views do not hit any backend API.
// Arabic: شاشات الحجز المؤقتة لا تتصل بأي واجهة برمجة تطبيقات.
emit(state.copyWith(isLoading: false));
break;
}
} catch (e) {
final cleanMsg = e.toString().replaceAll('Exception: ', '');
emit(state.copyWith(errorMessage: cleanMsg, isLoading: false));
}
}
// English: Action trigger to reload current active tab data.
// Arabic: مشغل الإجراء لإعادة تحميل بيانات الباب النشط الحالي.
Future<void> refreshCurrentTab() async {
await changeTab(state.activeTab);
}
// English: Add a new contact and automatically reload the updated contacts list.
// Arabic: إضافة جهة اتصال جديدة وإعادة تحميل قائمة جهات الاتصال المحدثة تلقائياً.
Future<bool> addContact(String name, String phone) async {
emit(state.copyWith(isLoading: true));
try {
await _repository.addContact(name, phone);
final contacts = await _repository.getContacts();
emit(state.copyWith(contacts: contacts, isLoading: false));
return true;
} catch (e) {
final cleanMsg = e.toString().replaceAll('Exception: ', '');
emit(state.copyWith(errorMessage: cleanMsg, isLoading: false));
return false;
}
}
// English: Request a new WhatsApp QR connection session and refresh status.
// Arabic: طلب جلسة اتصال واتساب جديدة برمز استجابة سريع وتحديث الحالة.
Future<void> requestWhatsAppQr() async {
emit(state.copyWith(isLoading: true));
try {
await _repository.requestWhatsAppQr();
final status = await _repository.getWhatsAppStatus();
emit(state.copyWith(whatsappStatus: status, isLoading: false));
} catch (e) {
final cleanMsg = e.toString().replaceAll('Exception: ', '');
emit(state.copyWith(errorMessage: cleanMsg, isLoading: false));
}
}
// English: Disconnect active WhatsApp connection and refresh status.
// Arabic: قطع اتصال الواتساب النشط وتحديث الحالة.
Future<void> disconnectWhatsApp() async {
emit(state.copyWith(isLoading: true));
try {
await _repository.disconnectWhatsApp();
final status = await _repository.getWhatsAppStatus();
emit(state.copyWith(whatsappStatus: status, isLoading: false));
} catch (e) {
final cleanMsg = e.toString().replaceAll('Exception: ', '');
emit(state.copyWith(errorMessage: cleanMsg, isLoading: false));
}
}
// English: Approve a pending company subscription billing and reload admin stats.
// Arabic: الموافقة على اشتراك شركة معلق وإعادة تحميل إحصائيات المدير العام.
Future<void> approveBilling(int companyId) async {
emit(state.copyWith(isLoading: true));
try {
await _repository.approveBilling(companyId);
final stats = await _repository.getAdminStats();
emit(state.copyWith(superAdminStats: stats, isLoading: false));
} catch (e) {
final cleanMsg = e.toString().replaceAll('Exception: ', '');
emit(state.copyWith(errorMessage: cleanMsg, isLoading: false));
}
}
}

View File

@@ -0,0 +1,89 @@
import 'package:equatable/equatable.dart';
import '../../data/models/chatbot_rule_model.dart';
import '../../data/models/contact_model.dart';
import '../../data/models/plan_model.dart';
import '../../data/models/super_admin_stats_model.dart';
import '../../data/models/whatsapp_status_model.dart';
// English: Enum representing the 9 tabs in the Nabeh web/mobile dashboard.
// Arabic: قائمة تعداد تمثل الأبواب التسعة في لوحة تحكم نبيه على الويب والهاتف.
enum DashboardTab {
superAdmin,
whatsapp,
billing,
contacts,
templates,
campaigns,
chatbot,
integrations,
staff
}
class DashboardState extends Equatable {
// English: The currently selected tab in navigation.
// Arabic: الباب المحدد حالياً في التنقل.
final DashboardTab activeTab;
// English: Indicator if data is being retrieved from backend.
// Arabic: مؤشر ما إذا كان يتم استرداد البيانات من الواجهة الخلفية.
final bool isLoading;
// English: Error message if API requests fail.
// Arabic: رسالة الخطأ إذا فشلت طلبات واجهة برمجة التطبيقات.
final String? errorMessage;
// English: Feature data models parsed from network API responses.
// Arabic: نماذج بيانات الميزات التي تم تحليلها من استجابات الشبكة.
final WhatsAppStatusModel? whatsappStatus;
final List<PlanModel> plans;
final List<ContactModel> contacts;
final List<ChatbotRuleModel> chatbotRules;
final SuperAdminStatsModel? superAdminStats;
const DashboardState({
required this.activeTab,
required this.isLoading,
this.errorMessage,
this.whatsappStatus,
this.plans = const [],
this.contacts = const [],
this.chatbotRules = const [],
this.superAdminStats,
});
// English: Helper copyWith constructor to copy immutable state data safely.
// Arabic: منشئ مساعد لنسخ بيانات الحالة الثابتة بشكل آمن.
DashboardState copyWith({
DashboardTab? activeTab,
bool? isLoading,
String? errorMessage,
WhatsAppStatusModel? whatsappStatus,
List<PlanModel>? plans,
List<ContactModel>? contacts,
List<ChatbotRuleModel>? chatbotRules,
SuperAdminStatsModel? superAdminStats,
}) {
return DashboardState(
activeTab: activeTab ?? this.activeTab,
isLoading: isLoading ?? this.isLoading,
errorMessage: errorMessage, // Reset if null
whatsappStatus: whatsappStatus ?? this.whatsappStatus,
plans: plans ?? this.plans,
contacts: contacts ?? this.contacts,
chatbotRules: chatbotRules ?? this.chatbotRules,
superAdminStats: superAdminStats ?? this.superAdminStats,
);
}
@override
List<Object?> get props => [
activeTab,
isLoading,
errorMessage,
whatsappStatus,
plans,
contacts,
chatbotRules,
superAdminStats,
];
}