Compare commits

...

5 Commits

Author SHA1 Message Date
andrei a7f4838ce9 refresh checklist page 2021-11-03 18:45:37 -04:00
andrei 65636ee956 Editable and lockable text field for item labels 2021-11-03 18:36:06 -04:00
andrei aac93df46b updated locking icons and functionality 2021-11-03 18:07:00 -04:00
andrei 055fb7241d lockable items in templates 2021-11-03 17:42:42 -04:00
andrei 6b6c96ea43 checklist page with editing 2021-11-03 17:28:03 -04:00
5 changed files with 169 additions and 8 deletions

View File

@ -105,6 +105,7 @@ class _AddFormState extends State<AddForm> {
_listLabel,
isTemplate: type.index == 1,
));
// TODO implement template starting point
Navigator.pop(context); // TODO replace route with checklist page
}
},

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'add_form.dart';
import 'check_list.dart';
import 'db_helper.dart';
import 'data_util.dart' as data;
@ -15,8 +16,11 @@ class BoxChecker extends StatelessWidget {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.from(colorScheme: ColorScheme.dark()).copyWith(
canvasColor: Colors.black,
shadowColor: Colors.blueGrey,
canvasColor: Colors.blueGrey[900],
cardColor: Colors.grey[800],
scaffoldBackgroundColor: Colors.black12,
shadowColor: Colors.black38,
toggleableActiveColor: Colors.blue,
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.blue,
),
@ -80,10 +84,18 @@ class _MainListPageState extends State<MainListPage> {
child: ListView.builder(
itemCount: lists.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {},
return Card(
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CheckList(id: lists[index].id!)));
},
title: Text(lists[index].name),
subtitle: Text(lists[index].id.toString()),
),
);
})),
bottomNavigationBar: BottomNavigationBar(

125
lib/check_list.dart Normal file
View File

@ -0,0 +1,125 @@
import 'package:flutter/material.dart';
import 'data_util.dart' as data;
import 'db_helper.dart';
class CheckList extends StatefulWidget {
const CheckList({Key? key, required this.id}) : super(key: key);
final int id;
@override
State<StatefulWidget> createState() => _CheckList(id);
}
class _CheckList extends State<CheckList> {
_CheckList(this.id);
final int id;
bool _editable = false;
data.List? listData;
List<data.Check> list = [];
void _loadList() async {
var rows = await DBHelper.dbHelper.getList(id);
list.clear();
setState(() {
for (var row in rows) {
list.add(data.Check.fromMap(row));
}
});
}
void _loadListData() async {
var rows = await DBHelper.dbHelper.getListData(id);
listData = (rows.isNotEmpty) ? data.List.fromMap(rows[0]) : null;
}
void _updateItem(data.Check item) async {
DBHelper.dbHelper.updateItem(item);
}
void _toggleEditable() {
setState(() {
_editable = !_editable;
});
}
@override
void initState() {
_loadListData();
_loadList();
super.initState();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text((listData != null) ? listData!.name : 'Check List: $id'),
actions: (listData != null && listData!.isTemplate! && !_editable)
? [
IconButton(
onPressed: () => _toggleEditable(),
icon: const Icon(Icons.lock))
]
: (listData != null && listData!.isTemplate!)
? [
IconButton(
onPressed: () => _toggleEditable(),
icon: const Icon(Icons.lock_open))
]
: [],
),
body: RefreshIndicator(
onRefresh: () async {
_loadListData();
_loadList();
},
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return Card(
child: CheckboxListTile(
title: TextFormField(
enabled: (listData != null &&
(!listData!.isTemplate! || _editable)),
decoration: InputDecoration(border: InputBorder.none),
initialValue: list[index].text,
onChanged: (value) {
list[index].text = value;
_updateItem(list[index]);
},
),
controlAffinity: ListTileControlAffinity.leading,
value: list[index].value,
onChanged:
(listData != null && (!listData!.isTemplate! || _editable))
? ((value) {
_updateItem(list[index]);
setState(() {
list[index].value = value!;
});
})
: null,
),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
if (listData!.isTemplate! && !_editable) {
ScaffoldMessenger.of(context)
..clearSnackBars()
..showSnackBar(SnackBar(content: Text("Template is locked")));
return;
}
// TODO implment adding items to lists
},
child: const Icon(Icons.check_box_outlined),
tooltip: "Add Item",
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
);
}
}

View File

@ -33,13 +33,13 @@ class Check {
var map = Map<String, dynamic>();
if (id != null) map["id"] = this.id;
map["check_text"] = this.text;
map["value"] = this.value as int;
map["status"] = this.value ? 1 : 0;
if (listID != null) map["list_id"] = this.listID! as int;
return map;
}
static Check fromMap(Map<String, dynamic> map) {
return Check(map["check_text"], map["value"] == 1,
return Check(map["check_text"], map["status"] == 1,
id: map["id"], listID: map["list_id"]);
}
}

View File

@ -59,9 +59,32 @@ class DBHelper {
return db.query("List", where: "is_template = ?", whereArgs: [type.index]);
}
Future<List<Map<String, dynamic>>> getList(int id) async {
Database db = await database;
return db.query("Item", where: "list_id = ?", whereArgs: [id]);
}
Future<List<Map<String, dynamic>>> getListData(int id) async {
Database db = await database;
return db.query("List", where: "id = ?", whereArgs: [id]);
}
Future<int> insertList(data.List l) async {
Database db = await database;
return db.insert("List", l.toMap());
}
Future<int> updateItem(data.Check item) async {
Database db = await database;
return db.update(
"Item",
item.toMap(),
where: 'id = ?',
whereArgs: [item.id],
);
}
}