Error messages

This commit is contained in:
marcoabat
2023-08-07 22:57:42 +02:00
parent f313850205
commit 8a9ab4a435
5 changed files with 133 additions and 57 deletions

View File

@@ -2,6 +2,7 @@ import 'package:briessenchecker/models/checklist.dart';
import 'package:briessenchecker/pages/detail_checklist_page.dart'; import 'package:briessenchecker/pages/detail_checklist_page.dart';
import 'package:briessenchecker/services/checklist_provider.dart'; import 'package:briessenchecker/services/checklist_provider.dart';
import 'package:briessenchecker/services/dbhelper.dart'; import 'package:briessenchecker/services/dbhelper.dart';
import 'package:briessenchecker/services/scaffold_messenger.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -87,8 +88,12 @@ class _DashboardPageState extends State<DashboardPage> {
} }
void _onDeleteTapped() { void _onDeleteTapped() {
DbHelper.deleteChecklistByid( final checklist = checklists.elementAt(_selectedChecklistIndex!);
checklists.elementAt(_selectedChecklistIndex!).id); DbHelper.deleteChecklistByid(checklist.id);
if (!DbHelper.isOwner(checklist.ownerId)) {
Messenger.showError(
context, 'Can\'t delete checklists that aren\'t yours');
}
setState(() { setState(() {
_selectedChecklistIndex = null; _selectedChecklistIndex = null;
}); });

View File

@@ -2,9 +2,11 @@ import 'package:briessenchecker/models/checklist.dart';
import 'package:briessenchecker/models/listitem.dart'; import 'package:briessenchecker/models/listitem.dart';
import 'package:briessenchecker/services/checklist_provider.dart'; import 'package:briessenchecker/services/checklist_provider.dart';
import 'package:briessenchecker/services/dbhelper.dart'; import 'package:briessenchecker/services/dbhelper.dart';
import 'package:briessenchecker/widgets/item_detail_dialog.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../services/scaffold_messenger.dart';
import '../widgets/item_list_tile.dart'; import '../widgets/item_list_tile.dart';
class DetailChecklistPage extends StatefulWidget { class DetailChecklistPage extends StatefulWidget {
@@ -78,69 +80,21 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
void _addItemTapped() { void _addItemTapped() {
showDialog( showDialog(
context: context, context: context,
builder: (context) => _itemDetailDialog(context, null)); builder: (context) => ItemDetailDialog(checklistId: _checklist!.id));
} }
void _itemTapped(int index) { void _itemTapped(int index) {
_selectedItemId = _items.elementAt(index).id; _selectedItemId = _items.elementAt(index).id;
showDialog( showDialog(
context: context, context: context,
builder: (context) => _itemDetailDialog(context, index)).whenComplete( builder: (context) => ItemDetailDialog(
checklistId: _checklist!.id,
item: _items.elementAt(index),
)).whenComplete(
() => _selectedItemId = null, () => _selectedItemId = null,
); );
} }
Widget _itemDetailDialog(BuildContext context, int? index) {
TextEditingController titleCon = TextEditingController();
TextEditingController descCon = TextEditingController();
if (_selectedItemId != null) {
final item = _items.elementAt(index!);
titleCon.text = item.title;
descCon.text = item.description;
}
return AlertDialog(
title: const Text('additem'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: titleCon,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(
label: Text('Title'),
),
),
TextFormField(
controller: descCon,
onFieldSubmitted: (value) =>
_itemSaved(titleCon.text, descCon.text),
decoration: const InputDecoration(
label: Text('Description'),
),
),
],
),
actions: [
TextButton(
onPressed: () {
_itemSaved(titleCon.text, descCon.text);
},
child: const Text('save'),
),
],
);
}
void _itemSaved(String title, String description) {
DbHelper.addOrUpdateItem(
_checklistProvider.selectedChecklistId!,
title,
description,
_selectedItemId,
);
Navigator.of(context).pop();
}
Widget? _itemListBuilder(BuildContext context, int index) { Widget? _itemListBuilder(BuildContext context, int index) {
Item item = _items.elementAt(index); Item item = _items.elementAt(index);
return ItemListTile( return ItemListTile(
@@ -170,8 +124,17 @@ class _DetailChecklistPageState extends State<DetailChecklistPage> {
void _onDeleteItemsPressed() { void _onDeleteItemsPressed() {
List<int> itemIds = []; List<int> itemIds = [];
bool showErrorPrompt = false;
for (final itemIndex in selectedItemIndexes) { for (final itemIndex in selectedItemIndexes) {
itemIds.add(_items.elementAt(itemIndex).id!); itemIds.add(_items.elementAt(itemIndex).id!);
if (!showErrorPrompt) {
showErrorPrompt =
!DbHelper.isOwner(_items.elementAt(itemIndex).ownerId) &&
!DbHelper.isOwner(_checklist!.ownerId);
}
}
if (showErrorPrompt) {
Messenger.showError(context, 'Can\'t delete items that aren\'t yours.');
} }
DbHelper.deleteItemsById(itemIds); DbHelper.deleteItemsById(itemIds);
setState(() { setState(() {

View File

@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:briessenchecker/services/checklist_provider.dart'; import 'package:briessenchecker/services/checklist_provider.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -185,11 +187,15 @@ class DbHelper {
} }
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).onError(_onError);
} }
static Future<void> deleteItemsById(List<int> ids) async { static Future<void> deleteItemsById(List<int> ids) async {
await _client.from(itemsTableName).delete().in_('id', ids); await _client
.from(itemsTableName)
.delete()
.in_('id', ids)
.onError(_onError);
} }
static Future<void> deleteChecklistByid(int id) async { static Future<void> deleteChecklistByid(int id) async {
@@ -201,6 +207,12 @@ class DbHelper {
static Stream<AuthState> get authChangeEventStream => static Stream<AuthState> get authChangeEventStream =>
_client.auth.onAuthStateChange; _client.auth.onAuthStateChange;
static bool isOwner(String id) {
return _client.auth.currentSession!.user.id == id;
}
static User? get currentUser => _client.auth.currentUser;
static Stream<List<Map<String, dynamic>>> get checklistChangeEventStream => static Stream<List<Map<String, dynamic>>> get checklistChangeEventStream =>
_client.from(checklistsTableName).stream(primaryKey: ['id']); _client.from(checklistsTableName).stream(primaryKey: ['id']);
@@ -245,4 +257,8 @@ class DbHelper {
} }
return items; return items;
} }
static FutureOr _onError(Object error, StackTrace stackTrace) {
print(error);
}
} }

View File

@@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
class Messenger {
static void showError(BuildContext context, String error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Theme.of(context).colorScheme.error,
content: Text(
error,
style: TextStyle(color: Theme.of(context).colorScheme.onError),
),
),
);
}
}

View File

@@ -0,0 +1,77 @@
import 'package:flutter/material.dart';
import '../models/listitem.dart';
import '../services/dbhelper.dart';
class ItemDetailDialog extends StatelessWidget {
const ItemDetailDialog({
super.key,
this.item,
required this.checklistId,
});
final Item? item;
final int checklistId;
@override
Widget build(BuildContext context) {
final TextEditingController titleCon = TextEditingController();
final TextEditingController descCon = TextEditingController();
bool isOwner = true;
String dialogTitle = 'Add item';
if (item != null) {
titleCon.text = item!.title;
descCon.text = item!.description;
isOwner = DbHelper.isOwner(item!.ownerId);
isOwner ? dialogTitle = 'Edit Item' : dialogTitle = item!.title;
}
return AlertDialog(
title: Text(dialogTitle),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (isOwner)
TextFormField(
controller: titleCon,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(
label: Text('Title'),
),
),
if (isOwner)
TextFormField(
controller: descCon,
onFieldSubmitted: (value) {
_itemSaved(titleCon.text, descCon.text);
Navigator.of(context).pop();
},
decoration: const InputDecoration(
label: Text('Description'),
),
),
if (!isOwner) Text(item!.description),
],
),
actions: [
TextButton(
onPressed: () {
_itemSaved(titleCon.text, descCon.text);
Navigator.of(context).pop();
},
child: const Text('save'),
),
],
);
}
void _itemSaved(String title, String description) {
DbHelper.addOrUpdateItem(
checklistId,
title,
description,
item?.id,
);
}
}