Error messages
This commit is contained in:
@@ -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;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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(() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
lib/services/scaffold_messenger.dart
Normal file
15
lib/services/scaffold_messenger.dart
Normal 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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
77
lib/widgets/item_detail_dialog.dart
Normal file
77
lib/widgets/item_detail_dialog.dart
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user