diff --git a/lib/redux/company/company_selectors.dart b/lib/redux/company/company_selectors.dart index 43dafe2ce..859fa6ddc 100644 --- a/lib/redux/company/company_selectors.dart +++ b/lib/redux/company/company_selectors.dart @@ -1,5 +1,31 @@ import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; +import 'package:invoiceninja_flutter/redux/company/company_state.dart'; + +List filteredSelector(String filter, CompanyState state) { + final List list = [] + ..addAll(state.productState.list + .map((productId) => state.productState.map[productId]) + .where((product) { + return product.matchesFilter(filter); + }).toList()) + ..addAll(state.clientState.list + .map((clientId) => state.clientState.map[clientId]) + .where((client) { + return client.matchesFilter(filter); + }).toList()) + ..addAll(state.invoiceState.list + .map((invoiceId) => state.invoiceState.map[invoiceId]) + .where((invoice) { + return invoice.matchesFilter(filter); + }).toList()); + + list.sort((BaseEntity entityA, BaseEntity entityB) { + return entityA.listDisplayName.compareTo(entityB.listDisplayName); + }); + + return list; +} List companiesSelector(AppState state) { final List list = []; @@ -21,4 +47,4 @@ List companiesSelector(AppState state) { } return list; -} \ No newline at end of file +} diff --git a/lib/redux/ui/ui_reducer.dart b/lib/redux/ui/ui_reducer.dart index 653f8e588..31dbbc06a 100644 --- a/lib/redux/ui/ui_reducer.dart +++ b/lib/redux/ui/ui_reducer.dart @@ -8,8 +8,8 @@ import 'package:invoiceninja_flutter/redux/invoice/invoice_reducer.dart'; import 'package:redux/redux.dart'; UIState uiReducer(UIState state, dynamic action) { - return state.rebuild((b) => b + ..filter = filterReducer(state.filter, action) ..selectedCompanyIndex = selectedCompanyIndexReducer(state.selectedCompanyIndex, action) ..currentRoute = currentRouteReducer(state.currentRoute, action) ..enableDarkMode = darkModeReducer(state.enableDarkMode, action) @@ -19,6 +19,14 @@ UIState uiReducer(UIState state, dynamic action) { ); } +Reducer filterReducer = combineReducers([ + TypedReducer(updateFilter), +]); + +String updateFilter(String filter, FilterCompany action) { + return action.filter; +} + Reducer darkModeReducer = combineReducers([ TypedReducer(updateDarkModeReducer), ]); diff --git a/lib/ui/app/list_filter_button.dart b/lib/ui/app/list_filter_button.dart index e4e4849c2..44a7b5cef 100644 --- a/lib/ui/app/list_filter_button.dart +++ b/lib/ui/app/list_filter_button.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; -import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; diff --git a/lib/ui/dashboard/dashboard_view.dart b/lib/ui/dashboard/dashboard_view.dart index 73b680991..da9baae3f 100644 --- a/lib/ui/dashboard/dashboard_view.dart +++ b/lib/ui/dashboard/dashboard_view.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/ui/app/app_drawer_vm.dart'; @@ -91,12 +93,39 @@ class CustomTabBarView extends StatelessWidget { @override Widget build(BuildContext context) { + if (viewModel.filter != null) { + return ListView.builder( + itemCount: viewModel.filteredList.length, + itemBuilder: (BuildContext context, index) { + final entity = viewModel.filteredList[index]; + final subtitle = entity.matchesFilterValue(viewModel.filter); + IconData icon; + switch (entity.entityType) { + case EntityType.client: + icon = FontAwesomeIcons.users; + break; + case EntityType.product: + icon = FontAwesomeIcons.cube; + break; + case EntityType.invoice: + icon = FontAwesomeIcons.filePdfO; + break; + } + return ListTile( + title: Text(entity.listDisplayName), + leading: Icon(icon), + trailing: Icon(Icons.navigate_next), + subtitle: subtitle != null ? Text(subtitle) : Container(), + ); + } + ); + } + return TabBarView( controller: controller, children: [ RefreshIndicator( onRefresh: () => viewModel.onRefreshed(context), - //child: DashboardOverview(viewModel: viewModel), child: DashboardPanels( viewModel: viewModel, ), diff --git a/lib/ui/dashboard/dashboard_vm.dart b/lib/ui/dashboard/dashboard_vm.dart index cf4091509..3687ce182 100644 --- a/lib/ui/dashboard/dashboard_vm.dart +++ b/lib/ui/dashboard/dashboard_vm.dart @@ -4,6 +4,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/data/models/entities.dart'; +import 'package:invoiceninja_flutter/redux/company/company_selectors.dart'; import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart'; import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart'; import 'package:invoiceninja_flutter/ui/dashboard/dashboard_view.dart'; @@ -32,11 +34,15 @@ class DashboardVM { final DashboardState dashboardState; final bool isLoading; final Function(BuildContext) onRefreshed; + final String filter; + final List filteredList; DashboardVM({ @required this.dashboardState, @required this.isLoading, @required this.onRefreshed, + @required this.filter, + @required this.filteredList, }); static DashboardVM fromStore(Store store) { @@ -51,10 +57,15 @@ class DashboardVM { }); } + final state = store.state; + final filter = state.uiState.filter; + return DashboardVM( - dashboardState: store.state.dashboardState, - isLoading: store.state.isLoading, + dashboardState: state.dashboardState, + isLoading: state.isLoading, onRefreshed: (context) => _handleRefresh(context), + filter: filter, + filteredList: filteredSelector(filter, state.selectedCompanyState), ); } }