الفصل 08Chapter 08

الميزات والمنطق البرمجي Features & Business Logic

استعراض شامل لكل ميزة في التطبيق، من كود الـ Bloc إلى واجهات المستخدم. A comprehensive review of every feature, from Bloc code to UI screens.

🔐 ميزة الأمان والدخول (Auth Feature) Security & Authentication

تطبيق MRE CashBook بيحفظ بيانات مالية حساسة، عشان كدة كان لازم يكون فيه نظام أمان قوي بيعتمد على بصمة الصيد أو الوجه (Biometrics).

📁 lib/features/auth/presentation/screens/auth_guard_screen.dart
class AuthGuardScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: sl().authenticate(),
      builder: (context, snapshot) {
        if (snapshot.data == true) return const MainScreen();
        return const LockScreen(); // شاشة القفل لو فشل
      },
    );
  }
}

لاحظ إننا استخدمنا الـ LocalAuthService اللي تم حقنه عن طريق الـ DI. دي ميزة إن كل حاجة تكون منفصلة وسهلة الاختبار.

📚 إدارة الكتب (Books Feature) Books Management

الكتاب هو الحاوية الأساسية لكل المعاملات. الميزة دي بتسمح للمستخدم بإضافة، تعديل، أو حذف الكتب، وكمان تحديد إذا كان الكتاب "داخل في العرض الإجمالي" ولا لأ.

📁 lib/features/books/presentation/bloc/books_bloc.dart
on((event, emit) async {
  await repository.insertBook(event.book);
  // البلوك هيرد أوتوماتيك لأننا مسجلين في الـ Stream بتاع الداتابيز
});

النقطة السحرية هنا هي الـ Reactivity. إنت مش محتاج تطلب البيانات يدوياً بعد الإضافة، الداتابيز هي اللي بتبعت إشارة لـ GetIt، والبلوك بيستلمها ويحدث الشاشة.

💸 المعاملات المالية (Entries Feature) Financial Entries

هنا بيحصل الشغل الحقيقي. كل معاملة ليها مبلغ، وصف، تاريخ، وكمان ممكن يكون ليها مرفقات (صور أو فيديوهات).

إحنا بنستخدم AppCustomScrollView عشان نعرض القائمة الطويلة من المعاملات بأداء عالي جداً (Slivers).

🛡️ تشريح ميزة الأمان: البصمة والتشفير Auth Deep Dive: Biometrics & Security

ميزة الـ Auth في التطبيق بتعتمد على مكتبة local_auth. إحنا مغلفين المكتبة دي في خدمة اسمها LocalAuthService عشان تكون سهلة الاستخدام.

📁 lib/core/services/local_auth_service.dart
class LocalAuthService {
  final LocalAuthentication _auth = LocalAuthentication();

  Future authenticate() async {
    final bool canAuthenticateWithBiometrics = await _auth.canCheckBiometrics;
    final bool isDeviceSupported = await _auth.isDeviceSupported();

    if (!canAuthenticateWithBiometrics || !isDeviceSupported) return false;

    return await _auth.authenticate(
      localizedReason: 'يرجى تأكيد هويتك للوصول إلى بياناتك المالية',
      options: const AuthenticationOptions(
        stickyAuth: true,
        biometricOnly: true,
      ),
    );
  }
}
stickyAuth: true

ده بيخلي عملية التأكد "لزجة". يعني لو المستخدم فتح الـ Recent Apps ورجع للتطبيق تاني، الموبايل بيفضل فاكر إنه كان بيحاول يعمل Auth ومبيقفلش العملية فجأة.

⚙️ تشريح ميزة الكتب: الإدارة والمتانة Books Deep Dive: Logic & Resilience

إدارة الكتب بتتم عن طريق BooksBloc. البلوك ده هو اللي بيتحكم في كل "الأرفف" المالية بتاعتك. تعالوا نشوف أهم الـ Events اللي فيه:

1
LoadBooks

بيفتح "ماسورة" (Stream) مع الداتابيز. أي تغيير يحصل في الداتابيز، الشاشة بتتحدث فوراً بدون ما تطلب تاني.

2
AddBook / UpdateBook

بيتحقق من صحة البيانات (Validation) قبل ما يبعتها للـ Repository.

3
DeleteBook

