From 8f3952d9bdcd914ac05becdd3e9d7e23f5a5d08f Mon Sep 17 00:00:00 2001 From: mene412 Date: Tue, 21 Feb 2023 11:47:22 +0100 Subject: [PATCH 1/9] Update pubspec.lock --- pubspec.lock | 119 +++++++++++++++------------------------------------ 1 file changed, 35 insertions(+), 84 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 3303597..bb9df07 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -92,6 +92,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -113,6 +120,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.4" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + url: "https://pub.dartlang.org" + source: hosted + version: "0.55.2" flutter: dependency: "direct main" description: flutter @@ -125,6 +139,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" flutter_staggered_grid_view: dependency: "direct main" description: @@ -249,55 +270,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" - path_provider: - dependency: "direct main" - description: - name: path_provider - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.21" - path_provider_ios: - dependency: transitive - description: - name: path_provider_ios - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.6" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" percent_indicator: dependency: "direct main" description: @@ -305,20 +277,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.2" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" pool: dependency: transitive description: @@ -326,20 +284,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.1" - process: + pub_semver: dependency: transitive description: - name: process + name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "4.2.4" - pub_semver: + version: "2.1.2" + riverpod: dependency: transitive description: - name: pub_semver + name: riverpod url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.2.0" shelf: dependency: transitive description: @@ -400,7 +358,7 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "2.2.0+3" + version: "2.2.2" sqflite_common: dependency: transitive description: @@ -436,6 +394,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.10.0" + state_notifier: + dependency: transitive + description: + name: state_notifier + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.2+1" stream_channel: dependency: transitive description: @@ -527,20 +492,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" - win32: - dependency: transitive - description: - name: win32 - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0+2" yaml: dependency: transitive description: From 2da950a4f8bdaa054fb2c6adb47c49619cd508d6 Mon Sep 17 00:00:00 2001 From: mene412 Date: Wed, 24 May 2023 17:06:29 +0200 Subject: [PATCH 2/9] First part of onboarding --- assets/openVault.png | Bin 0 -> 32086 bytes lib/constants/style.dart | 2 +- lib/main.dart | 2 +- .../onboarding_page/onboarding_page.dart | 628 ++++++++++++++++++ lib/routes.dart | 3 + linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 163 ++++- .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 11 files changed, 805 insertions(+), 4 deletions(-) create mode 100644 assets/openVault.png create mode 100644 lib/pages/onboarding_page/onboarding_page.dart diff --git a/assets/openVault.png b/assets/openVault.png new file mode 100644 index 0000000000000000000000000000000000000000..bc3c39a0b54b48bfd4744f6b6e7c55fcb8d515b1 GIT binary patch literal 32086 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�!VvX-o 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 z%0D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 Mlvb9ikuVAQKLU>$I{*Lx literal 0 HcmV?d00001 diff --git a/lib/constants/style.dart b/lib/constants/style.dart index 6041d88..594a623 100644 --- a/lib/constants/style.dart +++ b/lib/constants/style.dart @@ -21,7 +21,7 @@ BoxShadow defaultShadow = BoxShadow( const green = Color(0xFF248731); const red = Color(0xFFC52626); const white = Color(0xFFFFFFFF); -const black = Color(0x00000000); +const black = Color(0xFF000000); const blue1 = Color(0xFF00152D); const blue2 = Color(0xFF002855); diff --git a/lib/main.dart b/lib/main.dart index 15d030b..a7cb0e3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -112,7 +112,7 @@ class Launcher extends StatelessWidget { title: 'Sossoldi', theme: customThemeData, onGenerateRoute: makeRoute, - initialRoute: '/', + initialRoute: '/onboarding', ); } } diff --git a/lib/pages/onboarding_page/onboarding_page.dart b/lib/pages/onboarding_page/onboarding_page.dart new file mode 100644 index 0000000..8207782 --- /dev/null +++ b/lib/pages/onboarding_page/onboarding_page.dart @@ -0,0 +1,628 @@ +import 'dart:ui'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '/custom_widgets/default_container.dart'; +import '/model/budget.dart'; +import '/providers/categories_provider.dart'; +import '/constants/constants.dart'; +import '/constants/style.dart'; +import '/model/category_transaction.dart'; +import '/providers/budgets_provider.dart'; +import 'package:collection/collection.dart'; + +class Onboarding extends StatefulWidget { + const Onboarding({Key? key}) : super(key: key); + + @override + State createState() => _OnboardingState(); +} + +class _OnboardingState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: blue7, + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 80, + ), + Text( + 'Set up the app', + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: Theme.of(context).colorScheme.primary), + ), + const SizedBox( + height: 80, + ), + Image.asset( + 'assets/openVault.png', + height: 214, + ), + const SizedBox( + height: 74, + ), + Text( + 'In a few steps you\'ll be ready to start keeping\ntrack of ypur personal finances (almost) like\nMr. Rip', + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + const Spacer(), + SizedBox( + width: 342, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Step1(), + ), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text( + 'START THE SET UP', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white), + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } +} + +class Step1 extends ConsumerStatefulWidget { + const Step1({Key? key}) : super(key: key); + + @override + ConsumerState createState() => _Step1State(); +} + +class _Step1State extends ConsumerState { + // sum of the budget of the selected cards + int totalBudget = 0; + + @override + Widget build(BuildContext context) { + final categoriesGrid = ref.watch(categoriesProvider); + return Scaffold( + backgroundColor: blue7, + body: Center( + child: Column( + children: [ + const SizedBox(height: 40), + Text("STEP 1 OF 2", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Text( + "Set up your monthly\nbudgets", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox(height: 20), + Text( + "Choose which categories you want to set a budget for", + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + const SizedBox(height: 5), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + top: 0, bottom: 0, left: 16, right: 16), + child: NotificationListener( + onNotification: (OverscrollIndicatorNotification overscroll) { + overscroll.disallowIndicator(); + return true; + }, + child: categoriesGrid.when( + data: (categories) => GridView.builder( + itemCount: categories.length+1, + scrollDirection: Axis.vertical, + gridDelegate: + const SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 300, + childAspectRatio: 3, + crossAxisSpacing: 18, + mainAxisSpacing: 12, + ), + itemBuilder: (context, i) => GestureDetector( + onTap: () {}, + child: Container( + child: buildCard(categories.elementAt(i)), + ), + ), + ), + error: (err, stack) => Text('Error: $err'), + loading: () => const Center( + child: CircularProgressIndicator(), + ), + ), + ), + ), + ), + + // if the total budget (sum of the budget of the selected cards) is > 0, set the other layout. otherwise set the "continue without budget" button + totalBudget > 0 + ? Center( + child: Column( + children: [ + Text("Monthly budget total:", + style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + RichText( + textScaleFactor: + MediaQuery.of(context).textScaleFactor, + text: TextSpan( + children: [ + TextSpan( + text: totalBudget.toString(), + style: + Theme.of(context).textTheme.displayMedium, + ), + TextSpan( + text: "€", + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply( + fontFeatures: [ + const FontFeature.subscripts() + ], + ), + ), + ], + ), + ), + const SizedBox(height: 20), + SizedBox( + width: 342, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Step2()), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('NEXT STEP', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), + ], + ), + ) + : Padding( + padding: const EdgeInsets.only(left: 75, right: 75), + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Step2()), + ); + }, + style: ElevatedButton.styleFrom( + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Container( + padding: const EdgeInsets.only(bottom: 1.0), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(width: 1.2, color: black))), + child: Row( + children: [ + Text('CONTINUE WITHOUT BUDGET ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1)), + const Icon(Icons.arrow_forward, + size: 15, color: blue1), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } + + Widget buildCard(CategoryTransaction category) { + final budgetsList = ref.watch(budgetsProvider); + Color categoryColor = categoryColorList[category.color]; + String categoryName = category.name; + if (budgetsList is AsyncData>) { + final budgets = budgetsList.value; + + Budget? budget = + budgets?.firstWhereOrNull((c) => c.idCategory == category.id); + + if (budget != null && budget.active) { + return Container( + color: categoryColor, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: categoryColor, width: 2.5), + color: categoryColor, + borderRadius: const BorderRadius.all(Radius.circular(8))), + alignment: Alignment.center, + child: Row( + children: [ + CircleAvatar( + backgroundColor: categoryColor, + radius: 15.0, + child: CircleAvatar( + backgroundColor: white, + radius: 13, + child: Icon(Icons.check, color: categoryColor, size: 22), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 125, + child: Text( + categoryName, + textAlign: TextAlign.left, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply(color: white), + ), + ), + SizedBox( + width: 95, + child: Text( + "BUDGET: ${budget.amountLimit}€", + style: Theme.of(context) + .textTheme + .bodySmall + ?.apply(color: white), + ), + ), + ], + ) + ], + ), + ), + ); + } + } + return Container( + decoration: BoxDecoration( + border: Border.all(color: categoryColor, width: 2.5), + color: HSLColor.fromColor(categoryColor) + .withLightness(clampDouble(0.99, 0.0, 0.9)) + .toColor(), + borderRadius: const BorderRadius.all( + Radius.circular(8), + ), + ), + alignment: Alignment.center, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: CircleAvatar( + backgroundColor: blue1, + radius: 15.0, + child: CircleAvatar( + backgroundColor: HSLColor.fromColor(categoryColor) + .withLightness(clampDouble(0.99, 0.0, 0.9)) + .toColor(), + radius: 13, + child: const Icon(Icons.add, color: blue1)), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 95, + child: Text( + categoryName, + textAlign: TextAlign.left, + style: Theme.of(context).textTheme.bodyMedium, + )), + SizedBox( + width: 95, + child: Text("ADD BUDGET", + style: Theme.of(context).textTheme.bodySmall)), + ], + ) + ], + ), + ); + } + + Widget buildDefaultCard() { + return Container( + decoration: BoxDecoration( + border: Border.all(color: grey2, width: 0.5), + color: grey3, + borderRadius: const BorderRadius.all( + Radius.circular(8), + ), + ), + alignment: Alignment.center, + child: Row( + children: [ + const Padding( + padding: EdgeInsets.only(left: 10), + child: CircleAvatar( + backgroundColor: grey1, + radius: 15.0, + child: CircleAvatar( + backgroundColor: grey3, + radius: 13, + child: Icon(Icons.add, color: grey1), + ), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 125, + child: Text( + "Add category", + textAlign: TextAlign.left, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply(color: grey1), + ), + ), + ], + ), + ], + ), + ); + } +} + +class Step2 extends StatefulWidget { + const Step2({super.key}); + + @override + State createState() => _Step2State(); +} + +class _Step2State extends State { + TextEditingController accountNameController = TextEditingController(); + TextEditingController amountController = TextEditingController(); + + @override + Widget build(BuildContext context) { + accountNameController.text = "Main account"; + + return Scaffold( + backgroundColor: blue7, + body: Center( + child: Column( + children: [ + const SizedBox(height: 40), + Text("STEP 2 OF 2", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Text( + "Set the liquidity in your main\naccount", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox(height: 20), + Text( + "It will be used as a baseline to which you can add\nincome, expenses and calculate your wealth.\n\nYou’ll be able to add more accounts within the app.", + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + const SizedBox(height: 10), + Container( + margin: const EdgeInsets.only(left: 25.0, right: 25.0), + padding: const EdgeInsets.only(left: 20.0, right: 20.0), + decoration: BoxDecoration( + color: white, + shape: BoxShape.rectangle, + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 20, + offset: const Offset(2, 2), + ), + ], + borderRadius: const BorderRadius.all(Radius.circular(20))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("ACCOUNT NAME ", + style: Theme.of(context).textTheme.labelSmall), + const Icon(Icons.edit, size: 10) + ], + ), + TextField( + style: Theme.of(context) + .textTheme + .headlineMedium + ?.apply(color: black), + textAlign: TextAlign.center, + controller: accountNameController, + decoration: const InputDecoration( + border: UnderlineInputBorder( + borderSide: BorderSide(color: Colors.black, width: 0.8), + ), + ), + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("SET AMOUNT ", + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith(color: blue1)), + const Icon(Icons.edit, size: 10) + ], + ), + TextField( + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + controller: amountController, + decoration: InputDecoration( + hintText: "e.g 1300 €", + hintStyle: Theme.of(context).textTheme.bodySmall, + border: const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.black, width: 0.8), + ), + ), + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("EDIT ICON AND COLOR ", + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith(color: blue1)), + const Icon(Icons.edit, size: 10) + ], + ), + const SizedBox(height: 10), + ElevatedButton( + // TO DO - icona modificabile + onPressed: () {}, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + padding: const EdgeInsets.all(10), + backgroundColor: blue5, + ), + child: const Icon( + Icons.account_balance, + size: 40, + color: white, + ), + ), + const SizedBox(height: 15), + ], + ), + ), + const Spacer(), + Text('Or you can skip this step and start from 0', + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: blue1)), + const SizedBox(height: 5), + SizedBox( + width: 156, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/'); + }, + style: ElevatedButton.styleFrom( + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Container( + padding: const EdgeInsets.only(bottom: 1.0), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(width: 1.2, color: black), + ), + ), + child: Row( + children: [ + Text( + 'START FROM 0 ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1), + ), + const Icon(Icons.arrow_forward, size: 15, color: blue1), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + SizedBox( + width: 342, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/'); + }, + style: ElevatedButton.styleFrom( + backgroundColor: grey2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('START TRACKING YOUR EXPENSES', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } +} diff --git a/lib/routes.dart b/lib/routes.dart index c435b6a..c453712 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -18,11 +18,14 @@ import 'pages/settings_page.dart'; import 'pages/statistics_page.dart'; import 'pages/structure.dart'; import 'pages/transactions_page/transactions_page.dart'; +import 'pages/onboarding_page/onboarding_page.dart'; Route makeRoute(RouteSettings settings) { switch (settings.name) { case '/': return _materialPageRoute(settings.name, const Structure()); + case '/onboarding': + return _materialPageRoute(settings.name, const Onboarding()); case '/dashboard': return _materialPageRoute(settings.name, const HomePage()); case '/transactions': diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 2c1ec4f..4c0025f 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 7ea2a80..ad279a8 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST sqlite3_flutter_libs + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 4856abc..b4e2147 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,8 +7,10 @@ import Foundation import sqflite import sqlite3_flutter_libs +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index bb9df07..d766ffb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,13 +15,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.7.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.7" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.1" + version: "2.4.1" async: dependency: transitive description: @@ -43,6 +50,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" circular_menu: dependency: "direct main" description: @@ -50,6 +64,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.5" clock: dependency: transitive description: @@ -85,6 +106,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.2" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.2" cupertino_icons: dependency: "direct main" description: @@ -132,6 +160,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0" flutter_lints: dependency: "direct dev" description: @@ -139,6 +174,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + flutter_native_splash: + dependency: "direct main" + description: + name: flutter_native_splash + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.18" flutter_riverpod: dependency: "direct main" description: @@ -158,6 +200,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" frontend_server_client: dependency: transitive description: @@ -172,6 +219,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.3" http_multi_server: dependency: transitive description: @@ -186,6 +240,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.2" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.17" intl: dependency: "direct main" description: @@ -206,7 +267,14 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.5" + version: "0.6.4" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.8.0" lints: dependency: transitive description: @@ -277,6 +345,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.2" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + url: "https://pub.dartlang.org" + source: hosted + version: "3.7.3" pool: dependency: transitive description: @@ -457,6 +546,69 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + universal_io: + dependency: transitive + description: + name: universal_io + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.11" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.34" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.16" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.6" vector_math: dependency: transitive description: @@ -492,6 +644,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.0" yaml: dependency: transitive description: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 988f3c8..76d5285 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,11 @@ #include "generated_plugin_registrant.h" #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 8abff95..22aeaae 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST sqlite3_flutter_libs + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST From 55f7d69725824d685984d0492d79815a5c0aa029 Mon Sep 17 00:00:00 2001 From: mene412 Date: Tue, 6 Jun 2023 18:29:30 +0200 Subject: [PATCH 3/9] First part of onboarding [Figma reference](https://www.figma.com/file/6NyY9yqunpbU7HIkbNEAL3/Sossoldi-App?type=design&node-id=1163-4030&t=NgwAP2DuLag5D9oN-0) DONE (copying by 0xbaggi and updating with `style.dart` and `constant.dart`): * "start the set up" page * step 1 page (set budgets) * Scrollable list of selectable budgets (taken from the database) as a grid of cards * "add category" card * Numeric keyboard for adding the budget * step 2 page (set liquidity) * Input fields for account name and amount (with only number keyboard) TODO: * Show onboarding page only the first time * Implement the updating of the database when adding budget and account * Implement "Edit Icon and Color" when creating an account --- .../onboarding_page/onboarding_page.dart | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/lib/pages/onboarding_page/onboarding_page.dart b/lib/pages/onboarding_page/onboarding_page.dart index 8207782..7a87ece 100644 --- a/lib/pages/onboarding_page/onboarding_page.dart +++ b/lib/pages/onboarding_page/onboarding_page.dart @@ -3,7 +3,6 @@ import 'dart:ui'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '/custom_widgets/default_container.dart'; import '/model/budget.dart'; import '/providers/categories_provider.dart'; import '/constants/constants.dart'; @@ -139,7 +138,7 @@ class _Step1State extends ConsumerState { }, child: categoriesGrid.when( data: (categories) => GridView.builder( - itemCount: categories.length+1, + itemCount: categories.length + 1, scrollDirection: Axis.vertical, gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( @@ -148,12 +147,28 @@ class _Step1State extends ConsumerState { crossAxisSpacing: 18, mainAxisSpacing: 12, ), - itemBuilder: (context, i) => GestureDetector( - onTap: () {}, - child: Container( - child: buildCard(categories.elementAt(i)), - ), - ), + itemBuilder: (context, i) { + if (i < categories.length) { + return GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (context) => NumericKeyboardDialog( + categories.elementAt(i)), + ); + }, + child: Container( + child: buildCard(categories.elementAt(i)), + ), + ); + } else { + return GestureDetector( + onTap: () => Navigator.of(context) + .pushNamed('/add-category'), + child: buildDefaultCard(), + ); + } + }, ), error: (err, stack) => Text('Error: $err'), loading: () => const Center( @@ -370,7 +385,7 @@ class _Step1State extends ConsumerState { child: Text("ADD BUDGET", style: Theme.of(context).textTheme.bodySmall)), ], - ) + ), ], ), ); @@ -626,3 +641,33 @@ class _Step2State extends State { ); } } + +class NumericKeyboardDialog extends StatelessWidget { + CategoryTransaction category; + var valueEntered; + NumericKeyboardDialog(this.category, {this.valueEntered, super.key}); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, ref, _) { + final budgetsValue = ref.watch(budgetsValueProvider); + return AlertDialog( + title: Text('Add budget for ${category.name}'), + content: TextField( + keyboardType: TextInputType.number, + onChanged: (value) => ref.read(budgetsValueProvider.notifier).state = value as int, + ), + actions: [ + ElevatedButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Confirm'), + ), + ], + ); + }, + ); + } +} From b4d9db4f50cc8918cfa9cd80891d1860f2e225b7 Mon Sep 17 00:00:00 2001 From: mene412 Date: Tue, 6 Jun 2023 18:34:53 +0200 Subject: [PATCH 4/9] Removed useless code --- lib/pages/onboarding_page/onboarding_page.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/pages/onboarding_page/onboarding_page.dart b/lib/pages/onboarding_page/onboarding_page.dart index 7a87ece..862b600 100644 --- a/lib/pages/onboarding_page/onboarding_page.dart +++ b/lib/pages/onboarding_page/onboarding_page.dart @@ -644,19 +644,16 @@ class _Step2State extends State { class NumericKeyboardDialog extends StatelessWidget { CategoryTransaction category; - var valueEntered; - NumericKeyboardDialog(this.category, {this.valueEntered, super.key}); + NumericKeyboardDialog(this.category, {super.key}); @override Widget build(BuildContext context) { return Consumer( builder: (context, ref, _) { - final budgetsValue = ref.watch(budgetsValueProvider); return AlertDialog( title: Text('Add budget for ${category.name}'), - content: TextField( + content: const TextField( keyboardType: TextInputType.number, - onChanged: (value) => ref.read(budgetsValueProvider.notifier).state = value as int, ), actions: [ ElevatedButton( From bcc186c5610e775eafbc92666fe64edefaa43a2e Mon Sep 17 00:00:00 2001 From: mene412 Date: Thu, 8 Jun 2023 21:33:33 +0200 Subject: [PATCH 5/9] Code divided in widget for a better readability --- .../onboarding_page/onboarding_page.dart | 597 +----------------- .../widgets/account_setup.dart | 216 +++++++ .../onboarding_page/widgets/budget_setup.dart | 390 ++++++++++++ 3 files changed, 610 insertions(+), 593 deletions(-) create mode 100644 lib/pages/onboarding_page/widgets/account_setup.dart create mode 100644 lib/pages/onboarding_page/widgets/budget_setup.dart diff --git a/lib/pages/onboarding_page/onboarding_page.dart b/lib/pages/onboarding_page/onboarding_page.dart index 862b600..773c895 100644 --- a/lib/pages/onboarding_page/onboarding_page.dart +++ b/lib/pages/onboarding_page/onboarding_page.dart @@ -1,15 +1,6 @@ -import 'dart:ui'; - -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '/model/budget.dart'; -import '/providers/categories_provider.dart'; -import '/constants/constants.dart'; +import 'package:sossoldi/pages/onboarding_page/widgets/budget_setup.dart'; import '/constants/style.dart'; -import '/model/category_transaction.dart'; -import '/providers/budgets_provider.dart'; -import 'package:collection/collection.dart'; class Onboarding extends StatefulWidget { const Onboarding({Key? key}) : super(key: key); @@ -48,7 +39,7 @@ class _OnboardingState extends State { height: 74, ), Text( - 'In a few steps you\'ll be ready to start keeping\ntrack of ypur personal finances (almost) like\nMr. Rip', + 'In a few steps you\'ll be ready to start keeping\ntrack of your personal finances (almost) like\nMr. Rip', textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), @@ -62,7 +53,7 @@ class _OnboardingState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => const Step1(), + builder: (context) => const BudgetSetup(), ), ); }, @@ -87,584 +78,4 @@ class _OnboardingState extends State { ), ); } -} - -class Step1 extends ConsumerStatefulWidget { - const Step1({Key? key}) : super(key: key); - - @override - ConsumerState createState() => _Step1State(); -} - -class _Step1State extends ConsumerState { - // sum of the budget of the selected cards - int totalBudget = 0; - - @override - Widget build(BuildContext context) { - final categoriesGrid = ref.watch(categoriesProvider); - return Scaffold( - backgroundColor: blue7, - body: Center( - child: Column( - children: [ - const SizedBox(height: 40), - Text("STEP 1 OF 2", style: Theme.of(context).textTheme.labelSmall), - const SizedBox(height: 20), - Text( - "Set up your monthly\nbudgets", - textAlign: TextAlign.center, - style: Theme.of(context) - .textTheme - .headlineLarge - ?.copyWith(color: blue1), - ), - const SizedBox(height: 20), - Text( - "Choose which categories you want to set a budget for", - textAlign: TextAlign.center, - style: - Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), - ), - const SizedBox(height: 5), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - top: 0, bottom: 0, left: 16, right: 16), - child: NotificationListener( - onNotification: (OverscrollIndicatorNotification overscroll) { - overscroll.disallowIndicator(); - return true; - }, - child: categoriesGrid.when( - data: (categories) => GridView.builder( - itemCount: categories.length + 1, - scrollDirection: Axis.vertical, - gridDelegate: - const SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 300, - childAspectRatio: 3, - crossAxisSpacing: 18, - mainAxisSpacing: 12, - ), - itemBuilder: (context, i) { - if (i < categories.length) { - return GestureDetector( - onTap: () { - showDialog( - context: context, - builder: (context) => NumericKeyboardDialog( - categories.elementAt(i)), - ); - }, - child: Container( - child: buildCard(categories.elementAt(i)), - ), - ); - } else { - return GestureDetector( - onTap: () => Navigator.of(context) - .pushNamed('/add-category'), - child: buildDefaultCard(), - ); - } - }, - ), - error: (err, stack) => Text('Error: $err'), - loading: () => const Center( - child: CircularProgressIndicator(), - ), - ), - ), - ), - ), - - // if the total budget (sum of the budget of the selected cards) is > 0, set the other layout. otherwise set the "continue without budget" button - totalBudget > 0 - ? Center( - child: Column( - children: [ - Text("Monthly budget total:", - style: Theme.of(context).textTheme.bodySmall), - const SizedBox(height: 10), - RichText( - textScaleFactor: - MediaQuery.of(context).textScaleFactor, - text: TextSpan( - children: [ - TextSpan( - text: totalBudget.toString(), - style: - Theme.of(context).textTheme.displayMedium, - ), - TextSpan( - text: "€", - style: Theme.of(context) - .textTheme - .bodyMedium - ?.apply( - fontFeatures: [ - const FontFeature.subscripts() - ], - ), - ), - ], - ), - ), - const SizedBox(height: 20), - SizedBox( - width: 342, - height: 48, - child: ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const Step2()), - ); - }, - style: ElevatedButton.styleFrom( - backgroundColor: blue5, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: Text('NEXT STEP', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: Colors.white)), - ), - ), - ], - ), - ) - : Padding( - padding: const EdgeInsets.only(left: 75, right: 75), - child: ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const Step2()), - ); - }, - style: ElevatedButton.styleFrom( - elevation: 0.0, - shadowColor: Colors.transparent, - backgroundColor: Colors.transparent, - ), - child: Container( - padding: const EdgeInsets.only(bottom: 1.0), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(width: 1.2, color: black))), - child: Row( - children: [ - Text('CONTINUE WITHOUT BUDGET ', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: blue1)), - const Icon(Icons.arrow_forward, - size: 15, color: blue1), - ], - ), - ), - ), - ), - const SizedBox(height: 20), - ], - ), - ), - ); - } - - Widget buildCard(CategoryTransaction category) { - final budgetsList = ref.watch(budgetsProvider); - Color categoryColor = categoryColorList[category.color]; - String categoryName = category.name; - if (budgetsList is AsyncData>) { - final budgets = budgetsList.value; - - Budget? budget = - budgets?.firstWhereOrNull((c) => c.idCategory == category.id); - - if (budget != null && budget.active) { - return Container( - color: categoryColor, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: categoryColor, width: 2.5), - color: categoryColor, - borderRadius: const BorderRadius.all(Radius.circular(8))), - alignment: Alignment.center, - child: Row( - children: [ - CircleAvatar( - backgroundColor: categoryColor, - radius: 15.0, - child: CircleAvatar( - backgroundColor: white, - radius: 13, - child: Icon(Icons.check, color: categoryColor, size: 22), - ), - ), - const SizedBox(width: 10), - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SizedBox( - width: 125, - child: Text( - categoryName, - textAlign: TextAlign.left, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.apply(color: white), - ), - ), - SizedBox( - width: 95, - child: Text( - "BUDGET: ${budget.amountLimit}€", - style: Theme.of(context) - .textTheme - .bodySmall - ?.apply(color: white), - ), - ), - ], - ) - ], - ), - ), - ); - } - } - return Container( - decoration: BoxDecoration( - border: Border.all(color: categoryColor, width: 2.5), - color: HSLColor.fromColor(categoryColor) - .withLightness(clampDouble(0.99, 0.0, 0.9)) - .toColor(), - borderRadius: const BorderRadius.all( - Radius.circular(8), - ), - ), - alignment: Alignment.center, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.only(left: 10), - child: CircleAvatar( - backgroundColor: blue1, - radius: 15.0, - child: CircleAvatar( - backgroundColor: HSLColor.fromColor(categoryColor) - .withLightness(clampDouble(0.99, 0.0, 0.9)) - .toColor(), - radius: 13, - child: const Icon(Icons.add, color: blue1)), - ), - ), - const SizedBox(width: 10), - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SizedBox( - width: 95, - child: Text( - categoryName, - textAlign: TextAlign.left, - style: Theme.of(context).textTheme.bodyMedium, - )), - SizedBox( - width: 95, - child: Text("ADD BUDGET", - style: Theme.of(context).textTheme.bodySmall)), - ], - ), - ], - ), - ); - } - - Widget buildDefaultCard() { - return Container( - decoration: BoxDecoration( - border: Border.all(color: grey2, width: 0.5), - color: grey3, - borderRadius: const BorderRadius.all( - Radius.circular(8), - ), - ), - alignment: Alignment.center, - child: Row( - children: [ - const Padding( - padding: EdgeInsets.only(left: 10), - child: CircleAvatar( - backgroundColor: grey1, - radius: 15.0, - child: CircleAvatar( - backgroundColor: grey3, - radius: 13, - child: Icon(Icons.add, color: grey1), - ), - ), - ), - const SizedBox(width: 10), - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SizedBox( - width: 125, - child: Text( - "Add category", - textAlign: TextAlign.left, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.apply(color: grey1), - ), - ), - ], - ), - ], - ), - ); - } -} - -class Step2 extends StatefulWidget { - const Step2({super.key}); - - @override - State createState() => _Step2State(); -} - -class _Step2State extends State { - TextEditingController accountNameController = TextEditingController(); - TextEditingController amountController = TextEditingController(); - - @override - Widget build(BuildContext context) { - accountNameController.text = "Main account"; - - return Scaffold( - backgroundColor: blue7, - body: Center( - child: Column( - children: [ - const SizedBox(height: 40), - Text("STEP 2 OF 2", style: Theme.of(context).textTheme.labelSmall), - const SizedBox(height: 20), - Text( - "Set the liquidity in your main\naccount", - textAlign: TextAlign.center, - style: Theme.of(context) - .textTheme - .headlineLarge - ?.copyWith(color: blue1), - ), - const SizedBox(height: 20), - Text( - "It will be used as a baseline to which you can add\nincome, expenses and calculate your wealth.\n\nYou’ll be able to add more accounts within the app.", - textAlign: TextAlign.center, - style: - Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), - ), - const SizedBox(height: 10), - Container( - margin: const EdgeInsets.only(left: 25.0, right: 25.0), - padding: const EdgeInsets.only(left: 20.0, right: 20.0), - decoration: BoxDecoration( - color: white, - shape: BoxShape.rectangle, - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 5, - blurRadius: 20, - offset: const Offset(2, 2), - ), - ], - borderRadius: const BorderRadius.all(Radius.circular(20))), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 15), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("ACCOUNT NAME ", - style: Theme.of(context).textTheme.labelSmall), - const Icon(Icons.edit, size: 10) - ], - ), - TextField( - style: Theme.of(context) - .textTheme - .headlineMedium - ?.apply(color: black), - textAlign: TextAlign.center, - controller: accountNameController, - decoration: const InputDecoration( - border: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.black, width: 0.8), - ), - ), - ), - const SizedBox(height: 15), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("SET AMOUNT ", - style: Theme.of(context) - .textTheme - .labelSmall - ?.copyWith(color: blue1)), - const Icon(Icons.edit, size: 10) - ], - ), - TextField( - textAlign: TextAlign.center, - keyboardType: TextInputType.number, - controller: amountController, - decoration: InputDecoration( - hintText: "e.g 1300 €", - hintStyle: Theme.of(context).textTheme.bodySmall, - border: const UnderlineInputBorder( - borderSide: BorderSide(color: Colors.black, width: 0.8), - ), - ), - ), - const SizedBox(height: 15), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("EDIT ICON AND COLOR ", - style: Theme.of(context) - .textTheme - .labelSmall - ?.copyWith(color: blue1)), - const Icon(Icons.edit, size: 10) - ], - ), - const SizedBox(height: 10), - ElevatedButton( - // TO DO - icona modificabile - onPressed: () {}, - style: ElevatedButton.styleFrom( - shape: const CircleBorder(), - padding: const EdgeInsets.all(10), - backgroundColor: blue5, - ), - child: const Icon( - Icons.account_balance, - size: 40, - color: white, - ), - ), - const SizedBox(height: 15), - ], - ), - ), - const Spacer(), - Text('Or you can skip this step and start from 0', - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith(color: blue1)), - const SizedBox(height: 5), - SizedBox( - width: 156, - height: 48, - child: ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/'); - }, - style: ElevatedButton.styleFrom( - elevation: 0.0, - shadowColor: Colors.transparent, - backgroundColor: Colors.transparent, - ), - child: Container( - padding: const EdgeInsets.only(bottom: 1.0), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(width: 1.2, color: black), - ), - ), - child: Row( - children: [ - Text( - 'START FROM 0 ', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: blue1), - ), - const Icon(Icons.arrow_forward, size: 15, color: blue1), - ], - ), - ), - ), - ), - const SizedBox(height: 20), - SizedBox( - width: 342, - height: 48, - child: ElevatedButton( - onPressed: () { - Navigator.of(context).pushNamed('/'); - }, - style: ElevatedButton.styleFrom( - backgroundColor: grey2, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: Text('START TRACKING YOUR EXPENSES', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: Colors.white)), - ), - ), - const SizedBox(height: 20), - ], - ), - ), - ); - } -} - -class NumericKeyboardDialog extends StatelessWidget { - CategoryTransaction category; - NumericKeyboardDialog(this.category, {super.key}); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (context, ref, _) { - return AlertDialog( - title: Text('Add budget for ${category.name}'), - content: const TextField( - keyboardType: TextInputType.number, - ), - actions: [ - ElevatedButton( - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Confirm'), - ), - ], - ); - }, - ); - } -} +} \ No newline at end of file diff --git a/lib/pages/onboarding_page/widgets/account_setup.dart b/lib/pages/onboarding_page/widgets/account_setup.dart new file mode 100644 index 0000000..b71e633 --- /dev/null +++ b/lib/pages/onboarding_page/widgets/account_setup.dart @@ -0,0 +1,216 @@ +import 'dart:ui'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '/model/budget.dart'; +import '/providers/categories_provider.dart'; +import '/constants/constants.dart'; +import '/constants/style.dart'; +import '/model/category_transaction.dart'; +import '/providers/budgets_provider.dart'; +import 'package:collection/collection.dart'; + +class AccountSetup extends ConsumerStatefulWidget { + const AccountSetup({Key? key}) : super(key: key); + + @override + ConsumerState createState() => _AccountSetupState(); +} + +class _AccountSetupState extends ConsumerState { + TextEditingController accountNameController = TextEditingController(); + TextEditingController amountController = TextEditingController(); + + @override + Widget build(BuildContext context) { + accountNameController.text = "Main account"; + + return Scaffold( + backgroundColor: blue7, + body: Center( + child: Column( + children: [ + const SizedBox(height: 40), + Text("STEP 2 OF 2", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Text( + "Set the liquidity in your main\naccount", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox(height: 20), + Text( + "It will be used as a baseline to which you can add\nincome, expenses and calculate your wealth.\n\nYou’ll be able to add more accounts within the app.", + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + const SizedBox(height: 10), + Container( + margin: const EdgeInsets.only(left: 25.0, right: 25.0), + padding: const EdgeInsets.only(left: 20.0, right: 20.0), + decoration: BoxDecoration( + color: white, + shape: BoxShape.rectangle, + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 20, + offset: const Offset(2, 2), + ), + ], + borderRadius: const BorderRadius.all(Radius.circular(20))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("ACCOUNT NAME ", + style: Theme.of(context).textTheme.labelSmall), + const Icon(Icons.edit, size: 10) + ], + ), + TextField( + style: Theme.of(context) + .textTheme + .headlineMedium + ?.apply(color: black), + textAlign: TextAlign.center, + controller: accountNameController, + decoration: const InputDecoration( + border: UnderlineInputBorder( + borderSide: BorderSide(color: Colors.black, width: 0.8), + ), + ), + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("SET AMOUNT ", + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith(color: blue1)), + const Icon(Icons.edit, size: 10) + ], + ), + TextField( + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + controller: amountController, + decoration: InputDecoration( + hintText: "e.g 1300 €", + hintStyle: Theme.of(context).textTheme.bodySmall, + border: const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.black, width: 0.8), + ), + ), + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("EDIT ICON AND COLOR ", + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith(color: blue1)), + const Icon(Icons.edit, size: 10) + ], + ), + const SizedBox(height: 10), + ElevatedButton( + // TO DO - icona modificabile + onPressed: () {}, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + padding: const EdgeInsets.all(10), + backgroundColor: blue5, + ), + child: const Icon( + Icons.account_balance, + size: 40, + color: white, + ), + ), + const SizedBox(height: 15), + ], + ), + ), + const Spacer(), + Text('Or you can skip this step and start from 0', + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: blue1)), + const SizedBox(height: 5), + SizedBox( + width: 156, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/'); + }, + style: ElevatedButton.styleFrom( + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Container( + padding: const EdgeInsets.only(bottom: 1.0), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(width: 1.2, color: black), + ), + ), + child: Row( + children: [ + Text( + 'START FROM 0 ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1), + ), + const Icon(Icons.arrow_forward, size: 15, color: blue1), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + SizedBox( + width: 342, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pushNamed('/'); + }, + style: ElevatedButton.styleFrom( + backgroundColor: grey2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('START TRACKING YOUR EXPENSES', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } +} diff --git a/lib/pages/onboarding_page/widgets/budget_setup.dart b/lib/pages/onboarding_page/widgets/budget_setup.dart new file mode 100644 index 0000000..93d10f7 --- /dev/null +++ b/lib/pages/onboarding_page/widgets/budget_setup.dart @@ -0,0 +1,390 @@ +import 'dart:ui'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:sossoldi/pages/onboarding_page/widgets/account_setup.dart'; +import '/model/budget.dart'; +import '/providers/categories_provider.dart'; +import '/constants/constants.dart'; +import '/constants/style.dart'; +import '/model/category_transaction.dart'; +import '/providers/budgets_provider.dart'; +import 'package:collection/collection.dart'; + +class BudgetSetup extends ConsumerStatefulWidget { + const BudgetSetup({Key? key}) : super(key: key); + + @override + ConsumerState createState() => _BudgetSetupState(); +} + +class _BudgetSetupState extends ConsumerState { + // sum of the budget of the selected cards + int totalBudget = 0; + + @override + Widget build(BuildContext context) { + final categoriesGrid = ref.watch(categoriesProvider); + return Scaffold( + backgroundColor: blue7, + body: Center( + child: Column( + children: [ + const SizedBox(height: 40), + Text("STEP 1 OF 2", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Text( + "Set up your monthly\nbudgets", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox(height: 20), + Text( + "Choose which categories you want to set a budget for", + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + const SizedBox(height: 5), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + top: 0, bottom: 0, left: 16, right: 16), + child: NotificationListener( + onNotification: (OverscrollIndicatorNotification overscroll) { + overscroll.disallowIndicator(); + return true; + }, + child: categoriesGrid.when( + data: (categories) => GridView.builder( + itemCount: categories.length + 1, + scrollDirection: Axis.vertical, + gridDelegate: + const SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 300, + childAspectRatio: 3, + crossAxisSpacing: 18, + mainAxisSpacing: 12, + ), + itemBuilder: (context, i) { + if (i < categories.length) { + return GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (context) => NumericKeyboardDialog( + categories.elementAt(i)), + ); + }, + child: Container( + child: buildCard(categories.elementAt(i)), + ), + ); + } else { + return GestureDetector( + onTap: () => Navigator.of(context) + .pushNamed('/add-category'), + child: buildDefaultCard(), + ); + } + }, + ), + error: (err, stack) => Text('Error: $err'), + loading: () => const Center( + child: CircularProgressIndicator(), + ), + ), + ), + ), + ), + + // if the total budget (sum of the budget of the selected cards) is > 0, set the other layout. otherwise set the "continue without budget" button + totalBudget > 0 + ? Center( + child: Column( + children: [ + Text("Monthly budget total:", + style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + RichText( + textScaleFactor: + MediaQuery.of(context).textScaleFactor, + text: TextSpan( + children: [ + TextSpan( + text: totalBudget.toString(), + style: + Theme.of(context).textTheme.displayMedium, + ), + TextSpan( + text: "€", + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply( + fontFeatures: [ + const FontFeature.subscripts() + ], + ), + ), + ], + ), + ), + const SizedBox(height: 20), + SizedBox( + width: 342, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const AccountSetup()), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('NEXT STEP', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), + ], + ), + ) + : Padding( + padding: const EdgeInsets.only(left: 75, right: 75), + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const AccountSetup()), + ); + }, + style: ElevatedButton.styleFrom( + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Container( + padding: const EdgeInsets.only(bottom: 1.0), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(width: 1.2, color: black))), + child: Row( + children: [ + Text('CONTINUE WITHOUT BUDGET ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1)), + const Icon(Icons.arrow_forward, + size: 15, color: blue1), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } + + Widget buildCard(CategoryTransaction category) { + final budgetsList = ref.watch(budgetsProvider); + Color categoryColor = categoryColorList[category.color]; + String categoryName = category.name; + if (budgetsList is AsyncData>) { + final budgets = budgetsList.value; + + Budget? budget = + budgets?.firstWhereOrNull((c) => c.idCategory == category.id); + + if (budget != null && budget.active) { + return Container( + color: categoryColor, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: categoryColor, width: 2.5), + color: categoryColor, + borderRadius: const BorderRadius.all(Radius.circular(8))), + alignment: Alignment.center, + child: Row( + children: [ + CircleAvatar( + backgroundColor: categoryColor, + radius: 15.0, + child: CircleAvatar( + backgroundColor: white, + radius: 13, + child: Icon(Icons.check, color: categoryColor, size: 22), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 125, + child: Text( + categoryName, + textAlign: TextAlign.left, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply(color: white), + ), + ), + SizedBox( + width: 95, + child: Text( + "BUDGET: ${budget.amountLimit}€", + style: Theme.of(context) + .textTheme + .bodySmall + ?.apply(color: white), + ), + ), + ], + ) + ], + ), + ), + ); + } + } + return Container( + decoration: BoxDecoration( + border: Border.all(color: categoryColor, width: 2.5), + color: HSLColor.fromColor(categoryColor) + .withLightness(clampDouble(0.99, 0.0, 0.9)) + .toColor(), + borderRadius: const BorderRadius.all( + Radius.circular(8), + ), + ), + alignment: Alignment.center, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: CircleAvatar( + backgroundColor: blue1, + radius: 15.0, + child: CircleAvatar( + backgroundColor: HSLColor.fromColor(categoryColor) + .withLightness(clampDouble(0.99, 0.0, 0.9)) + .toColor(), + radius: 13, + child: const Icon(Icons.add, color: blue1)), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 95, + child: Text( + categoryName, + textAlign: TextAlign.left, + style: Theme.of(context).textTheme.bodyMedium, + )), + SizedBox( + width: 95, + child: Text("ADD BUDGET", + style: Theme.of(context).textTheme.bodySmall)), + ], + ), + ], + ), + ); + } + + Widget buildDefaultCard() { + return Container( + decoration: BoxDecoration( + border: Border.all(color: grey2, width: 0.5), + color: grey3, + borderRadius: const BorderRadius.all( + Radius.circular(8), + ), + ), + alignment: Alignment.center, + child: Row( + children: [ + const Padding( + padding: EdgeInsets.only(left: 10), + child: CircleAvatar( + backgroundColor: grey1, + radius: 15.0, + child: CircleAvatar( + backgroundColor: grey3, + radius: 13, + child: Icon(Icons.add, color: grey1), + ), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 125, + child: Text( + "Add category", + textAlign: TextAlign.left, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply(color: grey1), + ), + ), + ], + ), + ], + ), + ); + } +} + +class NumericKeyboardDialog extends StatelessWidget { + final CategoryTransaction category; + const NumericKeyboardDialog(this.category, {super.key}); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, ref, _) { + return AlertDialog( + title: Text('Add budget for ${category.name}'), + content: const TextField( + keyboardType: TextInputType.number, + ), + actions: [ + ElevatedButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Confirm'), + ), + ], + ); + }, + ); + } +} + From bfa5f072ca7caaf91a4cd6085c67dca65b477f80 Mon Sep 17 00:00:00 2001 From: mene412 Date: Fri, 9 Jun 2023 20:04:13 +0200 Subject: [PATCH 6/9] First try for using providers for budgets --- .../onboarding_page/widgets/add_budget.dart | 65 +++++++++++++++++++ .../onboarding_page/widgets/budget_setup.dart | 33 +--------- lib/providers/budgets_provider.dart | 27 ++++++-- 3 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 lib/pages/onboarding_page/widgets/add_budget.dart diff --git a/lib/pages/onboarding_page/widgets/add_budget.dart b/lib/pages/onboarding_page/widgets/add_budget.dart new file mode 100644 index 0000000..b1f7321 --- /dev/null +++ b/lib/pages/onboarding_page/widgets/add_budget.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sossoldi/constants/functions.dart'; +import 'package:sossoldi/providers/budgets_provider.dart'; + +import '../../../model/category_transaction.dart'; + +class AddBudget extends ConsumerStatefulWidget { + final CategoryTransaction category; + + const AddBudget(this.category, {Key? key}) : super(key: key); + + @override + ConsumerState createState() => _AddBudgetState(); +} + +class _AddBudgetState extends ConsumerState with Functions { + final TextEditingController amountController = TextEditingController(); + + @override + void dispose() { + ref.invalidate(selectedBudgetProvider); + ref.invalidate(budgetCategoryIdProvider); + ref.invalidate(budgetNameProvider); + ref.invalidate(budgetAmountLimitProvider); + ref.invalidate(budgetAmountLimitProvider); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final amountLimit = ref.read(budgetAmountLimitProvider); + setState(() { + amountController.text = (amountLimit).toString(); + }); + + return AlertDialog( + title: Text('Add budget for ${widget.category.name}'), + content: TextField( + controller: amountController, + keyboardType: TextInputType.number, + onChanged: (value) => ref.read(budgetAmountLimitProvider.notifier).state = value as num, + ), + actions: [ + ElevatedButton( + onPressed: () async { + ref.read(budgetActiveProvider.notifier).state = true; + ref.read(budgetNameProvider.notifier).state = widget.category.name; + ref.read(budgetCategoryIdProvider.notifier).state = widget.category.id!; + ref.read(budgetsProvider.notifier).addBudget().whenComplete(() => Navigator.pop(context)); + print('ok'); + }, + child: const Text('Confirm'), + ), + ElevatedButton( + onPressed: () { + ref.read(budgetActiveProvider.notifier).state = false; + Navigator.pop(context); + }, + child: const Text('Cancel'), + ), + ], + ); + } +} diff --git a/lib/pages/onboarding_page/widgets/budget_setup.dart b/lib/pages/onboarding_page/widgets/budget_setup.dart index 93d10f7..9056062 100644 --- a/lib/pages/onboarding_page/widgets/budget_setup.dart +++ b/lib/pages/onboarding_page/widgets/budget_setup.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:sossoldi/pages/onboarding_page/widgets/account_setup.dart'; +import 'package:sossoldi/pages/onboarding_page/widgets/add_budget.dart'; import '/model/budget.dart'; import '/providers/categories_provider.dart'; import '/constants/constants.dart'; @@ -76,7 +77,7 @@ class _BudgetSetupState extends ConsumerState { onTap: () { showDialog( context: context, - builder: (context) => NumericKeyboardDialog( + builder: (context) => AddBudget( categories.elementAt(i)), ); }, @@ -359,32 +360,4 @@ class _BudgetSetupState extends ConsumerState { ), ); } -} - -class NumericKeyboardDialog extends StatelessWidget { - final CategoryTransaction category; - const NumericKeyboardDialog(this.category, {super.key}); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (context, ref, _) { - return AlertDialog( - title: Text('Add budget for ${category.name}'), - content: const TextField( - keyboardType: TextInputType.number, - ), - actions: [ - ElevatedButton( - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Confirm'), - ), - ], - ); - }, - ); - } -} - +} \ No newline at end of file diff --git a/lib/providers/budgets_provider.dart b/lib/providers/budgets_provider.dart index 78801db..240e256 100644 --- a/lib/providers/budgets_provider.dart +++ b/lib/providers/budgets_provider.dart @@ -1,6 +1,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../model/budget.dart'; +final selectedBudgetProvider = StateProvider((ref) => null); +final budgetCategoryIdProvider = StateProvider((ref) => 0); +final budgetNameProvider = StateProvider((ref) => null); +final budgetAmountLimitProvider = StateProvider((ref) => 0); +final budgetActiveProvider = StateProvider((ref) => false); + class AsyncBudgetsNotifier extends AsyncNotifier> { @override Future> build() async { @@ -12,18 +18,31 @@ class AsyncBudgetsNotifier extends AsyncNotifier> { return account; } - Future addAccount(Budget account) async { + Future addBudget() async { state = const AsyncValue.loading(); + + Budget budget = Budget( + idCategory: ref.read(budgetCategoryIdProvider), + amountLimit: ref.read(budgetAmountLimitProvider), + active: ref.read(budgetActiveProvider), + ); + state = await AsyncValue.guard(() async { - await BudgetMethods().insert(account); + await BudgetMethods().insert(budget); return _getBudgets(); }); } - Future updateAccount(Budget account) async { + Future updateBudget(Budget budget) async { + Budget editBudget = budget.copy( + idCategory: ref.read(budgetCategoryIdProvider), + amountLimit: ref.read(budgetAmountLimitProvider), + active: ref.read(budgetActiveProvider), + ); + state = const AsyncValue.loading(); state = await AsyncValue.guard(() async { - await BudgetMethods().updateItem(account); + await BudgetMethods().updateItem(editBudget); return _getBudgets(); }); } From dae4775b37435b5ad7b0e1b3631560b787275aa3 Mon Sep 17 00:00:00 2001 From: mene412 Date: Sun, 16 Jul 2023 22:06:34 +0200 Subject: [PATCH 7/9] UI update - Update the keyboard for entering the budget. - Update the "EDIT ICON AND COLOR" section in `account_setup.dart`. TODO: - Make the onboarding page visible only on the first visit. - Connect the "ADD BUDGET" feature and the `account_setup.dart` page with the database. - Validate the presence of data when the "START TRACKING YOUR EXPENSES" button is pressed. --- .../onboarding_page/onboarding_page.dart | 10 +- .../widgets/account_setup.dart | 121 ++++++++++--- .../onboarding_page/widgets/add_budget.dart | 43 +++-- .../onboarding_page/widgets/budget_setup.dart | 165 +++++++++--------- 4 files changed, 218 insertions(+), 121 deletions(-) diff --git a/lib/pages/onboarding_page/onboarding_page.dart b/lib/pages/onboarding_page/onboarding_page.dart index 773c895..60f16e5 100644 --- a/lib/pages/onboarding_page/onboarding_page.dart +++ b/lib/pages/onboarding_page/onboarding_page.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:sossoldi/pages/onboarding_page/widgets/budget_setup.dart'; +import '/pages/onboarding_page/widgets/budget_setup.dart'; import '/constants/style.dart'; class Onboarding extends StatefulWidget { @@ -9,6 +9,8 @@ class Onboarding extends StatefulWidget { State createState() => _OnboardingState(); } +//TODO: make visible only at the first access in the app + class _OnboardingState extends State { @override Widget build(BuildContext context) { @@ -26,7 +28,7 @@ class _OnboardingState extends State { style: Theme.of(context) .textTheme .headlineLarge - ?.copyWith(color: Theme.of(context).colorScheme.primary), + ?.copyWith(color: blue1), ), const SizedBox( height: 80, @@ -68,7 +70,7 @@ class _OnboardingState extends State { style: Theme.of(context) .textTheme .bodyMedium - ?.copyWith(color: Colors.white), + ?.copyWith(color: white), ), ), ), @@ -78,4 +80,4 @@ class _OnboardingState extends State { ), ); } -} \ No newline at end of file +} diff --git a/lib/pages/onboarding_page/widgets/account_setup.dart b/lib/pages/onboarding_page/widgets/account_setup.dart index b71e633..608c49d 100644 --- a/lib/pages/onboarding_page/widgets/account_setup.dart +++ b/lib/pages/onboarding_page/widgets/account_setup.dart @@ -1,15 +1,10 @@ -import 'dart:ui'; - import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '/model/budget.dart'; -import '/providers/categories_provider.dart'; -import '/constants/constants.dart'; +import '../../../constants/constants.dart'; +import '../../../providers/accounts_provider.dart'; import '/constants/style.dart'; -import '/model/category_transaction.dart'; -import '/providers/budgets_provider.dart'; -import 'package:collection/collection.dart'; + +final showAccountIconsProvider = StateProvider.autoDispose((ref) => false); class AccountSetup extends ConsumerStatefulWidget { const AccountSetup({Key? key}) : super(key: key); @@ -25,9 +20,12 @@ class _AccountSetupState extends ConsumerState { @override Widget build(BuildContext context) { accountNameController.text = "Main account"; + final accountIcon = ref.watch(accountIconProvider); + final accountColor = ref.watch(accountColorProvider); return Scaffold( backgroundColor: blue7, + resizeToAvoidBottomInset: false, body: Center( child: Column( children: [ @@ -84,6 +82,7 @@ class _AccountSetupState extends ConsumerState { ?.apply(color: black), textAlign: TextAlign.center, controller: accountNameController, + autofocus: true, decoration: const InputDecoration( border: UnderlineInputBorder( borderSide: BorderSide(color: Colors.black, width: 0.8), @@ -126,22 +125,99 @@ class _AccountSetupState extends ConsumerState { const Icon(Icons.edit, size: 10) ], ), + const SizedBox(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(90)), + onTap: () => ref.read(showAccountIconsProvider.notifier).state = true, + child: Ink( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: accountColorList[accountColor], + ), + padding: const EdgeInsets.all(16), + child: Icon( + accountIconList[accountIcon], + size: 36, + color: Theme.of(context).colorScheme.background, + ), + ), + ), + ), const SizedBox(height: 10), - ElevatedButton( - // TO DO - icona modificabile - onPressed: () {}, - style: ElevatedButton.styleFrom( - shape: const CircleBorder(), - padding: const EdgeInsets.all(10), - backgroundColor: blue5, + const Divider(height: 1, color: grey2), + const SizedBox(height: 12), + SizedBox( + height: 38, + child: ListView.separated( + scrollDirection: Axis.horizontal, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 16), + separatorBuilder: (context, index) => const SizedBox(width: 16), + itemBuilder: (context, index) { + Color color = accountColorList[index]; + return GestureDetector( + onTap: () => ref.read(accountColorProvider.notifier).state = index, + child: Container( + height: accountColorList[accountColor] == color ? 38 : 32, + width: accountColorList[accountColor] == color ? 38 : 32, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: color, + border: accountColorList[accountColor] == color + ? Border.all( + color: Theme.of(context).colorScheme.primary, + width: 3, + ) + : null, + ), + ), + ); + }, + itemCount: accountColorList.length, ), - child: const Icon( - Icons.account_balance, - size: 40, - color: white, + ), + const SizedBox(height: 12,), + const Divider(height: 1, color: grey2), + const SizedBox(height: 12), + SizedBox( + height: 38, + child: ListView.separated( + scrollDirection: Axis.horizontal, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 16), + separatorBuilder: (context, index) => const SizedBox(width: 16), + itemBuilder: (context, index) { + IconData accountIconData = + accountIconList.values.elementAt(index); + String accountIconName = accountIconList.keys.elementAt(index); + return GestureDetector( + onTap: () => ref.read(accountIconProvider.notifier).state = + accountIconName, + child: Container( + width: 38, + height: 38, + margin: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: accountIconList[accountIcon] == accountIconData + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.surface, + shape: BoxShape.circle,), + child: Icon( + accountIconData, + color: accountIconList[accountIcon] == accountIconData + ? Colors.white + : Theme.of(context).colorScheme.primary, + size: 24, + ), + ), + ); + }, + itemCount: accountIconList.length, ), ), - const SizedBox(height: 15), + const SizedBox(height: 12,), ], ), ), @@ -186,12 +262,13 @@ class _AccountSetupState extends ConsumerState { ), ), ), - const SizedBox(height: 20), + const SizedBox(height: 30), SizedBox( width: 342, height: 48, child: ElevatedButton( onPressed: () { + //TODO: check if data are present Navigator.of(context).pushNamed('/'); }, style: ElevatedButton.styleFrom( diff --git a/lib/pages/onboarding_page/widgets/add_budget.dart b/lib/pages/onboarding_page/widgets/add_budget.dart index b1f7321..cc9cac3 100644 --- a/lib/pages/onboarding_page/widgets/add_budget.dart +++ b/lib/pages/onboarding_page/widgets/add_budget.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:sossoldi/constants/functions.dart'; +import 'package:sossoldi/constants/style.dart'; import 'package:sossoldi/providers/budgets_provider.dart'; import '../../../model/category_transaction.dart'; @@ -35,29 +36,47 @@ class _AddBudgetState extends ConsumerState with Functions { }); return AlertDialog( - title: Text('Add budget for ${widget.category.name}'), + title: Text( + 'Add budget for ${widget.category.name}', + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), content: TextField( controller: amountController, keyboardType: TextInputType.number, - onChanged: (value) => ref.read(budgetAmountLimitProvider.notifier).state = value as num, + onChanged: (value) => + ref.read(budgetAmountLimitProvider.notifier).state = value as num, ), actions: [ + TextButton( + onPressed: () { + ref.read(budgetActiveProvider.notifier).state = false; + Navigator.pop(context); + }, + child: Text('CANCEL', style: Theme.of(context).textTheme.bodyMedium?.apply(color: black),), + ), ElevatedButton( onPressed: () async { ref.read(budgetActiveProvider.notifier).state = true; ref.read(budgetNameProvider.notifier).state = widget.category.name; - ref.read(budgetCategoryIdProvider.notifier).state = widget.category.id!; - ref.read(budgetsProvider.notifier).addBudget().whenComplete(() => Navigator.pop(context)); + ref.read(budgetCategoryIdProvider.notifier).state = + widget.category.id!; + ref + .read(budgetsProvider.notifier) + .addBudget() + .whenComplete(() => Navigator.pop(context)); print('ok'); }, - child: const Text('Confirm'), - ), - ElevatedButton( - onPressed: () { - ref.read(budgetActiveProvider.notifier).state = false; - Navigator.pop(context); - }, - child: const Text('Cancel'), + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text( + 'CONFIRM', + style: Theme.of(context).textTheme.bodyMedium?.apply(color: white), + ), ), ], ); diff --git a/lib/pages/onboarding_page/widgets/budget_setup.dart b/lib/pages/onboarding_page/widgets/budget_setup.dart index 9056062..e265ed5 100644 --- a/lib/pages/onboarding_page/widgets/budget_setup.dart +++ b/lib/pages/onboarding_page/widgets/budget_setup.dart @@ -3,8 +3,8 @@ import 'dart:ui'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:sossoldi/pages/onboarding_page/widgets/account_setup.dart'; -import 'package:sossoldi/pages/onboarding_page/widgets/add_budget.dart'; +import '/pages/onboarding_page/widgets/account_setup.dart'; +import '/pages/onboarding_page/widgets/add_budget.dart'; import '/model/budget.dart'; import '/providers/categories_provider.dart'; import '/constants/constants.dart'; @@ -43,14 +43,13 @@ class _BudgetSetupState extends ConsumerState { .headlineLarge ?.copyWith(color: blue1), ), - const SizedBox(height: 20), + const SizedBox(height: 30), Text( "Choose which categories you want to set a budget for", textAlign: TextAlign.center, style: - Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), ), - const SizedBox(height: 5), Expanded( child: Padding( padding: const EdgeInsets.only( @@ -65,7 +64,7 @@ class _BudgetSetupState extends ConsumerState { itemCount: categories.length + 1, scrollDirection: Axis.vertical, gridDelegate: - const SliverGridDelegateWithMaxCrossAxisExtent( + const SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 300, childAspectRatio: 3, crossAxisSpacing: 18, @@ -77,8 +76,8 @@ class _BudgetSetupState extends ConsumerState { onTap: () { showDialog( context: context, - builder: (context) => AddBudget( - categories.elementAt(i)), + builder: (context) => + AddBudget(categories.elementAt(i)), ); }, child: Container( @@ -106,39 +105,65 @@ class _BudgetSetupState extends ConsumerState { // if the total budget (sum of the budget of the selected cards) is > 0, set the other layout. otherwise set the "continue without budget" button totalBudget > 0 ? Center( - child: Column( - children: [ - Text("Monthly budget total:", - style: Theme.of(context).textTheme.bodySmall), - const SizedBox(height: 10), - RichText( - textScaleFactor: - MediaQuery.of(context).textScaleFactor, - text: TextSpan( + child: Column( children: [ - TextSpan( - text: totalBudget.toString(), - style: - Theme.of(context).textTheme.displayMedium, - ), - TextSpan( - text: "€", - style: Theme.of(context) - .textTheme - .bodyMedium - ?.apply( - fontFeatures: [ - const FontFeature.subscripts() + Text("Monthly budget total:", + style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + RichText( + textScaleFactor: + MediaQuery.of(context).textScaleFactor, + text: TextSpan( + children: [ + TextSpan( + text: totalBudget.toString(), + style: + Theme.of(context).textTheme.displayMedium, + ), + TextSpan( + text: "€", + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply( + fontFeatures: [ + const FontFeature.subscripts() + ], + ), + ), ], ), ), + const SizedBox(height: 20), + SizedBox( + width: 342, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const AccountSetup()), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('NEXT STEP', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), ], ), - ), - const SizedBox(height: 20), - SizedBox( - width: 342, - height: 48, + ) + : Padding( + padding: const EdgeInsets.only(left: 75, right: 75), child: ElevatedButton( onPressed: () { Navigator.push( @@ -148,55 +173,29 @@ class _BudgetSetupState extends ConsumerState { ); }, style: ElevatedButton.styleFrom( - backgroundColor: blue5, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Container( + padding: const EdgeInsets.only(bottom: 1.0), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(width: 1.2, color: black))), + child: Row( + children: [ + Text('CONTINUE WITHOUT BUDGET ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1)), + const Icon(Icons.arrow_forward, + size: 15, color: blue1), + ], ), ), - child: Text('NEXT STEP', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: Colors.white)), ), ), - ], - ), - ) - : Padding( - padding: const EdgeInsets.only(left: 75, right: 75), - child: ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const AccountSetup()), - ); - }, - style: ElevatedButton.styleFrom( - elevation: 0.0, - shadowColor: Colors.transparent, - backgroundColor: Colors.transparent, - ), - child: Container( - padding: const EdgeInsets.only(bottom: 1.0), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(width: 1.2, color: black))), - child: Row( - children: [ - Text('CONTINUE WITHOUT BUDGET ', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: blue1)), - const Icon(Icons.arrow_forward, - size: 15, color: blue1), - ], - ), - ), - ), - ), const SizedBox(height: 20), ], ), @@ -212,7 +211,7 @@ class _BudgetSetupState extends ConsumerState { final budgets = budgetsList.value; Budget? budget = - budgets?.firstWhereOrNull((c) => c.idCategory == category.id); + budgets?.firstWhereOrNull((c) => c.idCategory == category.id); if (budget != null && budget.active) { return Container( @@ -318,7 +317,7 @@ class _BudgetSetupState extends ConsumerState { Widget buildDefaultCard() { return Container( decoration: BoxDecoration( - border: Border.all(color: grey2, width: 0.5), + border: Border.all(color: grey2, width: 1.5), color: grey3, borderRadius: const BorderRadius.all( Radius.circular(8), @@ -360,4 +359,4 @@ class _BudgetSetupState extends ConsumerState { ), ); } -} \ No newline at end of file +} From 77fbd3d08a79f17a24d5b971babdd0a5a5d9ed22 Mon Sep 17 00:00:00 2001 From: Matteo Meneghin Date: Thu, 18 Jan 2024 18:48:04 +0100 Subject: [PATCH 8/9] Update pubspec.lock --- pubspec.lock | 443 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 275 insertions(+), 168 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index b932601..2b082aa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,154 +5,184 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "61.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "5.13.0" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" + url: "https://pub.dev" + source: hosted + version: "2.0.2" archive: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.4.10" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" circular_menu: dependency: "direct main" description: name: circular_menu - url: "https://pub.dartlang.org" + sha256: "253e5e7aaf107e84251b0c51fb66ae17f6caaebf973eb30049f02b999646373a" + url: "https://pub.dev" source: hosted version: "2.0.1" cli_util: dependency: transitive description: name: cli_util - url: "https://pub.dartlang.org" + sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + url: "https://pub.dev" source: hosted version: "0.3.5" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.2" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted version: "3.1.1" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" + url: "https://pub.dev" source: hosted - version: "1.6.1" + version: "1.6.4" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" source: hosted - version: "0.17.2" + version: "1.0.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" equatable: dependency: transitive description: name: equatable - url: "https://pub.dartlang.org" + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" source: hosted version: "2.0.5" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" fl_chart: dependency: "direct main" description: name: fl_chart - url: "https://pub.dartlang.org" + sha256: "749b3342ea3e95cbf61a0fec31a62606e837377b8b6d0caa7367a7ef80f38b7d" + url: "https://pub.dev" source: hosted version: "0.55.2" flutter: @@ -164,35 +194,40 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - url: "https://pub.dartlang.org" + sha256: "02dcaf49d405f652b7160e882bacfc02cb497041bb2eab2a49b1c393cf9aac12" + url: "https://pub.dev" source: hosted version: "0.12.0" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.3" flutter_native_splash: dependency: "direct main" description: name: flutter_native_splash - url: "https://pub.dartlang.org" + sha256: "17d9671396fb8ec45ad10f4a975eb8a0f70bedf0fdaf0720b31ea9de6da8c4da" + url: "https://pub.dev" source: hosted - version: "2.2.18" + version: "2.3.7" flutter_riverpod: dependency: "direct main" description: name: flutter_riverpod - url: "https://pub.dartlang.org" + sha256: da9591d1f8d5881628ccd5c25c40e74fc3eef50ba45e40c3905a06e1712412d5 + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.9" flutter_staggered_grid_view: dependency: "direct main" description: name: flutter_staggered_grid_view - url: "https://pub.dartlang.org" + sha256: f0b6d8c0fa7b4b444985cdde68492c0138a4fb6fc57a641b24cb234b7ee0f5c4 + url: "https://pub.dev" source: hosted version: "0.4.1" flutter_test: @@ -209,212 +244,242 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" source: hosted - version: "0.15.3" + version: "0.15.4" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" image: dependency: transitive description: name: image - url: "https://pub.dartlang.org" + sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" + url: "https://pub.dev" source: hosted - version: "4.0.17" + version: "4.1.4" intl: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.7" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.5.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.4" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" percent_indicator: dependency: "direct main" description: name: percent_indicator - url: "https://pub.dartlang.org" + sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c + url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.2.3" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.4.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.8" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" riverpod: dependency: transitive description: name: riverpod - url: "https://pub.dartlang.org" + sha256: "942999ee48b899f8a46a860f1e13cee36f2f77609eb54c5b7a669bb20d550b11" + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.9" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -424,240 +489,282 @@ packages: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" source: hosted version: "2.1.1" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" source: hosted - version: "0.10.11" + version: "0.10.12" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.10.0" sqflite: dependency: "direct main" description: name: sqflite - url: "https://pub.dartlang.org" + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + url: "https://pub.dev" source: hosted - version: "2.4.0+2" + version: "2.5.0+2" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - url: "https://pub.dartlang.org" + sha256: "35d2fce1e971707c227cc4775cc017d5eafe06c2654c3435ebd5c3ad6c170f5f" + url: "https://pub.dev" source: hosted - version: "2.2.0+1" + version: "2.3.0+4" sqlite3: dependency: transitive description: name: sqlite3 - url: "https://pub.dartlang.org" + sha256: db65233e6b99e99b2548932f55a987961bc06d82a31a0665451fa0b4fff4c3fb + url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "2.1.0" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - url: "https://pub.dartlang.org" + sha256: "90963b515721d6a71e96f438175cf43c979493ed14822860a300b69694c74eb6" + url: "https://pub.dev" source: hosted - version: "0.5.10" + version: "0.5.19+1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" state_notifier: dependency: transitive description: name: state_notifier - url: "https://pub.dartlang.org" + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" source: hosted - version: "0.7.2+1" + version: "1.0.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" source: hosted - version: "3.0.0+3" + version: "3.1.0+1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test: dependency: "direct dev" description: name: test - url: "https://pub.dartlang.org" + sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + url: "https://pub.dev" source: hosted - version: "1.21.4" + version: "1.24.3" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.6.0" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.3" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" universal_io: dependency: transitive description: name: universal_io - url: "https://pub.dartlang.org" + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.2" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: d25bb0ca00432a5e1ee40e69c36c85863addf7cc45e433769d61bed3fe81fd96 + url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.2.3" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + url: "https://pub.dev" source: hosted - version: "6.0.34" + version: "6.2.2" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "6.2.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.1.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.3.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.2.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.1.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + url: "https://pub.dev" source: hosted - version: "9.4.0" + version: "11.10.0" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.3.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" \ No newline at end of file + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.13.0" From a51ca8a195ac90b7acd8b92a9c8dd641a55a74dd Mon Sep 17 00:00:00 2001 From: Matteo Meneghin Date: Tue, 6 Feb 2024 18:54:10 +0100 Subject: [PATCH 9/9] Update build.gradle --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 8ac4d8e..9bc02fa 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir }