import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rluv/global/utils.dart'; import 'package:rluv/models/shared_note.dart'; import '../../../global/api.dart'; import '../../../global/store.dart'; import '../../../global/styles.dart'; import '../../../global/widgets/ui_button.dart'; class SharedNotesScreen extends ConsumerStatefulWidget { const SharedNotesScreen({super.key, required this.initialData}); final Map initialData; @override ConsumerState createState() => _SharedNotesScreenState(); } class _SharedNotesScreenState extends ConsumerState { @override Widget build(BuildContext context) { final screen = MediaQuery.of(context).size; final sharedNotes = ref.watch(sharedNotesProvider); return Column( children: [ const Padding( padding: EdgeInsets.all(18.0), child: Text( 'Notes:', style: TextStyle(fontSize: 20), textAlign: TextAlign.center, ), ), if (sharedNotes.isEmpty) ...[ const Text('Add notes to get started:'), ], if (sharedNotes.isNotEmpty) SizedBox( height: screen.height * 0.65, child: GridView.builder( itemCount: sharedNotes.length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, ), itemBuilder: (BuildContext context, int index) { final note = sharedNotes[index]; final colorBrightness = note.color == null ? Brightness.light : getBrightness(note.color!); final textStyle = TextStyle( fontSize: 16.0, color: colorBrightness == Brightness.light ? Colors.black54 : Colors.white70, ); return Padding( padding: const EdgeInsets.all(8.0), child: InkWell( child: Card( color: note.color ?? Styles.washedStone, child: SizedBox( width: screen.width * 0.4, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ FittedBox(child: Text(note.title, style: const TextStyle(fontSize: 20))), Flexible( child: Text( note.content.length > 80 ? "${note.content.substring(0, 75)}..." : note.content, style: textStyle, ), ), ], ), ), ), ), onTap: () { showModalBottomSheet( isScrollControlled: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), ), backgroundColor: Colors.transparent, context: context, builder: (BuildContext context) { return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: NoteBottomSheet( index: index, ), ); }); }, ), ); }, ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 18.0, horizontal: 12.0), child: UiButton( text: 'Add Note', onPressed: () { showModalBottomSheet( isScrollControlled: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), ), backgroundColor: Colors.transparent, context: context, builder: (BuildContext context) { return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: const NoteBottomSheet( index: null, ), ); }); }), ), ], ); } } class NoteBottomSheet extends ConsumerStatefulWidget { const NoteBottomSheet({super.key, required this.index}); final int? index; @override ConsumerState createState() => _NoteBottomSheetState(); } class _NoteBottomSheetState extends ConsumerState { late final SharedNote? oldNote; late SharedNote newNote; final titleFocusNode = FocusNode(); final contentFocusNode = FocusNode(); late final TextEditingController titleController; late final TextEditingController contentController; @override void initState() { super.initState(); if (widget.index == null) { oldNote = null; final family = ref.read(familyProvider); final user = ref.read(userProvider); newNote = SharedNote( familyId: family!.id, createdByUserId: user!.id!, title: 'Title', content: '', tagIds: [], color: Styles.washedStone, isMarkdown: false, ); } else { oldNote = ref.read(sharedNotesProvider).elementAt(widget.index!); newNote = SharedNote.copy(oldNote!); } titleController = TextEditingController(text: newNote.title); contentController = TextEditingController(text: newNote.content); WidgetsBinding.instance.addPostFrameCallback( (timeStamp) => titleFocusNode.requestFocus(), ); } @override Widget build(BuildContext context) { final screen = MediaQuery.of(context).size; return Container( width: screen.width, decoration: BoxDecoration( color: newNote.color ?? Styles.washedStone, borderRadius: const BorderRadius.only(topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)), boxShadow: const [ BoxShadow(color: Colors.black26, spreadRadius: 5.0, blurRadius: 2.0, offset: Offset(0, -2)) ]), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( style: const TextStyle(fontSize: 18.0), maxLines: 1, focusNode: titleFocusNode, textAlign: TextAlign.left, controller: titleController, // decoration: Styles.inputLavenderBubble(), ), TextField( style: const TextStyle(fontSize: 18.0), maxLines: 6, focusNode: contentFocusNode, textAlign: TextAlign.left, controller: contentController, // decoration: Styles.inputLavenderBubble(), ), Padding( padding: const EdgeInsets.symmetric(vertical: 28.0, horizontal: 36.0), child: UiButton( onPressed: !noteChanged(oldNote, newNote) ? null : () async { newNote.content = contentController.text; newNote.title = titleController.text; try { Response? res; if (widget.index == null) { res = await ref.read(apiProvider).post('shared_note', data: newNote.toJson()); } else { res = await ref.read(apiProvider).put('shared_note', data: newNote.toJson()); } if (res.data != null && res.data['success']) { if (widget.index == null) { ref.read(dashboardProvider.notifier).add({'shared_notes': res.data}); } else { ref.read(dashboardProvider.notifier).update({'shared_notes': res.data}); } showSnack(ref: ref, text: 'Added note', type: SnackType.success); } else { showSnack( ref: ref, text: res.data['message'] ?? 'Unexpected error occurred', type: SnackType.error); } } catch (err) { showSnack(ref: ref, text: 'Unexpected error occurred', type: SnackType.error); print(err); } // ignore: use_build_context_synchronously Navigator.pop(context); }, text: 'Save', ), ), ], ), ), ); } bool noteChanged(SharedNote? n, SharedNote m) { if (n == null) return true; if (n.content != m.content) return true; if (n.title != m.content) return true; if (n.tagIds != m.tagIds) return true; if (n.color != m.color) return true; return false; } }