بيعمل "حذف متسلسل" (Cascade Delete). لما بتمسح كتاب، كل الديون والعمليات اللي جواه بتتمسح معاه أوتوماتيك من الداتابيز عشان ميسيبش garbage.

FieldTypePurpose
idIntالمعرف الفريد للكتاب.
nameStringاسم الكتاب (مثلاً: حسابات المحل).
isIncludedInTotalBoolهل نجمع فلوس الكتاب ده مع الفلوس الكلية؟
💸 تشريح ميزة المعاملات: التفاصيل والمرفقات Entries Deep Dive: Transactions & Media

كل "كتاب" جواه مئات "المعاملات". الميزة دي هي الأدق في التطبيق لأنها بتتعامل مع أرقام، تواريخ، وملفات.

📁 lib/features/books/presentation/bloc/entries_bloc.dart
class EntriesBloc extends Bloc {
  final BookDao _bookDao;
  final EntryDao _entryDao;

  // بنسمع للتغييرات في المعاملات بتاع الكتاب ده بس
  void _onLoadEntries(LoadEntries event, Emitter emit) {
    _entriesSubscription?.cancel();
    _entriesSubscription = _entryDao.watchEntriesWithBook(event.bookId).listen(
      (entries) => add(OnEntriesUpdated(entries)),
    );
  }
}

لاحظ هنا إننا استخدمنا watchEntriesWithBook. ده استعلام SQL معقد (Join) بيجيب بيانات المعاملة ومعاها بيانات الكتاب المرتبط بيها في "خبطة واحدة".

إدارة المرفقات (Media Handling)

المعاملة ممكن يكون ليها صور أو فيديوهات. إحنا مش بنحفظ الصور جوه الداتابيز (عشان مساحتها متكبرش)، إحنا بنحفظ "المسار" (Path) بتاع الصورة بس.

// إزاي بنعرض الصورة؟
Image.file(File(entry.attachmentPath!));
📈 لوحة المعلومات: الإحصائيات والرسوم Dashboard Deep Dive: Stats & Charts

الـ Dashboard هو مراية المستخدم. هنا بيعرف هو كسبان ولا خسران، وفلوسه بتروح فين بالظبط.

📁 lib/features/dashboard/presentation/cubit/dashboard_cubit.dart
void _calculateStats(List data) {
  double totalIncome = 0;
  double totalExpense = 0;

  for (var item in data) {
    if (item.book.isIncludedInTotal) {
      totalIncome += item.totalIncome;
      totalExpense += item.totalExpense;
    }
  }
  emit(DashboardLoaded(income: totalIncome, expense: totalExpense));
}

إحنا بنستخدم مكتبة fl_chart عشان نحول الأرقام دي لرسوم بيانية (Pie Chart & Bar Chart) تفتح النفس.

⚙️ الإعدادات: الثيم، اللغة، والخصوصية Settings Deep Dive: Theme, Locale & Privacy

الإعدادات هي المكان اللي المستخدم بيطوع فيه التطبيق لمزاجه. إحنا بنستخدم AppSettingsCubit عشان نتحكم في الحاجات دي.

📁 lib/core/settings/app_settings_cubit.dart
class AppSettingsCubit extends Cubit {
  void toggleTheme() {
    final newMode = state.themeMode == ThemeMode.light 
        ? ThemeMode.dark 
        : ThemeMode.light;
    emit(state.copyWith(themeMode: newMode));
    _saveThemePref(newMode);
  }

  void changeLanguage(Locale locale) {
    emit(state.copyWith(locale: locale));
    _saveLocalePref(locale);
  }
}

لاحظ إن التغيير بيسمع في التطبيق كله "لحظياً" لأننا بنستخدم BlocBuilder في أعلى نقطة في الـ Widget Tree (ملف main.dart).

سياسة الخصوصية (Privacy Policy)

إحنا بنعرض سياسة الخصوصية باستخدام webview_flutter. ده بيخلينا نحدث السياسة من غير ما نبعت تحديث جديد للأبلكيشن على الستور.

🏗️ الحقول المخصصة: نظام البيانات المرن Custom Fields: The Dynamic Data Model

أقوى ميزة في MRE CashBook هي إنك تقدر تضيف حقول زيادة لأي معاملة (زي: اسم المورد، رقم الفاتورة، إلخ). إحنا معملناش ده بجدول واحد ثابت، إحنا عملنا نظام مرن جداً.

1
CustomField Definition

