checked items on db
This commit is contained in:
@@ -24,6 +24,7 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
|
|||||||
Checklist? _checklist;
|
Checklist? _checklist;
|
||||||
late Future<List<Object>> _checklistFutures;
|
late Future<List<Object>> _checklistFutures;
|
||||||
late final ChecklistProvider _checklistProvider;
|
late final ChecklistProvider _checklistProvider;
|
||||||
|
List<int> _checkedItemIds = [];
|
||||||
List<Item> _items = [];
|
List<Item> _items = [];
|
||||||
int? _selectedItemId;
|
int? _selectedItemId;
|
||||||
bool _titleEditMode = false;
|
bool _titleEditMode = false;
|
||||||
@@ -45,14 +46,22 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
|
|||||||
return Future.wait([
|
return Future.wait([
|
||||||
DbHelper.getChecklistById(checklistId),
|
DbHelper.getChecklistById(checklistId),
|
||||||
DbHelper.getItemsByChecklistId(checklistId),
|
DbHelper.getItemsByChecklistId(checklistId),
|
||||||
|
DbHelper.fetchcheckedItemIds(checklistId),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _futureBuilder(
|
Widget _futureBuilder(
|
||||||
BuildContext context, AsyncSnapshot<List<Object>> snapshot) {
|
BuildContext context, AsyncSnapshot<List<Object>> snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
_checklist = snapshot.data!.first as Checklist;
|
_checklist = snapshot.data!.elementAt(0) as Checklist;
|
||||||
_items = snapshot.data!.last as List<Item>;
|
_items = snapshot.data!.elementAt(1) as List<Item>;
|
||||||
|
_checkedItemIds = snapshot.data!.elementAt(2) as List<int>;
|
||||||
|
if (pageTitle == null) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() =>
|
||||||
|
pageTitle = _checklist!.title == ''
|
||||||
|
? 'Unnamed ${_checklist!.id}'
|
||||||
|
: _checklist!.title));
|
||||||
|
}
|
||||||
return StreamBuilder(
|
return StreamBuilder(
|
||||||
stream: DbHelper.itemsChangeEventStream,
|
stream: DbHelper.itemsChangeEventStream,
|
||||||
builder: (BuildContext context,
|
builder: (BuildContext context,
|
||||||
@@ -130,13 +139,17 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget? _itemListBuilder(BuildContext context, int index) {
|
Widget? _itemListBuilder(BuildContext context, int index) {
|
||||||
|
Item item = _items.elementAt(index);
|
||||||
return ItemListTile(
|
return ItemListTile(
|
||||||
title: _items.elementAt(index).title,
|
title: item.title,
|
||||||
description: _items.elementAt(index).description,
|
description: item.description,
|
||||||
onTap: () => _itemTapped(index),
|
onTap: () => _itemTapped(index),
|
||||||
itemSelectionChanged: (isSelected) =>
|
itemSelectionChanged: (isSelected) =>
|
||||||
_itemSelectionChanged(isSelected, index),
|
_itemSelectionChanged(isSelected, index),
|
||||||
selectionMode: selectedItemIndexes.isNotEmpty,
|
selectionMode: selectedItemIndexes.isNotEmpty,
|
||||||
|
isChecked: _checkedItemIds.contains(item.id),
|
||||||
|
onCheckedChanged: (isSelected) =>
|
||||||
|
_onItemCheckedChanged(isSelected, item.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,10 +183,12 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
|
|||||||
child: Text(pageTitle ?? ''));
|
child: Text(pageTitle ?? ''));
|
||||||
} else {
|
} else {
|
||||||
titleController.text = pageTitle ?? '';
|
titleController.text = pageTitle ?? '';
|
||||||
return Expanded(
|
return TextField(
|
||||||
child: TextField(
|
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
controller: titleController,
|
controller: titleController,
|
||||||
|
onSubmitted: (value) => _onTitleChanged(
|
||||||
|
_checklist!.id,
|
||||||
|
titleController.text,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -192,12 +207,6 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
|
|||||||
AsyncSnapshot<List<Map<String, dynamic>>> snapshot,
|
AsyncSnapshot<List<Map<String, dynamic>>> snapshot,
|
||||||
Checklist? checklist,
|
Checklist? checklist,
|
||||||
List<Item> items) {
|
List<Item> items) {
|
||||||
if (pageTitle != _checklist!.title) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() =>
|
|
||||||
pageTitle = _checklist!.title == ''
|
|
||||||
? 'Unnamed ${_checklist!.id}'
|
|
||||||
: _checklist!.title));
|
|
||||||
}
|
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
_items = DbHelper.resToItemList(snapshot.data!);
|
_items = DbHelper.resToItemList(snapshot.data!);
|
||||||
}
|
}
|
||||||
@@ -250,4 +259,12 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onItemCheckedChanged(bool isSelected, int? id) async {
|
||||||
|
if (isSelected) {
|
||||||
|
await DbHelper.insertCheckedEntry(_checklist!.id, id!);
|
||||||
|
} else {
|
||||||
|
await DbHelper.deleteCheckedEntry(_checklist!.id, id!);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import 'package:provider/provider.dart' as provider;
|
|||||||
class DbHelper {
|
class DbHelper {
|
||||||
static const checkedItemsTableName = 'checkedItems';
|
static const checkedItemsTableName = 'checkedItems';
|
||||||
static const checklistsTableName = 'checklists';
|
static const checklistsTableName = 'checklists';
|
||||||
|
static ChecklistProvider? clProvider;
|
||||||
static const itemsTableName = 'items';
|
static const itemsTableName = 'items';
|
||||||
|
|
||||||
static late final SupabaseClient _client;
|
static late final SupabaseClient _client;
|
||||||
static ChecklistProvider? clProvider;
|
|
||||||
|
|
||||||
static Future<void> init() async {
|
static Future<void> init() async {
|
||||||
await Supabase.initialize(
|
await Supabase.initialize(
|
||||||
@@ -58,6 +58,26 @@ class DbHelper {
|
|||||||
return checklists;
|
return checklists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<List<int>> fetchcheckedItemIds(int checklistId) async {
|
||||||
|
List<int> itemIdList = [];
|
||||||
|
final res = await _client
|
||||||
|
.from(checkedItemsTableName)
|
||||||
|
.select<List<Map<String, dynamic>>>('item_id');
|
||||||
|
for (final element in res) {
|
||||||
|
itemIdList.add(element['item_id']);
|
||||||
|
}
|
||||||
|
return itemIdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> insertCheckedEntry(int checklistId, int itemId) async {
|
||||||
|
final ownerId = _client.auth.currentSession!.user.id;
|
||||||
|
await _client.from(checkedItemsTableName).insert({
|
||||||
|
'id': ownerId,
|
||||||
|
'checklist_id': checklistId,
|
||||||
|
'item_id': itemId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static Future<void> updateChecklistTitle(int id, String title) async {
|
static Future<void> updateChecklistTitle(int id, String title) async {
|
||||||
await _client
|
await _client
|
||||||
.from(checklistsTableName)
|
.from(checklistsTableName)
|
||||||
@@ -155,6 +175,15 @@ class DbHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> deleteCheckedEntry(int checklistId, int itemId) async {
|
||||||
|
final ownerId = _client.auth.currentSession!.user.id;
|
||||||
|
await _client.from(checkedItemsTableName).delete().match({
|
||||||
|
'id': ownerId,
|
||||||
|
'checklist_id': checklistId,
|
||||||
|
'item_id': itemId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static Future<void> deleteItemById(int id) async {
|
static Future<void> deleteItemById(int id) async {
|
||||||
await _client.from(itemsTableName).delete().eq('id', id);
|
await _client.from(itemsTableName).delete().eq('id', id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,26 +10,28 @@ class ItemListTile extends StatefulWidget {
|
|||||||
required this.onTap,
|
required this.onTap,
|
||||||
required this.itemSelectionChanged,
|
required this.itemSelectionChanged,
|
||||||
required this.selectionMode,
|
required this.selectionMode,
|
||||||
this.isSelected = false,
|
required this.isChecked,
|
||||||
|
required this.onCheckedChanged,
|
||||||
});
|
});
|
||||||
final String title;
|
final String title;
|
||||||
final String description;
|
final String description;
|
||||||
final bool selectionMode;
|
final bool selectionMode;
|
||||||
|
final bool isChecked;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
final BoolCallback onCheckedChanged;
|
||||||
final BoolCallback itemSelectionChanged;
|
final BoolCallback itemSelectionChanged;
|
||||||
final bool isSelected;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ItemListTile> createState() => _ItemListTileState();
|
State<ItemListTile> createState() => _ItemListTileState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ItemListTileState extends State<ItemListTile> {
|
class _ItemListTileState extends State<ItemListTile> {
|
||||||
late bool isSelected;
|
late bool isChecked;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
isSelected = widget.isSelected;
|
isChecked = widget.isChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -39,19 +41,25 @@ class _ItemListTileState extends State<ItemListTile> {
|
|||||||
subtitle: Text(widget.description),
|
subtitle: Text(widget.description),
|
||||||
onTap: _onTap,
|
onTap: _onTap,
|
||||||
onLongPress: _onLongPress,
|
onLongPress: _onLongPress,
|
||||||
selected: isSelected,
|
trailing: Checkbox(
|
||||||
|
value: isChecked,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() => isChecked = value!);
|
||||||
|
widget.onCheckedChanged(value!);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onLongPress() {
|
void _onLongPress() {
|
||||||
setState(() => isSelected = true);
|
setState(() => isChecked = true);
|
||||||
widget.itemSelectionChanged(isSelected);
|
widget.itemSelectionChanged(isChecked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onTap() {
|
void _onTap() {
|
||||||
if (isSelected || widget.selectionMode) {
|
if (isChecked || widget.selectionMode) {
|
||||||
setState(() => isSelected = !isSelected);
|
setState(() => isChecked = !isChecked);
|
||||||
widget.itemSelectionChanged(isSelected);
|
widget.itemSelectionChanged(isChecked);
|
||||||
} else {
|
} else {
|
||||||
widget.onTap();
|
widget.onTap();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user