تعديل الملاحظة

تعديل ملاحظة (Edit Note) في صفحة مستقلة

🧭 الفلو الكامل
ضغط على الملاحظة / زر تعديل

فتح صفحة EditNotePage (مع note)

تعديل الحقول

Cubit.updateNote()

UseCase

Repository

DataSource (update)

Supabase

emit(NoteUpdated)

SnackBar + fetchNotes()
Dart
🧱 1) DataSource (تنفيذ التعديل)
📁 notes_remote_datasource.dart
import 'package:supabase_flutter/supabase_flutter.dart';
import '../models/note_model.dart';

class NotesRemoteDataSource {
  final SupabaseClient client;

  NotesRemoteDataSource(this.client);

  /// 🔥 تحديث ملاحظة
  Future<void> updateNote(NoteModel note) async {
    /// update = تعديل الصف
    /// eq = where id = note.id
    await client
        .from('notes')
        .update(note.toJson())
        .eq('id', note.id);
  }
}
Dart

🧠 الشرح

- update(...) يرسل القيم الجديدة
- eq('id', ...) يحدد الصف المطلوب
- هذا الملف فقط يتعامل مع Supabase
Dart
🧱 2) Repository (Interface)
📁 notes_repository.dart
import '../entities/note.dart';

abstract class NotesRepository {
  Future<void> updateNote(Note note);
}
Dart
🧠 الشرح
Domain يعرّف العملية فقط (Update)
ولا يعرف كيف تُنفّذ
Dart
🧱 3) 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';

class NotesRepositoryImpl implements NotesRepository {
  final NotesRemoteDataSource remote;

  NotesRepositoryImpl(this.remote);

  @override
  Future<void> updateNote(Note note) async {
    /// تحويل Entity → Model
    final model = NoteModel(
      id: note.id,
      title: note.title,
      content: note.content,
    );

    /// إرسال التعديل للـ API
    await remote.updateNote(model);
  }
}
Dart
🧠 الشرح
- يحول Note (Entity) إلى NoteModel
- ثم يمررها للـ DataSource
Dart
🧱 4) UseCase
📁 update_note_usecase.dart
import '../entities/note.dart';
import '../repository/notes_repository.dart';

class UpdateNoteUseCase {
  final NotesRepository repo;

  UpdateNoteUseCase(this.repo);

  /// call() يسمح بالاستدعاء المباشر
  Future<void> call(Note note) async {
    await repo.updateNote(note);
  }
}
Dart
🧠 الشرح
يمثل "عملية التعديل" فقط
لا يعرف Supabase ولا UI
Dart
🧱 5) State (إضافة حالة نجاح)
📁 notes_state.dart
class NoteUpdated extends NotesState {}
Dart

🧠 الشرح

نستخدمها لإظهار SnackBar عند النجاح
Dart
🧱 6) Cubit
📁 notes_cubit.dart
import '../../domain/usecases/update_note_usecase.dart';

class NotesCubit extends Cubit<NotesState> {
  final UpdateNoteUseCase updateNoteUseCase;

  NotesCubit(
    this.getNotesUseCase,
    this.addNoteUseCase,
    this.deleteNoteUseCase,
    this.updateNoteUseCase,
  ) : super(NotesInitial());

  /// 🔥 تعديل ملاحظة
  Future<void> updateNote(Note note) async {
    try {
      await updateNoteUseCase(note);

      /// إشعار النجاح
      emit(NoteUpdated());

      /// تحديث القائمة
      fetchNotes();
    } catch (e) {
      emit(NotesError(e.toString()));
    }
  }
}
Dart
🧠 الشرح
Cubit ينفذ العملية عبر UseCase
ثم يرسل State للـ UI
Dart
🧱 7) صفحة التعديل (UI)
📁 edit_note_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../domain/entities/note.dart';
import '../cubit/notes_cubit.dart';

class EditNotePage extends StatefulWidget {
  final Note note;

  const EditNotePage({super.key, required this.note});

  @override
  State<EditNotePage> createState() => _EditNotePageState();
}

class _EditNotePageState extends State<EditNotePage> {
  late TextEditingController titleController;
  late TextEditingController contentController;

  @override
  void initState() {
    super.initState();

    /// تعبئة الحقول بالقيم الحالية
    titleController = TextEditingController(text: widget.note.title);
    contentController = TextEditingController(text: widget.note.content);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("تعديل الملاحظة")),

      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [

            TextField(
              controller: titleController,
              decoration: const InputDecoration(labelText: "العنوان"),
            ),

            TextField(
              controller: contentController,
              decoration: const InputDecoration(labelText: "المحتوى"),
            ),

            const SizedBox(height: 20),

            ElevatedButton(
              onPressed: () {

                /// إنشاء note جديد بنفس id
                final updatedNote = Note(
                  id: widget.note.id,
                  title: titleController.text,
                  content: contentController.text,
                );

                /// إرسال للـ Cubit
                context.read<NotesCubit>().updateNote(updatedNote);

                Navigator.pop(context);
              },
              child: const Text("حفظ التعديل"),
            ),
          ],
        ),
      ),
    );
  }
}
Dart

🧠 الشرح

- نستقبل note من الصفحة السابقة
- نعبّي الحقول بالقيم الحالية
- عند الضغط: ننشئ note جديد بنفس id
- نرسل للـ Cubit
Dart
🧱 8) فتح صفحة التعديل
داخل NoteCard أو DetailsPage
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => EditNotePage(note: note),
  ),
);
Dart
🧱 9) SnackBar
📁 notes_page.dart
if (state is NoteUpdated) {
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text("تم تعديل الملاحظة")),
  );
}
Dart
💥 الربط النهائي
EditPage

Cubit.updateNote()

UseCase

Repository

DataSource

Supabase

emit(NoteUpdated)

SnackBar

fetchNotes()

UI يتحدث
Dart
🧠 الخلاصة الذهبية
التعديل = نفس الإضافة لكن مع id ثابت
Dart