ده جدول فيه أسماء الحقول اللي المستخدم كريتها (مثلاً حقل اسمه "رقم التليفون").

2
EntryFieldValue

ده جدول تالت بيربط المعاملة (Entry) بالحقل (CustomField) وبيحط فيه القيمة (Value).

// إزاي بنجيب كل الحقول لمعاملة معينة؟
Future> getEntryWithFields(int entryId) {
  return (select(entries)..where((t) => t.id.equals(entryId)))
      .join([
        leftOuterJoin(entryFieldValues, entryFieldValues.entryId.equalsExp(entries.id)),
        leftOuterJoin(customFields, customFields.id.equalsExp(entryFieldValues.fieldId)),
      ]).get();
}

ده بيسمح للمستخدم بتحويل التطبيق لـ CRM صغير أو مخزن بسيط، وكل ده بفضل قوة الـ Joins في SQLite.

🔍 محرك البحث: سرعة الوصول للمعلومة Search Deep Dive: Real-time Filtering

لما يكون عندك آلاف المعاملات، البحث بالعين بيكون مستحيل. إحنا عملنا محرك بحث "لحظي" (Debounced Search) بيفهم إنت بتكتب إيه وبيدور في الوصف، رقم المعاملة، وحتى الحقول المخصصة.

// في الـ Bloc، بنستخدم الـ Transformation عشان منعملش Search مع كل حرف
on(
  (event, emit) async {
    // استعلام SQL بسيط لكن فعال
    final results = await repository.searchEntries(event.query);
    emit(EntriesLoaded(results));
  },
  transformer: restartable(), // بيلغي البحث القديم لو كتبت حرف جديد بسرعة
);

استخدام restartable() من مكتبة bloc_concurrency بيوفر كتير في استهلاك البطارية والبروسيسور، لأنه بيوقف أي عملية بحث قديمة ملهاش لازمة.

📜 سجل النشاطات: ذاكرة التطبيق Activity Logs: Tracking Every Action

إيه اللي حصل في التطبيق النهاردة؟ مين مسح الكتاب ده؟ سجل النشاطات هو "الصندوق الأسود" بتاع MRE CashBook.

📁 lib/core/database/tables/activity_logs.dart
class ActivityLogs extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get action => text()(); // مثلاً: 'add_entry'
  TextColumn get description => text()(); // وصف بالعربي والإنجليزي
  DateTimeColumn get createdAt => dateTime()();
}

كل مرة بتعمل فيها عملية (Add, Update, Delete)، إحنا بنرمي "سطر" في الجدول ده. ده مش بس مفيد للمستخدم، ده كمان بيساعدنا في الـ Debugging لو حصلت مشكلة.

ActionDescription (AR)Description (EN)
book_createdتم إنشاء كتاب جديدNew book created
entry_deletedتم حذف معاملةEntry deleted
settings_changedتغيير في الإعداداتSettings updated
📄 تقارير PDF: كشوف حسابات احترافية PDF Reports: Professional Financial Documents

المستخدم غالباً بيحتاج يطبع كشف حساب أو يبعته للعميل. ميزة الـ PDF في MRE CashBook بتطلع ملفات منظمة، فيها براند التطبيق، وحسابات دقيقة.

📁 lib/core/services/pdf_export_service.dart
class PdfExportService {
  Future generateReport(List entries, Book book) async {
    final pdf = pw.Document();
    
    pdf.addPage(
      pw.Page(
        build: (context) => pw.Column(
          children: [
            _buildHeader(book),
            _buildTable(entries),
            _buildFooter(), // فيه لينكات المبرمج والتايمستامب
          ],
        ),
      ),
    );
    return await _savePdf(pdf);
  }
}
تقنيات تحسين الـ PDF (Zebra Striping)

عشان الجدول يكون سهل في القراءة، بنستخدم تقنية الـ Zebra Striping، وهي إننا نغير لون خلفية السطور بالتناوب (سطر أبيض وسطر رمادي فاتح).

// منطق التلوين
rowDecoration: index % 2 == 0 
    ? pw.BoxDecoration(color: PdfColors.grey100) 
    : null,
💾 الأمان أولاً: نسخ وقراءة بيانات قاعدة البيانات Safety First: Database Backup & Sharing

إيه اللي يحصل لو المستخدم غير موبايله؟ إحنا بنسمح للمستخدم "يصدر" (Export) ملف قاعدة البيانات بالكامل ويبعته على الواتساب أو الإيميل.

