تعديل ملاحظة (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', ...) يحدد الصف المطلوب
- هذا الملف فقط يتعامل مع SupabaseDart🧱 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
- ثم يمررها للـ DataSourceDart🧱 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 ولا UIDart🧱 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 للـ UIDart🧱 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
- نرسل للـ CubitDart🧱 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