diff --git a/lib/core/di_container.dart b/lib/core/di_container.dart index c1c484c..e99aa36 100644 --- a/lib/core/di_container.dart +++ b/lib/core/di_container.dart @@ -1,5 +1,6 @@ import 'package:get_it/get_it.dart'; import 'package:noteapp/bloc/fetch_notes/fetch_notes_bloc.dart'; +import 'package:noteapp/bloc/update_note/update_note_bloc.dart'; import '../bloc/save_new_note/save_new_note_bloc.dart'; import '../data/implementation/local_notes_repository.dart'; @@ -19,4 +20,8 @@ void setupLocator() { getIt.registerFactory( () => FetchNotesBloc(repository: getIt()), ); + + getIt.registerFactory( + () => UpdateNoteBloc(repository: getIt()), + ); } diff --git a/lib/core/go_router.dart b/lib/core/go_router.dart index 70df59e..526b3b8 100644 --- a/lib/core/go_router.dart +++ b/lib/core/go_router.dart @@ -1,4 +1,5 @@ import 'package:go_router/go_router.dart'; +import 'package:noteapp/ui/screens/edit_note.dart'; import 'package:noteapp/ui/screens/note_view.dart'; import '../models/note.dart'; @@ -23,6 +24,12 @@ GoRouter appRouter = GoRouter( GoRoute( path: '/NoteView', builder: (context, state) => NoteView(note: state.extra as Note), + routes: [ + GoRoute( + path: 'EditNote', + builder: (context, state) => EditNote(state.extra as Note), + ), + ], ), ], ); diff --git a/lib/ui/screens/edit_note.dart b/lib/ui/screens/edit_note.dart new file mode 100644 index 0000000..18518fe --- /dev/null +++ b/lib/ui/screens/edit_note.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; + +import '../../bloc/update_note/update_note_bloc.dart'; +import '../../models/note.dart'; +import '../widgets/go_back_button.dart'; +import '../widgets/square_icon_button.dart'; + +class EditNote extends StatefulWidget { + final Note oldNote; + const EditNote( + this.oldNote, { + super.key, + }); + + @override + State createState() => _EditNoteState(); +} + +class _EditNoteState extends State { + late final UpdateNoteBloc bloc; + late final TextEditingController titleController; + late final TextEditingController contentController; + + @override + void initState() { + super.initState(); + bloc = GetIt.I.get(); + titleController = TextEditingController(text: widget.oldNote.title); + contentController = TextEditingController(text: widget.oldNote.content); + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => bloc, + child: BlocListener( + listener: (context, state) { + if (state is UpdateNoteInSuccess) context.pop(); + }, + child: Scaffold( + appBar: AppBar( + leadingWidth: 75, + leading: const GoBackButton(), + actions: [ + SquareIconButton( + icon: const Icon(Icons.visibility_outlined), + onPressed: () => context.push( + '/NoteView', + extra: Note( + title: titleController.text, + content: contentController.text, + ), + ), + ), + const SizedBox(width: 25), + SaveButton( + titleController: titleController, + noteController: contentController, + bloc: bloc, + oldNote: widget.oldNote, + ), + const SizedBox(width: 25), + ], + ), + body: Container( + margin: const EdgeInsets.symmetric(horizontal: 32), + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 40), + TextField( + controller: titleController, + decoration: const InputDecoration( + hintText: 'Title', + border: InputBorder.none, + ), + maxLines: null, + style: Theme.of(context).textTheme.titleLarge, + ), + const SizedBox(height: 40), + TextField( + controller: contentController, + decoration: const InputDecoration( + hintText: 'Note', + border: InputBorder.none, + ), + style: Theme.of(context).textTheme.bodyLarge, + maxLines: null, + ), + ], + ), + ), + ), + ), + ), + ); + } +} + +class SaveButton extends StatelessWidget { + const SaveButton({ + super.key, + required this.titleController, + required this.noteController, + required this.bloc, + required this.oldNote, + }); + + final Note oldNote; + final TextEditingController titleController; + final TextEditingController noteController; + final UpdateNoteBloc bloc; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is UpdateNoteInProgress) { + return const CircularProgressIndicator.adaptive(); + } + return SquareIconButton( + icon: const Icon(Icons.save_outlined), + onPressed: () { + if (titleController.text.trim().isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('The title cannot be empty')), + ); + return; + } + final Note newNote = Note( + title: titleController.text, + content: noteController.text, + ); + bloc.add(UpdateNote(oldNote: oldNote, newNote: newNote)); + }, + ); + }, + ); + } +} diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart index 397040b..12dafbf 100644 --- a/lib/ui/screens/home_screen.dart +++ b/lib/ui/screens/home_screen.dart @@ -24,7 +24,7 @@ class HomeScreen extends StatefulWidget { State createState() => _HomeScreenState(); } -class _HomeScreenState extends State { +class _HomeScreenState extends State with RouteAware { late final FetchNotesBloc bloc; late final GlobalKey refreshIndicatorKey; diff --git a/lib/ui/screens/note_view.dart b/lib/ui/screens/note_view.dart index 23ee411..424ba90 100644 --- a/lib/ui/screens/note_view.dart +++ b/lib/ui/screens/note_view.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:noteapp/ui/widgets/square_icon_button.dart'; import '../../models/note.dart'; import '../widgets/go_back_button.dart'; @@ -17,6 +19,18 @@ class NoteView extends StatelessWidget { appBar: AppBar( leadingWidth: 75, leading: const GoBackButton(), + actions: [ + SquareIconButton( + icon: const Icon(Icons.edit), + onPressed: () => context + .push( + '/NoteView/EditNote', + extra: note, + ) + .then((value) => context.pop()), + ), + const SizedBox(width: 25), + ], ), body: SingleChildScrollView( child: Container(