Future exportDatabase() async {
  final dbFile = await DatabaseProvider.getDatabaseFile();
  if (await dbFile.exists()) {
    await Share.shareXFiles(
      [XFile(dbFile.path)],
      text: 'MRE CashBook Database Backup',
    );
  }
}

ملف قاعدة البيانات .sqlite هو أغلى ما يملك المستخدم. دايماً بننصح في شاشة الإعدادات إن المستخدم يعمل Backup دوري عشان لو الموبايل ضاع بيانه متضيعش.

🕸️ النظام البيئي: كيف تتفاعل الميزات؟ The Ecosystem: Feature Interaction Diagram

الميزات في MRE CashBook مش شغالة في جزر منعزلة، هي بتكلم بعضها طول الوقت. الرسمة دي بتوضح المسار:

graph TD
    A[Auth Feature] -- Success --> B[Main Screen]
    B --> C[Books Feature]
    C -- Book Selected --> D[Entries Feature]
    D -- New Entry --> E[Database]
    E -- Stream Update --> F[Dashboard Feature]
    E -- Sync --> G[Backup/Export]
    D -- Generate --> H[PDF Service]

لاحظ إن الـ Database هي القلب اللي كل الميزات بتسمع منه. ده بيخلي الواجهة دايماً متحدثة (Reactive UI).

🛠️ دليل المصلح: حل مشاكل منطق الميزات The Debugger's Guide: Troubleshooting Features

أشهر المشاكل اللي ممكن تقابلك وأنت بتطور ميزات جديدة:

1
The "Ghost" Data

المشكلة: ضفت معاملة بس مظهرتش في الـ Dashboard.

الحل: اتأكد إن الـ isIncludedInTotal معمول له true في جدول الكتب. لو الكتاب مستبعد، الـ Dashboard مش هيحسب أرقامه.

2
Biometric Failure

المشكلة: البصمة مش بتفتح في الـ Emulator.

الحل: لازم تفعل الـ Biometrics من إعدادات الـ Emulator نفسه (Features -> Fingerprint). في الموبايل الحقيقي، اتأكد إن المستخدم مسجل بصمة أصلاً.

3
PDF Empty Pages

المشكلة: الـ PDF بيطلع صفحات فاضية.

الحل: ده غالباً بسبب حجم الـ Table أكبر من الصفحة. استخدم pw.MultiPage بدل pw.Page عشان يتحمل الزيادة ويبدأ صفحة جديدة أوتوماتيك.

أسئلة شائعة حول ميزات التطبيق Features FAQ
إزاي التطبيق بيحسب "الإجمالي" بسرعة مع آلاف العمليات؟
How does the app calculate totals quickly with thousands of entries?
إحنا مش بنحسب في الـ UI. إحنا بنستخدم SQL Queries جاهزة (Aggregations) زي SUM(amount) بتنفذها قاعدة البيانات في ملي ثانية وترجع لنا الرقم النهائي بس.
Calculations happen in the database using SQL aggregations like SUM(amount). SQLite is extremely optimized for this, returning results in milliseconds.
هل يمكن تغيير العملة لكل كتاب لوحده؟
Can I change the currency for each book separately?
حاليا العملة موحدة للتطبيق كله لتبسيط الحسابات، لكننا بنخطط نخليه "متعدد العملات" (Multi-currency) في المستقبل بحيث كل كتاب يكون ليه عملته الخاصة.
Currently, the currency is global. We plan to add multi-currency support in future updates, allowing each ledger to have its own currency.
إيه اللي بيحصل لو قفلت التطبيق وأنا بضيف عملية؟
What happens if I close the app while adding an entry?
البيانات مش هتتحفظ لغاية ما تدوس "حفظ". ده بيضمن إن قاعدة البيانات مفيهاش "بيانات ناقصة" أو عمليات مش مكتملة.
Data is only saved when you tap "Save". This ensures database integrity and prevents partial or corrupted entries.
ليه التطبيق مبيحتاجش إنترنت؟
Why does the app work offline?
لأننا بنستخدم SQLite داخلياً. البيانات ملكك وموجودة على جهازك طول الوقت. الإنترنت بنحتاجه بس لو هتعمل Sync مع السحاب أو تفتح سياسة الخصوصية.
We use local SQLite storage. Your data is yours and stays on your device. Internet is only needed for cloud syncing or viewing the privacy policy.
📖 قاموس الميزات: مصطلحات تقنية The Feature Dictionary: Glossary

