import'package:supabase_flutter/supabase_flutter.dart';import'../models/note_model.dart';/// هذا الكلاس مسؤول فقط عن الاتصال مع Supabase/// ❌ لا يعرف Cubit/// ❌ لا يعرف UI/// ✅ فقط APIclassNotesRemoteDataSource {finalSupabaseClient client;/// نستقبل client من الخارج (Dependency Injection)NotesRemoteDataSource(this.client);/// 🔥 دالة إضافة ملاحظةFuture<void> addNote(NoteModel note) async {/// insert = إدخال بيانات إلى الجدول /// note.toJson() = تحويل object إلى Mapawait client .from('notes') // اسم الجدول .insert(note.toJson()); }}
Dart
🧠 شرح الملف
هذا الملف هو "المتحدث الوحيد مع Supabase"أي عملية API تتم هنا فقط
Dart
🧱 2) RepositoryImpl (التحويل + الربط)
📁 notes_repository_impl.dart
📄 الكود + شرح
import'../../domain/entities/note.dart';import'../../domain/repository/notes_repository.dart';import'../datasource/notes_remote_datasource.dart';import'../models/note_model.dart';/// هذا الكلاس يطبق interface الموجود في domain/// مهمته:/// تحويل Entity → Model/// ثم إرسالها للـ DataSourceclassNotesRepositoryImplimplementsNotesRepository {finalNotesRemoteDataSource remote;NotesRepositoryImpl(this.remote);@overrideFuture<void> addNote(Note note) async {/// تحويل Entity إلى Modelfinal model = NoteModel( id: note.id, title: note.title, content: note.content, );/// إرسال البيانات للـ APIawait remote.addNote(model); }}
Dart
🧠 شرح الملف
هذا هو "الجسر" بين domain و data
Dart
🧱 3) Repository (Interface)
📁 notes_repository.dart
📄 الكود
import'../entities/note.dart';/// هذا مجرد عقد (contract)/// لا يحتوي تنفيذabstractclassNotesRepository {/// تعريف العملية فقطFuture<void> addNote(Note note);}
Dart
🧠 شرح
Domain لا يعرف Supabaseفقط يعرف أن هناك عملية "إضافة"
Dart
🧱 4) UseCase (منطق العملية)
📁 add_note_usecase.dart
📄 الكود
import'../entities/note.dart';import'../repository/notes_repository.dart';/// UseCase = يمثل "فعل" في التطبيق/// هنا: إضافة ملاحظةclassAddNoteUseCase {finalNotesRepository repo;AddNoteUseCase(this.repo);/// call() يسمح باستدعاء الكلاس كدالةFuture<void> call(Note note) async {/// تنفيذ العملية عبر repositoryawait repo.addNote(note); }}
Dart
🧠 شرح
UseCase = الطبقة التي تقول "ماذا نفعل"وليس "كيف نفعل"
Dart
🧱 5) Cubit (إدارة الحالة)
📁 notes_cubit.dart
📄 الكود
import'package:flutter_bloc/flutter_bloc.dart';import'../../domain/entities/note.dart';import'../../domain/usecases/add_note_usecase.dart';import'../../domain/usecases/get_notes_usecase.dart';import'notes_state.dart';/// Cubit = مدير الحالة/// لا يعرف Supabase/// لا يعرف Model/// فقط ينادي UseCasesclassNotesCubitextendsCubit<NotesState> {finalGetNotesUseCase getNotesUseCase;finalAddNoteUseCase addNoteUseCase;NotesCubit(this.getNotesUseCase,this.addNoteUseCase, ) : super(NotesInitial());/// إضافة ملاحظةFuture<void> addNote(Note note) async {/// تنفيذ العمليةawaitaddNoteUseCase(note);/// تحديث القائمة بعد الإضافةfetchNotes(); }/// جلب البياناتFuture<void> fetchNotes() async {emit(NotesLoading());try {final notes = awaitgetNotesUseCase();emit(NotesLoaded(notes)); } catch (e) {emit(NotesError(e.toString())); } }}
Dart
🧠 شرح
Cubit = حلقة الوصل بين UI و UseCase
Dart
🧱 6) صفحة إضافة ملاحظة (UI)
📁 add_note_page.dart
📄 الكود
import'package:flutter/material.dart';import'package:flutter_bloc/flutter_bloc.dart';import'package:uuid/uuid.dart';import'../../domain/entities/note.dart';import'../cubit/notes_cubit.dart';/// هذه الصفحة مسؤولة فقط عن:/// أخذ input من المستخدمclassAddNotePageextendsStatefulWidget {constAddNotePage({super.key});@overrideStatecreateState() => _AddNotePageState();}class_AddNotePageStateextendsState {/// Controllers لجلب النص من الحقولfinal titleController = TextEditingController();final contentController = TextEditingController();@overrideWidgetbuild(BuildContext context) {returnScaffold( appBar: AppBar(title: constText("إضافة ملاحظة")), body: Padding( padding: constEdgeInsets.all(16), child: Column( children: [/// إدخال العنوانTextField( controller: titleController, ),/// إدخال المحتوىTextField( controller: contentController, ),constSizedBox(height: 20),/// زر الحفظElevatedButton( onPressed: () {/// إنشاء Notefinal note = Note( id: constUuid().v4(), title: titleController.text, content: contentController.text, );/// إرسال البيانات للـ Cubit context.read().addNote(note);/// الرجوع للصفحة السابقةNavigator.pop(context); }, child: constText("حفظ"), ), ], ), ), ); }}