diff --git a/lib/redux/recurring_expense/recurring_expense_reducer.dart b/lib/redux/recurring_expense/recurring_expense_reducer.dart index da42f10db..7021373c7 100644 --- a/lib/redux/recurring_expense/recurring_expense_reducer.dart +++ b/lib/redux/recurring_expense/recurring_expense_reducer.dart @@ -277,8 +277,9 @@ RecurringExpenseState _addRecurringExpense( RecurringExpenseState _updateRecurringExpense( RecurringExpenseState recurringExpenseState, SaveRecurringExpenseSuccess action) { - return recurringExpenseState.rebuild( - (b) => b..map[action.recurringExpense.id] = action.recurringExpense); + return recurringExpenseState.rebuild((b) => b + ..map[action.recurringExpense.id] = action.recurringExpense + .rebuild((b) => b..loadedAt = DateTime.now().millisecondsSinceEpoch)); } RecurringExpenseState _startRecurringExpensesSuccess( diff --git a/lib/ui/expense/view/expense_view.dart b/lib/ui/expense/view/expense_view.dart index 2c0164d10..3ead1eae0 100644 --- a/lib/ui/expense/view/expense_view.dart +++ b/lib/ui/expense/view/expense_view.dart @@ -9,10 +9,12 @@ import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/bottom_buttons.dart'; import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart'; import 'package:invoiceninja_flutter/ui/expense/view/expense_view_documents.dart'; +import 'package:invoiceninja_flutter/ui/expense/view/expense_view_schedule.dart'; import 'package:invoiceninja_flutter/ui/expense/view/expense_view_vm.dart'; import 'package:invoiceninja_flutter/ui/expense/view/expense_view_overview.dart'; import 'package:invoiceninja_flutter/utils/files.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; +import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:permission_handler/permission_handler.dart'; class ExpenseView extends StatefulWidget { @@ -39,10 +41,11 @@ class _ExpenseViewState extends State void initState() { super.initState(); - final state = widget.viewModel.state; + final viewModel = widget.viewModel; + final state = viewModel.state; _controller = TabController( vsync: this, - length: 2, + length: viewModel.expense.isRecurring ? 3 : 2, initialIndex: widget.isFilter ? 0 : state.expenseUIState.tabIndex); _controller.addListener(_onTabChanged); } @@ -83,6 +86,7 @@ class _ExpenseViewState extends State entity: expense, appBarBottom: TabBar( controller: _controller, + isScrollable: isMobile(context), tabs: [ Tab( text: localization.overview, @@ -120,8 +124,7 @@ class _ExpenseViewState extends State if (expense.isRecurring) RefreshIndicator( onRefresh: () => viewModel.onRefreshed(context), - child: ExpenseViewDocuments( - viewModel: viewModel, expense: viewModel.expense), + child: ExpenseViewSchedule(viewModel: viewModel), ), ], ), diff --git a/lib/ui/expense/view/expense_view_schedule.dart b/lib/ui/expense/view/expense_view_schedule.dart new file mode 100644 index 000000000..ec2503ded --- /dev/null +++ b/lib/ui/expense/view/expense_view_schedule.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; +import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart'; +import 'package:invoiceninja_flutter/ui/expense/view/expense_view_vm.dart'; +import 'package:invoiceninja_flutter/utils/formatting.dart'; +import 'package:invoiceninja_flutter/utils/localization.dart'; + +class ExpenseViewSchedule extends StatefulWidget { + const ExpenseViewSchedule({Key key, @required this.viewModel}) + : super(key: key); + + final AbstractExpenseViewVM viewModel; + + @override + _ExpenseViewScheduleState createState() => _ExpenseViewScheduleState(); +} + +class _ExpenseViewScheduleState extends State { + @override + void didChangeDependencies() { + if (widget.viewModel.expense.isStale) { + widget.viewModel.onRefreshed(context); + } + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + final expense = widget.viewModel.expense; + final localization = AppLocalization.of(context); + + return ScrollableListView( + padding: const EdgeInsets.all(16), + children: [ + Row( + children: [ + Expanded( + child: Text( + localization.sendDate, + style: TextStyle(fontWeight: FontWeight.w600), + ), + ), + ], + ), + if (expense.isStale && expense.recurringDates.isEmpty) + LoadingIndicator( + height: 300, + ), + ...expense.recurringDates + .map((schedule) => Padding( + padding: const EdgeInsets.only(top: 16), + child: Row( + children: [ + Expanded( + child: Text(formatDate(schedule.sendDate, context)), + ), + ], + ), + )) + .toList(), + ], + ); + } +}