دي المصطلحات اللي بنستخدمها كفريق تطوير عشان نوصف الميزات:

  • Biometrics: التحقق الحيوي عن طريق البصمة أو الوجه.
  • Reactivity: قدرة الواجهة على التحديث التلقائي بمجرد تغيير البيانات.
  • Cascade Delete: الحذف المتتابع (مثلاً حذف المعاملات عند حذف الكتاب).
  • Debounce: تأخير تنفيذ العملية (زي البحث) لغاية ما المستخدم يبطل كتابة.
  • Zebra Striping: تلوين سطور الجدول بألوان مختلفة لسهولة القراءة.
  • Custom Fields: حقول إإضافية بيعرفها المستخدم حسب حاجته.
  • Audit Log: سجل تتبع لكل العمليات اللي حصلت في السيستم.
  • Sticky Auth: بقاء عملية التحقق نشطة حتى لو خرجت من التطبيق ورجعت بسرعة.
  • Pie Chart: الرسم البياني الدائري اللي بيوضح توزيع المصاريف.
  • Export: تصدير البيانات بصيغة .sqlite أو .pdf.
  • SQL Join: ربط أكتر من جدول ببعض عشان نجيب بيانات متكاملة.
  • PDF Layout: تصميم شكل الملف اللي هيطلع للمطبعة أو للمشاركة.
  • Cubit: نسخة خفيفة ومبسطة من الـ Bloc لإدارة الحالة البسيطة.
  • Repository: الطبقة اللي بتفصل بين الـ Bloc ومصدر البيانات (DB/API).
  • UI Overlay: طبقة فوق الواجهة لعرض تنبيهات أو قوائم اختيار سريعة.
📊 مصفوفة الميزات: القدرات الأساسية Feature Matrix: Core Capabilities

الجدول ده بيلخص كل اللي التطبيق بيقدر يعمله، والملفات المسؤولة عن كل جزء:

FeaturePurpose (AR)Core FilesDependencies
Biometricsتأمين الدخول بالبصمة.auth_guard_screen.dartlocal_auth
Ledger Managementإدارة كتب الحسابات المختلفة.books_bloc.dartdrift
Daily Entriesتسجيل الديون والمدفوعات.entries_bloc.dartdrift
Dashboardsرؤية شاملة للوضع المالي.dashboard_cubit.dartfl_chart
Media Attachmentsإرفاق صور وفيديوهات للعملية.image_picker_helper.dartimage_picker
PDF Exportتصدير كشوفات الحساب.pdf_export_service.dartpdf
DB Backupنسخ احتياطي لقاعدة البيانات.database_provider.dartshare_plus
Themingالوضع الليلي والنهاري.app_settings_cubit.dartflutter_bloc
Localizationدعم العربية والإنجليزية.l10n/easy_localization
🚀 دورة حياة الميزة: من الفكرة للمحترفين The Feature Lifecycle: From V1 to Pro

عشان تبني ميزة صح في MRE CashBook، إحنا بنمشي على خطوات ثابتة بتضمن الجودة:

1
The DB Schema (Drift)

أول حاجة بنعرف الجدول في الداتابيز. البيانات هي الأساس.

2
The Bloc/Cubit Logic

بنكتب الـ Logic اللي هيتعامل مع البيانات دي (Add, Load, Filter).

3
The UI & Core Widgets

بنبني الواجهة باستخدام الـ Widgets اللي موجودة في lib/core/widgets عشان نحافظ على الشكل الموحد.

4
Localization & Testing

بنضيف الترجمات (AR/EN) ونجرب الميزة على الموبايل والتابلت.

التزامنا بالـ Clean Architecture هو اللي بيخلينا نقدر نضيف ميزة زي "الحقول المخصصة" في يوم واحد من غير ما نهد الكود القديم.

🧠 اختبار: خبير الميزات (Feature Expert Quiz) Interactive Quiz: The Feature Expert

اختبر نفسك وشوف مدى فهمك لأجزاء التطبيق:

