From 9a24b913dbac41f84378681cb014a3875064f018 Mon Sep 17 00:00:00 2001 From: Selva Date: Sat, 7 Sep 2024 16:36:13 +0530 Subject: [PATCH] new color picker and bug fixes --- lib/colors.dart | 32 ++++++++ lib/screens/accounts/accounts_controller.dart | 1 + lib/screens/accounts/accounts_model.dart | 15 ++-- .../categories/add_category_controller.dart | 2 + .../categories/add_edit_category_screen.dart | 76 +++++++++++++++---- lib/screens/categories/category_model.dart | 2 +- .../dashboard/dashboard_controller.dart | 16 +++- lib/screens/dashboard/dashboard_screen.dart | 14 +++- lib/utils.dart | 12 ++- pubspec.lock | 12 +-- pubspec.yaml | 5 +- 11 files changed, 149 insertions(+), 38 deletions(-) diff --git a/lib/colors.dart b/lib/colors.dart index 4ee24c1..e9f0ed7 100644 --- a/lib/colors.dart +++ b/lib/colors.dart @@ -10,6 +10,38 @@ class AppColors { static const darkGreyColor = Color(0xff1c1b1f); static const errorColor = Colors.redAccent; static const successColor = Colors.green; + static const List categoryColors = [ + Color(0xFF0A73EB), // Ink Blue + Color(0xFF26A942), // Grass Green + Color(0xFFDE3535), // Danger Red + Color(0xFF9A3CEC), // Voilet + Color(0xFF7CD913), // Parrot Green + Color(0xFFF74186), // Candy Pink + Color(0xFFF6B041), // Fanta + Color(0xFF5DDFEE), // Cyan + Color(0xFFFF6F00), // Dark Orange + Color(0xFFA9B63F), // Pop Green + Color(0xFF001757), // Navy Blue + Color(0xFF2CC990), // Distember Green + Color(0xFFEE8C3D), // Biscuit + Color(0xFF39B4FF), // Dark Sky Blue + Color(0xFF837AF2), // Indigo + Color(0xFFEAD339), // Yellow + Color(0xFF2CBCBD), // Teal + Color(0xFFCE9965), // Brownish Orange + Color(0xFF5D5FB3), // Dark Voilet + Color(0xFF188C8B), // Dark Teal + Color(0xFFD43B99), // Dark Candy + Color(0xFFCFCB51), // Caution Yellow + Color(0xFFDF5F37), // Saffron + Color(0xFF56CA4E), // Venom + Color(0xFFB353CB), // Paint Pink + Color(0xFF8B1650), // Crimson + Color(0xFF8DCCAC), // Gray Green + Color(0xFF00468B), // Blueish Blue + Color(0xFF003D00), // Tree Green + Color(0xFF93B728), // Yellowish Green + ]; static ThemeData defaultTheme = ThemeData.dark(useMaterial3: true).copyWith( pageTransitionsTheme: const PageTransitionsTheme(builders: { diff --git a/lib/screens/accounts/accounts_controller.dart b/lib/screens/accounts/accounts_controller.dart index aa4fdde..98be692 100644 --- a/lib/screens/accounts/accounts_controller.dart +++ b/lib/screens/accounts/accounts_controller.dart @@ -68,6 +68,7 @@ class AccountsController extends GetxController { (key, value) => dbController.accounts[key]?.isDeleted == 1); List tempAccountList = dbController.accounts.values.toList(); tempAccountList.removeWhere((account) => account.isDeleted == 1); + tempAccountList.sort((a, b) => a.accountName.compareTo(b.accountName)); Map> temp = groupBy( tempAccountList, (account) => account.accountType); accountList.value = temp; diff --git a/lib/screens/accounts/accounts_model.dart b/lib/screens/accounts/accounts_model.dart index 22fdb61..c0e3e92 100644 --- a/lib/screens/accounts/accounts_model.dart +++ b/lib/screens/accounts/accounts_model.dart @@ -4,11 +4,14 @@ import 'dart:convert'; -Map accountsFromJson(List> list) => - Map.fromEntries(list.map((x) { - Account account = Account.fromJson(x); - return MapEntry(account.id!, account); - })); +Map accountsFromJson(List> list) { + final accountList = + list.map((account) => Account.fromJson(account)).toList(); + accountList.sort((a, b) => a.accountName.compareTo(b.accountName)); + return Map.fromEntries(accountList.map((account) { + return MapEntry(account.id!, account); + })); +} String accountsToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); @@ -32,7 +35,7 @@ class Account { accountName: json["account_name"], accountType: AccountType.values[json["account_type"]], parentId: json["parent_id"], - isDeleted: json['is_deleted']??0); + isDeleted: json['is_deleted'] ?? 0); Map toJson() => { if (id != null) "id": id, diff --git a/lib/screens/categories/add_category_controller.dart b/lib/screens/categories/add_category_controller.dart index 652c04a..6a5b420 100644 --- a/lib/screens/categories/add_category_controller.dart +++ b/lib/screens/categories/add_category_controller.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_iconpicker/flutter_iconpicker.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; +import 'package:vase/utils.dart'; import '../../const.dart'; import '../../controllers/db_controller.dart'; @@ -23,6 +24,7 @@ class AddCategoryController extends GetxController { preFillCategory(Get.arguments['category']); } else { categoryType.value = Get.arguments['type']; + selectedColor.value = Utils.getNextColor(); } } diff --git a/lib/screens/categories/add_edit_category_screen.dart b/lib/screens/categories/add_edit_category_screen.dart index 4a3200c..13bc384 100644 --- a/lib/screens/categories/add_edit_category_screen.dart +++ b/lib/screens/categories/add_edit_category_screen.dart @@ -1,6 +1,8 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:flutter_iconpicker/flutter_iconpicker.dart'; -import 'package:flutter_material_color_picker/flutter_material_color_picker.dart'; import 'package:get/get.dart'; import 'package:vase/colors.dart'; import 'package:vase/screens/categories/add_category_controller.dart'; @@ -92,7 +94,8 @@ class AddCategoryScreen extends StatelessWidget { TextButton( onPressed: () async { Color? selectedColor = - await showColorSelectionDialog(context); + await showColorSelectionDialog(context, + controller.selectedColor.value); controller.onColorChange(selectedColor); }, child: const Text('Click to choose a Color'), @@ -132,20 +135,59 @@ class AddCategoryScreen extends StatelessWidget { ); } - Future showColorSelectionDialog(BuildContext context) async { + Future showColorSelectionDialog( + BuildContext context, Color oldColor) async { Color? selectedColor; - return showDialog( + TextEditingController textController = TextEditingController(); + return await showDialog( context: context, - builder: (_) { + builder: (BuildContext context) { return AlertDialog( - contentPadding: const EdgeInsets.all(18.0), - title: const Text("Pick a color"), - content: MaterialColorPicker( - onColorChange: (Color color) { - selectedColor = color; - }, - selectedColor: - Get.find().selectedColor.value), + scrollable: true, + actionsPadding: const EdgeInsets.all(0), + titlePadding: const EdgeInsets.all(0), + contentPadding: const EdgeInsets.only(top: 16), + content: Column( + children: [ + ColorPicker( + pickerColor: oldColor, + onColorChanged: (newColor) { + selectedColor = newColor; + }, + colorPickerWidth: 300, + pickerAreaHeightPercent: 0.7, + enableAlpha: false, + displayThumbColor: true, + paletteType: PaletteType.hsvWithHue, + labelTypes: const [], + pickerAreaBorderRadius: const BorderRadius.only( + topLeft: Radius.circular(2), + topRight: Radius.circular(2), + ), + hexInputController: textController, // <- here + portraitOnly: true, + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 0), + child: CupertinoTextField( + controller: textController, + style: const TextStyle(color: Colors.white), + prefix: const Padding( + padding: EdgeInsets.only(left: 8), + child: Icon(Icons.tag)), + suffix: IconButton( + icon: const Icon(Icons.content_paste_rounded), + onPressed: () => copyToClipboard(textController.text), + ), + maxLength: 9, + inputFormatters: [ + UpperCaseTextFormatter(), + FilteringTextInputFormatter.allow(RegExp(kValidHexPattern)), + ], + ), + ) + ], + ), actions: [ TextButton( onPressed: Navigator.of(context).pop, @@ -162,4 +204,12 @@ class AddCategoryScreen extends StatelessWidget { }, ); } + + void copyToClipboard(String input) { + String textToCopy = input.replaceFirst('#', '').toUpperCase(); + if (textToCopy.startsWith('FF') && textToCopy.length == 8) { + textToCopy = textToCopy.replaceFirst('FF', ''); + } + Clipboard.setData(ClipboardData(text: '#$textToCopy')); + } } diff --git a/lib/screens/categories/category_model.dart b/lib/screens/categories/category_model.dart index 89c82de..12d3f82 100644 --- a/lib/screens/categories/category_model.dart +++ b/lib/screens/categories/category_model.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; List categoryFromJson(List> list) => List.from( list.map((x) => Category.fromJson(x)), - ); + )..sort((a, b) => a.categoryName.compareTo(b.categoryName)); String categoryToJson(List data) => json.encode(List.from(data.map( diff --git a/lib/screens/dashboard/dashboard_controller.dart b/lib/screens/dashboard/dashboard_controller.dart index 2ad872e..d1a3d11 100644 --- a/lib/screens/dashboard/dashboard_controller.dart +++ b/lib/screens/dashboard/dashboard_controller.dart @@ -1,6 +1,7 @@ import 'package:get/get.dart'; import 'package:vase/const.dart'; import 'package:vase/controllers/db_controller.dart'; +import 'package:vase/enums.dart'; import 'package:vase/screens/dashboard/dashboard_model.dart'; import 'package:vase/utils.dart'; @@ -10,6 +11,7 @@ class DashboardController extends GetxController { RxList sectors = RxList.empty(); DbController dbController = Get.find(); double total = 0; + Rx dashboardState = VaseState.loading.obs; @override void onInit() { @@ -18,6 +20,7 @@ class DashboardController extends GetxController { } Future fetchSectors() async { + dashboardState.value = VaseState.loading; var transList = await dbController.db.rawQuery( '''SELECT SUM(${Const.trans}.amount) AS total , count(${Const.categories}.category_name) AS share , ${Const.categories}.category_name , ${Const.categories}.color, ${Const.categories}.icon from ${Const.trans} @@ -34,10 +37,21 @@ class DashboardController extends GetxController { if (double.parse(transaction['total'].toString()) < 0 && transaction['category_name'] != null) { Sector s = Sector.fromJson(transList[i]); - total += s.amount; + if (s.include) total += s.amount; sectors.add(s); } } + dashboardState.value = VaseState.loaded; + update(); + } + + void recalculateTotal() { + total = 0; + for (Sector sector in sectors) { + if (sector.include) { + total += sector.amount; + } + } update(); } diff --git a/lib/screens/dashboard/dashboard_screen.dart b/lib/screens/dashboard/dashboard_screen.dart index fb1d7ba..8a9b4cc 100644 --- a/lib/screens/dashboard/dashboard_screen.dart +++ b/lib/screens/dashboard/dashboard_screen.dart @@ -2,10 +2,12 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:vase/colors.dart'; +import 'package:vase/enums.dart'; import 'package:vase/extensions.dart'; import 'package:vase/screens/dashboard/dashboard_controller.dart'; import 'package:vase/screens/dashboard/dashboard_model.dart'; import 'package:vase/screens/dashboard/pie_chart.dart'; +import 'package:vase/screens/widgets/empty.dart'; import 'package:vase/widgets/category_icon.dart'; import 'package:vase/widgets/focused_layout.dart'; import 'package:vase/widgets/wrapper.dart'; @@ -33,6 +35,16 @@ class DashboardScreen extends StatelessWidget { child: GetBuilder( init: DashboardController(Get.arguments), builder: (DashboardController controller) { + if (controller.dashboardState.value == VaseState.loading) { + return const Center( + child: CircularProgressIndicator(), + ); + } + if (controller.sectors.isEmpty) { + return const EmptyWidget( + assetName: "assets/img/no_cat.svg", + label: "No Transactions for the selected month"); + } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -46,7 +58,7 @@ class DashboardScreen extends StatelessWidget { return ListTile( onTap: () { sector.switchInclusion(); - controller.update(); + controller.recalculateTotal(); }, leading: CategoryIcon( icon: sector.icon, diff --git a/lib/utils.dart b/lib/utils.dart index db16bb2..cd265c5 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -22,6 +22,12 @@ class Utils { .toList(); } + static Color getNextColor() { + int categoriesLength = Get.find().categories.length; + List colors = AppColors.categoryColors; + return colors[categoriesLength % colors.length]; + } + static void showBottomSnackBar( {required String title, required String message, required Icon ic}) { Get.snackbar( @@ -62,8 +68,7 @@ class Utils { static Future importDb() async { try { - FilePickerResult? result = await FilePicker.platform - .pickFiles(); + FilePickerResult? result = await FilePicker.platform.pickFiles(); if (result != null && result.files.single.path != null) { File file = File(result.files.single.path!); @@ -107,7 +112,8 @@ class Utils { } static int getLastDate(DateTime currentDate) { - DateTime dateTime = DateTime(currentDate.year, currentDate.month + 1, 1).subtract(const Duration(seconds: 1)); + DateTime dateTime = DateTime(currentDate.year, currentDate.month + 1, 1) + .subtract(const Duration(seconds: 1)); return dateTime.millisecondsSinceEpoch; } diff --git a/pubspec.lock b/pubspec.lock index 8cf1aea..dbb5ac1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -162,10 +162,10 @@ packages: dependency: "direct main" description: name: flutter_colorpicker - sha256: "458a6ed8ea480eb16ff892aedb4b7092b2804affd7e046591fb03127e8d8ef8b" + sha256: "969de5f6f9e2a570ac660fb7b501551451ea2a1ab9e2097e89475f60e07816ea" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.1.0" flutter_driver: dependency: transitive description: flutter @@ -187,14 +187,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" - flutter_material_color_picker: - dependency: "direct main" - description: - name: flutter_material_color_picker - sha256: ca1e7749d228c9155ea24bce98e647cdbffa350e6f334f6c001f841cd3d9c987 - url: "https://pub.dev" - source: hosted - version: "1.2.0" flutter_plugin_android_lifecycle: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a31cdf6..17d1f97 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.3.0+8 +version: 1.3.1+9 environment: sdk: ">=2.19.0 <3.0.0" @@ -46,8 +46,7 @@ dependencies: fl_chart: ^0.68.0 flutter_svg: ^2.0.6 flutter_iconpicker: ^3.2.4 - flutter_colorpicker: ^1.0.3 - flutter_material_color_picker: ^1.2.0 + flutter_colorpicker: ^1.1.0 flutter: sdk: flutter