From c7335a8dbb267fe6f7ee322899560b501d1c7c69 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 14 Oct 2020 22:48:11 +0300 Subject: [PATCH] Expenses --- lib/main_app.dart | 3 + lib/ui/app/main_screen.dart | 4 ++ lib/ui/settings/expense_settings.dart | 70 ++++++++++++++++++++++++ lib/ui/settings/expense_settings_vm.dart | 60 ++++++++++++++++++++ lib/ui/settings/settings_list.dart | 2 +- 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 lib/ui/settings/expense_settings.dart create mode 100644 lib/ui/settings/expense_settings_vm.dart diff --git a/lib/main_app.dart b/lib/main_app.dart index 60cef5706..314378a64 100644 --- a/lib/main_app.dart +++ b/lib/main_app.dart @@ -36,6 +36,7 @@ import 'package:invoiceninja_flutter/ui/payment_term/view/payment_term_view_vm.d import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart'; import 'package:invoiceninja_flutter/ui/reports/reports_screen_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/account_management_vm.dart'; +import 'package:invoiceninja_flutter/ui/settings/expense_settings_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/settings_screen_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/tax_settings_vm.dart'; import 'package:invoiceninja_flutter/ui/tax_rate/edit/tax_rate_edit_vm.dart'; @@ -335,6 +336,8 @@ class InvoiceNinjaAppState extends State { TaxRateEditScreen.route: (context) => TaxRateEditScreen(), ProductSettingsScreen.route: (context) => ProductSettingsScreen(), + ExpenseSettingsScreen.route: (context) => + ExpenseSettingsScreen(), IntegrationSettingsScreen.route: (context) => IntegrationSettingsScreen(), ImportExportScreen.route: (context) => ImportExportScreen(), diff --git a/lib/ui/app/main_screen.dart b/lib/ui/app/main_screen.dart index b27052cf3..f41c782bd 100644 --- a/lib/ui/app/main_screen.dart +++ b/lib/ui/app/main_screen.dart @@ -33,6 +33,7 @@ import 'package:invoiceninja_flutter/ui/recurring_invoice/view/recurring_invoice import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart'; import 'package:invoiceninja_flutter/ui/reports/reports_screen_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/account_management_vm.dart'; +import 'package:invoiceninja_flutter/ui/settings/expense_settings_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/settings_screen_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/tax_settings_vm.dart'; import 'package:invoiceninja_flutter/ui/token/edit/token_edit_vm.dart'; @@ -402,6 +403,9 @@ class SettingsScreens extends StatelessWidget { case kSettingsProducts: screen = ProductSettingsScreen(); break; + case kSettingsExpenses: + screen = ExpenseSettingsScreen(); + break; case kSettingsIntegrations: screen = IntegrationSettingsScreen(); break; diff --git a/lib/ui/settings/expense_settings.dart b/lib/ui/settings/expense_settings.dart new file mode 100644 index 000000000..204c33c7e --- /dev/null +++ b/lib/ui/settings/expense_settings.dart @@ -0,0 +1,70 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/ui/app/form_card.dart'; +import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart'; +import 'package:invoiceninja_flutter/ui/settings/expense_settings_vm.dart'; +import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart'; +import 'package:invoiceninja_flutter/utils/localization.dart'; + +class ExpenseSettings extends StatefulWidget { + const ExpenseSettings({ + Key key, + @required this.viewModel, + }) : super(key: key); + + final ExpenseSettingsVM viewModel; + + @override + _ExpenseSettingsState createState() => _ExpenseSettingsState(); +} + +class _ExpenseSettingsState extends State { + static final GlobalKey _formKey = + GlobalKey(debugLabel: '_expenseSettings'); + FocusScopeNode _focusNode; + + @override + void initState() { + super.initState(); + _focusNode = FocusScopeNode(); + } + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final localization = AppLocalization.of(context); + final viewModel = widget.viewModel; + final company = viewModel.company; + + return EditScaffold( + title: localization.expenseSettings, + onSavePressed: viewModel.onSavePressed, + body: AppForm( + formKey: _formKey, + focusNode: _focusNode, + children: [ + FormCard( + children: [ + /* + SwitchListTile( + activeColor: Theme.of(context).accentColor, + title: Text(localization.showCost), + value: company.enableExpenseCost ?? false, + subtitle: Text(localization.showCostHelp), + onChanged: (value) => viewModel.onCompanyChanged( + company.rebuild((b) => b..enableExpenseCost = value)), + ), + + */ + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/settings/expense_settings_vm.dart b/lib/ui/settings/expense_settings_vm.dart new file mode 100644 index 000000000..b154a001e --- /dev/null +++ b/lib/ui/settings/expense_settings_vm.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/constants.dart'; +import 'package:invoiceninja_flutter/data/models/company_model.dart'; +import 'package:invoiceninja_flutter/redux/company/company_actions.dart'; +import 'package:invoiceninja_flutter/ui/settings/expense_settings.dart'; +import 'package:invoiceninja_flutter/utils/completers.dart'; +import 'package:invoiceninja_flutter/utils/localization.dart'; +import 'package:redux/redux.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; + +class ExpenseSettingsScreen extends StatelessWidget { + const ExpenseSettingsScreen({Key key}) : super(key: key); + static const String route = '/$kSettings/$kSettingsExpenses'; + + @override + Widget build(BuildContext context) { + return StoreConnector( + converter: ExpenseSettingsVM.fromStore, + builder: (context, viewModel) { + return ExpenseSettings( + viewModel: viewModel, + key: ValueKey(viewModel.state.settingsUIState.updatedAt), + ); + }, + ); + } +} + +class ExpenseSettingsVM { + ExpenseSettingsVM({ + @required this.state, + @required this.company, + @required this.onCompanyChanged, + @required this.onSavePressed, + }); + + static ExpenseSettingsVM fromStore(Store store) { + final state = store.state; + + return ExpenseSettingsVM( + state: state, + company: state.uiState.settingsUIState.company, + onCompanyChanged: (company) => + store.dispatch(UpdateCompany(company: company)), + onSavePressed: (context) { + final settingsUIState = state.uiState.settingsUIState; + final completer = snackBarCompleter( + context, AppLocalization.of(context).savedSettings); + store.dispatch(SaveCompanyRequest( + completer: completer, company: settingsUIState.company)); + }); + } + + final AppState state; + final Function(BuildContext) onSavePressed; + final CompanyEntity company; + final Function(CompanyEntity) onCompanyChanged; +} diff --git a/lib/ui/settings/settings_list.dart b/lib/ui/settings/settings_list.dart index 2de43081e..e89b0a384 100644 --- a/lib/ui/settings/settings_list.dart +++ b/lib/ui/settings/settings_list.dart @@ -100,7 +100,7 @@ class SettingsList extends StatelessWidget { section: kSettingsProducts, viewModel: viewModel, ), - if (showAll) + if (showAll && state.company.isModuleEnabled(EntityType.expense)) SettingsListTile( section: kSettingsExpenses, viewModel: viewModel,