Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/pages/categories/category_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CategoryList extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final categorysList = ref.watch(categoriesProvider);
final categorysList = ref.watch(allParentCategoriesProvider);
ref.listen(selectedCategoryProvider, (_, _) {});
return Scaffold(
appBar: AppBar(
Expand Down
78 changes: 31 additions & 47 deletions lib/pages/categories/create_edit_category_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import '../../../providers/transactions_provider.dart';
import '../../../ui/device.dart';
import '../../../ui/extensions.dart';
import 'widgets/category_icon_color_selector.dart';
import 'widgets/subcategories_list.dart';

class CreateEditCategoryPage extends ConsumerStatefulWidget {
final bool hideIncome;
Expand Down Expand Up @@ -111,8 +112,6 @@ class _CreateEditCategoryPage extends ConsumerState<CreateEditCategoryPage> {
color: categoryColor,
);
}
ref.invalidate(selectedCategoryProvider);
ref.invalidate(categoryMapProvider);
// Result from the .pop is used in lib\pages\planning_page\manage_budget_page.dart.
//
// If the category has been created correctly, result is true.
Expand Down Expand Up @@ -190,23 +189,22 @@ class _CreateEditCategoryPage extends ConsumerState<CreateEditCategoryPage> {
value: categoryType,
underline: const SizedBox(),
isExpanded: true,
items:
(widget.hideIncome
? [
CategoryTransactionType.expense,
] // Only show 'expense' if true
: CategoryTransactionType
.values) // Otherwise, show all values
.map((CategoryTransactionType type) {
return DropdownMenuItem<CategoryTransactionType>(
value: type,
child: Text(
type.toString().split('.').last.capitalize(),
style: Theme.of(context).textTheme.titleLarge,
),
);
})
.toList(),
items: CategoryTransactionType.values
.where(
(category) =>
!widget.hideIncome ||
category == CategoryTransactionType.expense,
)
.map((CategoryTransactionType type) {
return DropdownMenuItem<CategoryTransactionType>(
value: type,
child: Text(
type.name.capitalize(),
style: Theme.of(context).textTheme.titleLarge,
),
);
})
.toList(),
onChanged: (CategoryTransactionType? newType) {
if (newType != categoryType) {
setState(() => categoryType = newType!);
Expand All @@ -222,37 +220,23 @@ class _CreateEditCategoryPage extends ConsumerState<CreateEditCategoryPage> {
onIconChanged: (icon) => setState(() => categoryIcon = icon),
onColorChanged: (color) => setState(() => categoryColor = color),
),
/* temporary hided, see #178
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 16, top: 32, bottom: 8),
child: Text(
"SUBCATEGORY",
style:
Theme.of(context).textTheme.labelLarge!.copyWith(color: Theme.of(context).colorScheme.primary),
),
),
Material(
child: InkWell(
onTap: () => print("click"),
child: Ink(
width: double.infinity,
color: Theme.of(context).colorScheme.surface,
padding: const EdgeInsets.all(16),
child: Row(
children: [
const Icon(Icons.add_circle_outline_rounded, size: 30, color: grey1),
const SizedBox(width: 12),
Text(
"Add subcategory",
style: Theme.of(context).textTheme.titleSmall!.copyWith(color: grey1),
),
],
if (selectedCategory != null)
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(
left: Sizes.lg,
top: Sizes.lg,
bottom: Sizes.sm,
),
child: Text(
"SUBCATEGORY",
style: Theme.of(context).textTheme.labelLarge!.copyWith(
color: Theme.of(context).colorScheme.primary,
),
),
),
),
*/
if (selectedCategory != null)
SubcategoriesList(category: selectedCategory),
if (selectedCategory != null)
Container(
width: double.infinity,
Expand Down
192 changes: 192 additions & 0 deletions lib/pages/categories/create_edit_subcategory_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../constants/constants.dart';
import '../../../constants/style.dart';
import '../../../model/category_transaction.dart';
import '../../../providers/categories_provider.dart';
import '../../../ui/device.dart';
import 'widgets/category_icon_color_selector.dart';

class CreateEditSubcategoryPage extends ConsumerStatefulWidget {
final CategoryTransaction category;

const CreateEditSubcategoryPage({super.key, required this.category});

@override
ConsumerState<CreateEditSubcategoryPage> createState() =>
_CreateEditSubcategoryPage();
}

class _CreateEditSubcategoryPage
extends ConsumerState<CreateEditSubcategoryPage> {
final TextEditingController nameController = TextEditingController();
late CategoryTransactionType categoryType;
String categoryIcon = iconList.keys.first;
int categoryColor = 0;

@override
void initState() {
super.initState();

categoryType = widget.category.type;
categoryColor = widget.category.color;

final selectedSubcategory = ref.read(selectedSubcategoryProvider);
if (selectedSubcategory != null) {
nameController.text = selectedSubcategory.name;
categoryType = selectedSubcategory.type;
categoryIcon = selectedSubcategory.symbol;
}
}

@override
void dispose() {
nameController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final selectedSubcategory = ref.watch(selectedSubcategoryProvider);
return Scaffold(
appBar: AppBar(
title: Text(
"${selectedSubcategory == null ? "New" : "Edit"} Subcategory",
),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new),
onPressed: () => Navigator.pop(context, false),
),
),
persistentFooterDecoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
boxShadow: [
BoxShadow(
color: Theme.of(
context,
).colorScheme.primary.withValues(alpha: 0.15),
blurRadius: 5.0,
offset: const Offset(0, -1.0),
),
],
),
persistentFooterButtons: [
Padding(
padding: const EdgeInsets.fromLTRB(
Sizes.sm,
Sizes.xs,
Sizes.sm,
Sizes.sm,
),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
boxShadow: [defaultShadow],
borderRadius: BorderRadius.circular(Sizes.borderRadius),
),
child: ElevatedButton(
onPressed: () async {
if (nameController.text.isNotEmpty) {
if (selectedSubcategory != null) {
await ref
.read(categoriesProvider.notifier)
.updateSubcategory(
name: nameController.text,
icon: categoryIcon,
);
} else {
await ref
.read(categoriesProvider.notifier)
.addSubcategory(
name: nameController.text,
icon: categoryIcon,
);
}
// Result from the .pop is used in lib\pages\planning_page\manage_budget_page.dart.
//
// If the category has been created correctly, result is true.
if (context.mounted) Navigator.of(context).pop(true);
}
},
child: Text(
"${selectedSubcategory == null ? "CREATE" : "UPDATE"} SUBCATEGORY",
),
),
),
),
],
body: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(
horizontal: Sizes.lg,
vertical: Sizes.md,
),
padding: const EdgeInsets.fromLTRB(
Sizes.lg,
Sizes.md,
Sizes.lg,
0,
),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(Sizes.borderRadiusSmall),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"NAME",
style: Theme.of(context).textTheme.labelLarge!.copyWith(
color: Theme.of(context).colorScheme.primary,
),
),
TextField(
controller: nameController,
decoration: const InputDecoration(
hintText: "Category name",
),
style: Theme.of(context).textTheme.titleLarge,
),
],
),
),
CategoryIconColorSelector(
selectedIcon: categoryIcon,
selectedColor: categoryColor,
onIconChanged: (icon) => setState(() => categoryIcon = icon),
),
if (selectedSubcategory != null)
Container(
width: double.infinity,
padding: const EdgeInsets.all(Sizes.lg),
child: TextButton.icon(
onPressed: () => ref
.read(categoriesProvider.notifier)
.removeCategory(selectedSubcategory.id!)
.whenComplete(() {
if (context.mounted) {
Navigator.of(context).pop();
}
}),
style: TextButton.styleFrom(
side: const BorderSide(color: red, width: 1),
),
icon: const Icon(Icons.delete_outlined, color: red),
label: Text(
"Delete subcategory",
style: Theme.of(
context,
).textTheme.bodyLarge!.copyWith(color: red),
),
),
),
],
),
),
);
}
}
Loading