Categories page works!
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ltx_flutter/appwrite/auth_api.dart';
|
||||
import 'package:ltx_flutter/appwrite/database_api.dart';
|
||||
import 'package:ltx_flutter/appwrite/categories_api.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AccountPage extends StatefulWidget {
|
||||
const AccountPage({Key? key}) : super(key: key);
|
||||
@@ -10,8 +14,47 @@ class AccountPage extends StatefulWidget {
|
||||
class _AccountPageState extends State<AccountPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(child: Text("Account")),
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
Card(
|
||||
child: Consumer<AuthAPI>(builder: (context, account, child) {
|
||||
return ListTile(
|
||||
leading: Icon(Icons.person),
|
||||
title: Text("Account"),
|
||||
trailing: Text("${account.username}"),
|
||||
);
|
||||
}),
|
||||
),
|
||||
Card(
|
||||
child:
|
||||
Consumer<DatabaseAPI>(builder: (context, entries, child) {
|
||||
return ListTile(
|
||||
leading: Icon(Icons.edit_note),
|
||||
title: Text("Entries"),
|
||||
trailing: Text("${entries.total}"),
|
||||
);
|
||||
}),
|
||||
),
|
||||
Card(
|
||||
child: Consumer<CategoriesAPI>(
|
||||
builder: (context, categories, child) {
|
||||
return ListTile(
|
||||
leading: Icon(Icons.category),
|
||||
title: Text("Categories"),
|
||||
trailing: Text("${categories.total}"),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Placeholder(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:ltx_flutter/appwrite/categories_api.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:appwrite/models.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
|
||||
class CategoriesPage extends StatefulWidget {
|
||||
const CategoriesPage({Key? key}) : super(key: key);
|
||||
@@ -10,53 +12,218 @@ class CategoriesPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _CategoriesPageState extends State<CategoriesPage> {
|
||||
final api = CategoriesAPI();
|
||||
late List<Document>? categories = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
loadCategories();
|
||||
}
|
||||
|
||||
Future loadCategories() async {
|
||||
try {
|
||||
final value = await api.getCategories();
|
||||
setState(() {
|
||||
categories = value.documents;
|
||||
});
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: loadCategories,
|
||||
child: Center(
|
||||
child: ListView.builder(
|
||||
itemCount: categories!.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= categories!.length || categories!.isEmpty) {
|
||||
return ListTile(
|
||||
leading: Text("New Category"),
|
||||
);
|
||||
} else {
|
||||
Document? category = categories?[index];
|
||||
Color backgroundColor =
|
||||
Color(int.parse("0x${category!.data['color']}"));
|
||||
Color textColor = backgroundColor.computeLuminance() > 0.2
|
||||
? Colors.black
|
||||
: Colors.white;
|
||||
return ListTile(
|
||||
tileColor: backgroundColor,
|
||||
textColor: textColor,
|
||||
leading: Text(category.data['number'].toString()),
|
||||
title: Text(category.data['name']),
|
||||
);
|
||||
return Scaffold(
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const NewCategoryPage()),
|
||||
).then((value) {
|
||||
setState(() {});
|
||||
}),
|
||||
tooltip: "New Category",
|
||||
child: Icon(Icons.add),
|
||||
),
|
||||
body: Consumer<CategoriesAPI>(builder: (context, categories, child) {
|
||||
return ListView.builder(
|
||||
itemCount: categories.total + 1,
|
||||
itemBuilder: (context, i) {
|
||||
if (i < categories.total) {
|
||||
Category category = categories.get(i);
|
||||
if (!category.hasParent() && category.number != 0) {
|
||||
return Column(
|
||||
children: [
|
||||
Divider(
|
||||
thickness: 1,
|
||||
),
|
||||
CategoryRow(category: category),
|
||||
],
|
||||
);
|
||||
}
|
||||
return CategoryRow(category: category);
|
||||
}
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CategoryRow extends StatelessWidget {
|
||||
const CategoryRow({
|
||||
super.key,
|
||||
required this.category,
|
||||
});
|
||||
|
||||
final Category category;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
color: category.backgroundColor,
|
||||
child: SizedBox.square(
|
||||
dimension: 70,
|
||||
child: Center(
|
||||
child: Text(
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: category.foregroundColor,
|
||||
fontSize: 18,
|
||||
),
|
||||
category.number.toString())),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: category.leftPadding()),
|
||||
child: Text(
|
||||
style: TextStyle(
|
||||
fontSize: 17,
|
||||
),
|
||||
category.name,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Text(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white38,
|
||||
),
|
||||
"${category.description}",
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NewCategoryPage extends StatefulWidget {
|
||||
const NewCategoryPage({super.key});
|
||||
|
||||
@override
|
||||
State<NewCategoryPage> createState() => _NewCategoryPageState();
|
||||
}
|
||||
|
||||
class _NewCategoryPageState extends State<NewCategoryPage> {
|
||||
String _name = "";
|
||||
final _formKey = GlobalKey<FormBuilderState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_name = "New Category";
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CategoriesAPI api = context.watch<CategoriesAPI>();
|
||||
saveCategory(form, context) {
|
||||
var name = form?.fields['categoryName'].value;
|
||||
var number = form?.fields['categoryNumber'].value;
|
||||
var color = form?.fields['categoryColor'].value;
|
||||
var description = form?.fields['categoryDescription'].value;
|
||||
var parent = form?.fields['categoryParent'].value;
|
||||
api.addCategory(
|
||||
name: name,
|
||||
number: double.parse(number),
|
||||
color: color,
|
||||
description: description,
|
||||
parentId: int.parse(parent),
|
||||
);
|
||||
Navigator.pop(context);
|
||||
api.getCategories();
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("New Category"),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(left: 50, right: 50),
|
||||
child: Column(
|
||||
children: [
|
||||
FormBuilder(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 25),
|
||||
FormBuilderTextField(
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Number",
|
||||
),
|
||||
name: 'categoryNumber',
|
||||
),
|
||||
SizedBox(height: 25),
|
||||
FormBuilderTextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Name",
|
||||
),
|
||||
name: 'categoryName',
|
||||
),
|
||||
SizedBox(height: 25),
|
||||
Consumer<CategoriesAPI>(
|
||||
builder: (context, categories, child) {
|
||||
print(categories.colors);
|
||||
return FormBuilderDropdown(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Color",
|
||||
),
|
||||
items: [
|
||||
for (var c in categories.colors)
|
||||
DropdownMenuItem(
|
||||
value: c.hex,
|
||||
child: Container(
|
||||
decoration:
|
||||
BoxDecoration(color: c.backgroundColor()),
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Text(
|
||||
c.name(),
|
||||
style: TextStyle(color: c.foregroundColor()),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
name: 'categoryColor',
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 25),
|
||||
FormBuilderTextField(
|
||||
name: 'categoryDescription',
|
||||
decoration: InputDecoration(
|
||||
labelText: "Description",
|
||||
),
|
||||
),
|
||||
SizedBox(height: 25),
|
||||
FormBuilderTextField(
|
||||
keyboardType: TextInputType.number,
|
||||
name: 'categoryParent',
|
||||
decoration: InputDecoration(
|
||||
labelText: "Parent",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40),
|
||||
OutlinedButton(
|
||||
onPressed: () => saveCategory(_formKey.currentState, context),
|
||||
child: Text("Save"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:appwrite/appwrite.dart';
|
||||
import 'package:ltx_flutter/appwrite/appwrite.dart';
|
||||
import 'package:ltx_flutter/appwrite/auth_api.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:spreadsheet_table/spreadsheet_table.dart';
|
||||
import 'package:pluto_grid/pluto_grid.dart';
|
||||
import 'package:ltx_flutter/appwrite/appwrite.dart';
|
||||
import 'package:ltx_flutter/appwrite/auth_api.dart';
|
||||
import 'package:ltx_flutter/appwrite/database_api.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:appwrite/models.dart';
|
||||
|
||||
@@ -11,7 +11,7 @@ class TabsPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _TabsPageState extends State<TabsPage> {
|
||||
int _selectedIndex = 0;
|
||||
int _selectedIndex = 2;
|
||||
|
||||
static const _widgets = [TodayPage(), CategoriesPage(), AccountPage()];
|
||||
|
||||
@@ -25,7 +25,7 @@ class _TabsPageState extends State<TabsPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("LTX Android"),
|
||||
title: Text("Flutter"),
|
||||
),
|
||||
body: _widgets.elementAt(_selectedIndex),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:ltx_flutter/appwrite/appwrite.dart';
|
||||
import 'dart:math' as math;
|
||||
import 'package:ltx_flutter/appwrite/auth_api.dart';
|
||||
import 'package:ltx_flutter/appwrite/database_api.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -92,6 +93,38 @@ class _TodayPageState extends State<TodayPage> {
|
||||
},
|
||||
).toList()),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
color: Colors.black,
|
||||
child: Row(
|
||||
children: List<int>.generate(10, (i) => i).map(
|
||||
(e) {
|
||||
var generatedColor =
|
||||
math.Random().nextInt(Colors.primaries.length);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
child: FilledButton(
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all<
|
||||
RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.zero,
|
||||
side: BorderSide(color: Colors.white))),
|
||||
backgroundColor: MaterialStateProperty.all(
|
||||
Colors.primaries[generatedColor]),
|
||||
),
|
||||
onLongPress: () =>
|
||||
print("Long pressed ${e.toString()}"),
|
||||
onPressed: () => print("Tapped ${e.toString()}"),
|
||||
child: Text(e.toString()),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user