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

289 lines
10 KiB
Dart
Raw Normal View History

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';
import 'package:helpers/helpers/misc_build/build_media.dart';
2023-07-27 01:40:26 -06:00
import 'package:helpers/helpers/print.dart';
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) {
2023-07-27 01:40:26 -06:00
final screen = BuildMedia(context).size;
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!);
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,
2023-08-17 13:34:30 -06:00
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,
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,
),
);
});
},
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),
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 = BuildMedia(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)
2023-08-17 13:34:30 -06:00
.post('shared_note', data: newNote.toJson());
2023-07-27 01:40:26 -06:00
} else {
res = await ref
.read(apiProvider)
2023-08-17 13:34:30 -06:00
.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});
} 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);
printRed(err);
}
// 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;
}
}