rluv_client/lib/features/notes/screens/notes_screen.dart

256 lines
9.6 KiB
Dart
Raw Normal View History

import 'package:colorful_print/colorful_print.dart';
2023-07-27 01:40:26 -06:00
import 'package:dio/dio.dart';
2023-07-22 21:29:32 -06:00
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
2023-07-27 01:40:26 -06:00
import 'package:rluv/global/utils.dart';
import 'package:rluv/models/shared_note.dart';
2023-07-22 21:29:32 -06:00
2023-07-27 01:40:26 -06:00
import '../../../global/api.dart';
2023-07-22 21:29:32 -06:00
import '../../../global/store.dart';
2023-07-27 01:40:26 -06:00
import '../../../global/styles.dart';
import '../../../global/widgets/ui_button.dart';
2023-07-22 21:29:32 -06:00
class SharedNotesScreen extends ConsumerStatefulWidget {
const SharedNotesScreen({super.key, required this.initialData});
final Map<String, dynamic> initialData;
@override
ConsumerState<SharedNotesScreen> createState() => _SharedNotesScreenState();
}
class _SharedNotesScreenState extends ConsumerState<SharedNotesScreen> {
@override
Widget build(BuildContext context) {
final screen = MediaQuery.of(context).size;
2023-07-27 01:40:26 -06:00
final sharedNotes = ref.watch(sharedNotesProvider);
2023-07-22 21:29:32 -06:00
return Column(
children: [
const Padding(
padding: EdgeInsets.all(18.0),
child: Text(
'Notes:',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
),
2023-07-27 01:40:26 -06:00
if (sharedNotes.isEmpty) ...[
const Text('Add notes to get started:'),
],
2023-07-22 21:29:32 -06:00
if (sharedNotes.isNotEmpty)
2023-07-27 01:40:26 -06:00
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!);
2023-07-27 01:40:26 -06:00
final textStyle = TextStyle(
fontSize: 16.0,
color: colorBrightness == Brightness.light ? Colors.black54 : Colors.white70,
2023-07-27 01:40:26 -06:00
);
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))),
2023-07-27 01:40:26 -06:00
Flexible(
child: Text(
note.content.length > 80 ? "${note.content.substring(0, 75)}..." : note.content,
2023-07-27 01:40:26 -06:00
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),
2023-07-27 01:40:26 -06:00
child: NoteBottomSheet(
index: index,
),
);
});
},
2023-07-22 21:29:32 -06:00
),
2023-07-27 01:40:26 -06:00
);
},
),
2023-07-22 21:29:32 -06:00
),
2023-07-27 01:40:26 -06:00
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),
2023-07-27 01:40:26 -06:00
child: const NoteBottomSheet(
index: null,
),
);
});
}),
),
2023-07-22 21:29:32 -06:00
],
);
}
}
2023-07-27 01:40:26 -06:00
class NoteBottomSheet extends ConsumerStatefulWidget {
const NoteBottomSheet({super.key, required this.index});
final int? index;
@override
ConsumerState<NoteBottomSheet> createState() => _NoteBottomSheetState();
}
class _NoteBottomSheetState extends ConsumerState<NoteBottomSheet> {
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;
2023-07-27 01:40:26 -06:00
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)),
2023-07-27 01:40:26 -06:00
boxShadow: const [
BoxShadow(color: Colors.black26, spreadRadius: 5.0, blurRadius: 2.0, offset: Offset(0, -2))
2023-07-27 01:40:26 -06:00
]),
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),
2023-07-27 01:40:26 -06:00
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());
2023-07-27 01:40:26 -06:00
} else {
res = await ref.read(apiProvider).put('shared_note', data: newNote.toJson());
2023-07-27 01:40:26 -06:00
}
if (res.data != null && res.data['success']) {
if (widget.index == null) {
ref.read(dashboardProvider.notifier).add({'shared_notes': res.data});
2023-07-27 01:40:26 -06:00
} else {
ref.read(dashboardProvider.notifier).update({'shared_notes': res.data});
2023-07-27 01:40:26 -06:00
}
showSnack(ref: ref, text: 'Added note', type: SnackType.success);
2023-07-27 01:40:26 -06:00
} else {
showSnack(
ref: ref,
text: res.data['message'] ?? 'Unexpected error occurred',
2023-07-27 01:40:26 -06:00
type: SnackType.error);
}
} catch (err) {
showSnack(ref: ref, text: 'Unexpected error occurred', type: SnackType.error);
printColor(err, textColor: TextColor.red);
2023-07-27 01:40:26 -06:00
}
// ignore: use_build_context_synchronously
2023-07-27 01:40:26 -06:00
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;
}
}