1. إيه اللي بيحصل لما بتمسح كتاب فيه 50 معاملة؟
المعاملات بتتمسح أوتوماتيك بفضل الـ Cascade Delete في الداتابيز.
2. إزاي بنضمن إن البحث ميتقلش التطبيق لو المستخدم كتب بسرعة؟
بنستخدم transformer: restartable() في البلوك عشان نلغي عمليات البحث القديمة.
3. ليه مش بنحفظ الصور جوه ملف الـ SQLite؟
عشان نحافظ على حجم قاعدة البيانات صغير ونمنع البطء؛ بنحفظ المسار (Path) بس.
🛤️ خريطة تدفق البيانات: من المعاملة للرسوم Visualizing Flow: Data Infographic

 [ User Action ] ──▶ [ AddEntry Screen ] ──▶ [ EntriesBloc ]
                                                 │
       ┌─────────────────────────────────────────┘
       ▼
 [ EntryDao (Drift) ] ──▶ [ SQLite DB File ]
       │
       ▼ (Reactive Stream Update)
       │
 [ DashboardCubit ] ──▶ [ Stats Map ] ──▶ [ FlChart UI ]
        

التدفق ده بيحصل في أجزاء من الثانية، وده اللي بيدي إحساس الـ Smoothness في التطبيق.

🔭 الأفق: ميزات قيد التطوير The Horizon: Future Feature Roadmap

إحنا مش بنوقف تطوير. دي أهم الميزات اللي بنخطط لإضافتها في الإصدارات الجاية:

  • Cloud Sync: ربط الحسابات بـ Firebase عشان البيانات تكون متاحة على أكتر من جهاز.
  • Dynamic Tax Calculation: حساب الضرائب والقيمة المضافة أوتوماتيك لكل معاملة.
  • OCR Scan: تصوير الفاتورة بالموبايل والتطبيق يستخرج منها المبلغ والتاريخ لوحده باستخدام الـ AI.
  • CSV/Excel Export: تصدير البيانات بصيغة إكسيل عشان المحاسبين يقدروا يشتغلوا عليها.
📜 الوصايا العشر لبناء الميزات The 10 Feature Commandments

عشان تحافظ على نظافة الكود في MRE CashBook، لازم تتبع القواعد دي وأنت بتبني أي ميزة جديدة:

1

لا تلمس الـ UI قبل الداتابيز: صمم جدولك الأول، هو ده اللي هيحدد شكل المنطق بتاعك.

2

البلوك هو العقل: أي عملية حسابية أو فلترة لازم تتم جوه الـ Bloc/Cubit، والـ UI بس بيعرض النتيجة.

3

احترم الـ Extensions: استخدم context.colors و context.tr() دايماً؛ إياك والألوان الثابتة أو النصوص الهارد كود.

4

التصرف للتابلت: فكر دايماً شكل الميزة هيكون إيه على التابلت قبل ما تبدأ، واستخدم ResponsiveLayout.

5

سجل كل شيء: ارمي سطر في الـ ActivityLogs لكل عملية مؤثرة المستخدم بيعملها.

6

نظف خلفك: لو مسحت حاجة، اتأكد إن كل متعلقاتها اتمسحت (Cascade Delete).

7

الاستجابة اللحظية: ميزة المستخدم مش هيحس بقوتها إلا لو البيانات اتحدثت قدامه من غير ما يعمل ريفريش.

8

الأمان ليس رفاهية: ميزات الحذف لازم تكون محمية بـ Dialog تأكيدي أو بصمة لو كانت حساسة.

9

استخدم الـ Core: لا تعيد اختراع العجلة؛ الـ lib/core/widgets فيها 90% من اللي هتحتاجه.

10

التوثيق بصمت: سمي المتغيرات بأسماء واضحة، ولا تستخدم الكومنتات إلا لشرح الـ "ليه" مش الـ "إيه".

📐 تحدي مهندس الميزات: ميزة الاشتراكات Advanced Challenge: The Feature Architect

تخيل إنك عاوز تضيف ميزة "الاشتراكات الشهرية" (Subscriptions). فكر في الخطوات دي:

A
DB Schema

هتحتاج جدول للاشتراكات فيه (الاسم، المبلغ، تاريخ التجديد، والحالة نشط أم لأ).

B
The Engine

هتعمل SubscriptionCubit بيسمع للاشتراكات ويقارن تاريخ النهاردة بتاريخ التجديد عشان يبعت تنبيه.

C
The Dashboard

إزاي هتعرض إجمالي مصاريف الاشتراكات في الرسم البياني للـ Dashboard؟

