// ignore_for_file: inference_failure_on_function_invocation import 'package:currency_picker/currency_picker.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:flex_color_picker/flex_color_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_iconpicker/flutter_iconpicker.dart'; import 'package:introduction_screen/introduction_screen.dart'; import 'package:prasule/api/category.dart'; import 'package:prasule/api/wallet.dart'; import 'package:prasule/api/walletmanager.dart'; import 'package:prasule/pw/platformbutton.dart'; import 'package:prasule/pw/platformdialog.dart'; import 'package:prasule/pw/platformfield.dart'; import 'package:prasule/pw/platformroute.dart'; import 'package:prasule/util/text_color.dart'; import 'package:prasule/views/home.dart'; import 'package:shared_preferences/shared_preferences.dart'; /// View that shows on first-time setup class SetupView extends StatefulWidget { /// View that shows on first-time setup const SetupView({super.key, this.newWallet = false}); /// We are only creating a new wallet, no first-time setup final bool newWallet; @override State createState() => _SetupViewState(); } class _SetupViewState extends State { var _selectedCurrency = Currency.from( json: { "code": "USD", "name": "United States Dollar", "symbol": r"$", "flag": "USD", "decimal_digits": 2, "number": 840, "name_plural": "US dollars", "thousands_separator": ",", "decimal_separator": ".", "space_between_amount_and_symbol": false, "symbol_on_left": true, }, ); List categories = []; String name = ""; double balance = 0; @override void didChangeDependencies() { super.didChangeDependencies(); if (categories.isEmpty) { categories = [ WalletCategory( name: AppLocalizations.of(context).noCategory, id: 0, icon: IconData( Icons.payments.codePoint, fontFamily: 'MaterialIcons', ), color: Colors.transparent, ), WalletCategory( name: AppLocalizations.of(context).categoryHealth, id: 1, icon: IconData( Icons.medical_information.codePoint, fontFamily: 'MaterialIcons', ), color: Colors.red.shade700 .harmonizeWith(Theme.of(context).colorScheme.primary), ), WalletCategory( name: AppLocalizations.of(context).categoryCar, id: 2, icon: IconData(Icons.car_repair.codePoint, fontFamily: 'MaterialIcons'), color: Colors.purple .harmonizeWith(Theme.of(context).colorScheme.primary), ), WalletCategory( name: AppLocalizations.of(context).categoryFood, id: 3, icon: IconData(Icons.restaurant.codePoint, fontFamily: 'MaterialIcons'), color: Colors.green.shade700 .harmonizeWith(Theme.of(context).colorScheme.primary), ), WalletCategory( name: AppLocalizations.of(context).categoryTravel, id: 4, icon: IconData(Icons.train.codePoint, fontFamily: 'MaterialIcons'), color: Colors.orange.shade700 .harmonizeWith(Theme.of(context).colorScheme.primary), ), ]; setState(() {}); } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: IntroductionScreen( dotsDecorator: DotsDecorator( activeColor: Theme.of(context).colorScheme.primary, ), showBackButton: true, next: Text(AppLocalizations.of(context).next), back: Text(AppLocalizations.of(context).back), done: Text(AppLocalizations.of(context).finish), onDone: () { if (name.isEmpty) { ScaffoldMessenger.of(context) .clearSnackBars(); // TODO: iOS replacement ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context).errorEmptyName), ), ); return; } final wallet = Wallet( name: name, currency: _selectedCurrency, categories: categories, ); WalletManager.saveWallet(wallet).then( (value) { if (!value) { ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context).walletExists), ), ); return; } if (widget.newWallet) { Navigator.of(context).pop(); return; } Navigator.of(context).pushReplacement( platformRoute( (c) => const HomeView(), ), ); }, ); }, pages: [ PageViewModel( decoration: const PageDecoration(bodyAlignment: Alignment.center), titleWidget: Padding( padding: const EdgeInsets.all(8), child: Text( AppLocalizations.of(context).welcome, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), ), bodyWidget: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ if (!widget.newWallet) Flexible( child: Text( AppLocalizations.of(context).welcomeAboutPrasule, ), ), if (!widget.newWallet) const SizedBox( height: 5, ), Flexible( child: Text( AppLocalizations.of(context).welcomeInstruction, ), ), ], ), ), PageViewModel( decoration: const PageDecoration(bodyAlignment: Alignment.center), titleWidget: Padding( padding: const EdgeInsets.all(8), child: Text( AppLocalizations.of(context).setupWalletNameCurrency, textAlign: TextAlign.center, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), ), bodyWidget: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: MediaQuery.of(context).size.width * 0.7, child: PlatformField( labelText: AppLocalizations.of(context).setupNamePlaceholder, onChanged: (t) { name = t; }, ), ), const SizedBox( height: 5, ), PlatformButton( text: AppLocalizations.of(context) .setupCurrency(_selectedCurrency.code), onPressed: () { showCurrencyPicker( context: context, onSelect: (currency) { _selectedCurrency = currency; setState(() {}); }, ); }, ), const SizedBox( height: 5, ), SizedBox( width: MediaQuery.of(context).size.width * 0.7, child: PlatformField( labelText: AppLocalizations.of(context).setupStartingBalance, keyboardType: const TextInputType.numberWithOptions( decimal: true, ), inputFormatters: [ FilteringTextInputFormatter.allow( RegExp(r'\d+[\.,]{0,1}\d{0,}'), ), ], onChanged: (t) { balance = double.parse(t); }, ), ), ], ), ), PageViewModel( decoration: const PageDecoration(bodyAlignment: Alignment.center), titleWidget: Padding( padding: const EdgeInsets.all(8), child: Text( AppLocalizations.of(context).setupCategoriesHeading, textAlign: TextAlign.center, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), ), bodyWidget: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( AppLocalizations.of(context).setupCategoriesEditHint, textAlign: TextAlign.center, ), SizedBox( height: MediaQuery.of(context).size.height * 0.64, child: ListView.builder( shrinkWrap: true, itemBuilder: (context, i) => (i == 0) ? const SizedBox() : ListTile( leading: GestureDetector( onTap: () async { final icon = await FlutterIconPicker.showIconPicker( context, ); if (icon != null) categories[i].icon = icon; final materialEnabled = (await SharedPreferences.getInstance()) .getBool("useMaterialYou") ?? false; if (!mounted) return; await showDialog( context: context, builder: (c) => PlatformDialog( actions: [ PlatformButton( text: AppLocalizations.of(context) .done, onPressed: () { Navigator.of(c).pop(); }, ), ], title: AppLocalizations.of(context) .pickColor, content: Column( children: [ ColorPicker( pickersEnabled: { ColorPickerType.wheel: true, ColorPickerType.primary: false, ColorPickerType.custom: false, ColorPickerType.bw: false, ColorPickerType.accent: materialEnabled, }, color: categories[i].color, onColorChanged: (color) { categories[i].color = color; setState(() {}); }, ), ], ), ), ); setState(() {}); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), color: categories[i].color, ), child: Padding( padding: const EdgeInsets.all(8), child: Icon( categories[i].icon, color: categories[i] .color .calculateTextColor(), ), ), ), ), trailing: IconButton( icon: const Icon(Icons.cancel), onPressed: () { categories.removeAt(i); setState(() {}); }, ), title: GestureDetector( onTap: () { final controller = TextEditingController( text: categories[i].name, ); showDialog( context: context, builder: (c) => PlatformDialog( actions: [ TextButton( onPressed: () { if (controller.text.isEmpty) { return; } categories[i].name = controller.text; Navigator.of(context).pop(); }, child: Text( AppLocalizations.of(context).ok, ), ), TextButton( onPressed: () { Navigator.of(context).pop(); }, child: Text( AppLocalizations.of(context) .cancel, ), ), ], title: AppLocalizations.of(context) .setupCategoriesEditingName, content: SizedBox( width: 400, child: PlatformField( controller: controller, ), ), ), ); }, child: Text( categories[i].name, style: const TextStyle( fontWeight: FontWeight.bold, ), ), ), ), itemCount: categories.length, ), ), IconButton( onPressed: () { var id = 0; while (categories .where((element) => element.id == id) .isNotEmpty) { id++; // create unique ID } categories.add( WalletCategory( name: AppLocalizations.of(context) .setupWalletNamePlaceholder, id: id, icon: IconData( Icons.question_mark.codePoint, fontFamily: 'MaterialIcons', ), color: Colors.blueGrey.harmonizeWith( Theme.of(context).colorScheme.primary, ), ), ); setState(() {}); }, icon: const Icon(Icons.add), ), ], ), ), ], ), ), ), ); } }