⚙️ خلف الكواليس: رحلة الـ BLoC الكاملة Under the Hood: The BLoC Event Loop

تعال نتبع رحلة "حذف كتاب" من ساعة ما المستخدم يدوس على الزرار لغاية ما يختفي من الشاشة:

1
UI Level

المستخدم بيدوس على أيقونة المسح. بنظهر AdaptiveOverlays.showAdaptiveModal للتأكيد.

2
Event Dispatch

لو أكد، بنبعت الـ Event: context.read<BooksBloc>().add(DeleteBook(id)).

3
Repository Action

البلوك بينادي الـ Repository، والـ Repository بيمسح السطر من الداتابيز.

4
Auto-Reactivity

الداتابيز بتبعت إشارة للـ watchBooks Stream إن البيانات اتغيرت.

5
UI Refresh

البلوك بيستلم الـ Stream الجديد ويبعت BooksLoaded، والـ UI بيتحدث بالكتب المتبقية بس.

الجمال هنا إن الـ Bloc مبيحتفظش بحالة "الكتب" عنده يدوياً، هو مجرد "نافذة" بتعرض اللي في الداتابيز لحظة بلحظة.

📝 جدول المراجعة النهائية للفصل الثامن Final Mastery: Chapter 08 Recap
LessonKey Takeaway (AR)Technical Tools
Authالأمان يبدأ من بصمة الإصبع.local_auth
Booksالكتب هي الحاوية التنظيمية.watchStream
Entriesالمعاملات المالية هي قلب العمل.Slivers
Dashboardالأرقام لا تكذب، والرسوم توضح.fl_chart
Custom Fieldsالمرونة هي سر البقاء والاستمرار.SQLite Joins
Searchالبحث اللحظي يوفر الوقت والجهد.restartable()
Activity Logsالشفافية تمنع الأخطاء البشرية.DB Audit
PDF Exportالاحترافية تظهر في التقارير.pdf package
Backupsبياناتك أمانة، فاحمِها بالنسخ.share_plus
Architectureنظام الميزات المنفصل يسهل التطوير.Clean Architecture
🏆 قائمة احتراف الميزات (Mastery Checklist) The Feature Mastery Checklist

قبل ما تقول إن الميزة دي "خيرة"، اتأكد إنك عملت الـ 15 حاجة دول:

Checklist ItemAR DescriptionDone?
DB Schema Definedالجدول متعرف صح في Drift.
Sync logic (Stream)الـ UI بيحدث لحظياً.
Error Handlingفيه Try/Catch ورسايل خطأ واضحة.
Biometric Guardلو الميزة حساسة، عليها قفل.
Localization (AR)كل النصوص مترجمة عربي.
Localization (EN)كل النصوص مترجمة إنجليزي.
Dark Mode Supportالألوان واضحة في الوضع الليلي.
Tablet Optimizationالشكل مظبوط على الشاشات الكبيرة.
Media Supportالمرفقات شغالة (صور/فيديو).
PDF Integrationالميزة بتظهر في التقارير.
Searchableممكن نوصل للبيانات بالبحث.
Audit Loggedالعملية متسجلة في الـ History.
Input Validationالمستخدم مبيعرفش يدخل بيانات غلط.
Performance Checkالميزة مش بتقل التطبيق.
Clean Code Principlesالكود منظم ومكتوب صح.
🏁 خاتمة الفصل الثامن: القوة تكمن في التفاصيل Chapter 08: Final Thoughts

الفصل ده كان الأطول والأهم في كورس MRE CashBook. لأن الميزات هي اللي بتقدم القيمة للمستخدم في الآخر. لما بتنفذ ميزة بنظام الـ Clean Architecture وتراعي فيها الأداء والأمان، إنت مش بس بتبني تطبيق، إنت بتبني "أداة" المستخدم يقدر يعتمد عليها في حياته اليومية.

في الفصل الجاي: هننقل من "المنطق" لـ "الجمال". هنعرف إزاي عملنا نظام الثيمات (UI Theming) اللي بيخلي التطبيق مريح للعين في كل الأوقات.

📝 الملخص Summary

الميزات هي قلب التطبيق. تنظيمها في فولدرات منفصلة (Clean Architecture) هو اللي بيخليه يعيش سنين بدون مشاكل.

الفصل السابقPrevious الفصل التاليNext