This commit is contained in:
Hillel Coren 2018-12-26 15:00:15 +02:00
parent c46da0b8f7
commit 8ea15b9c1d
3 changed files with 80 additions and 14 deletions

View File

@ -3,6 +3,22 @@ import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart'; import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
var memoizedTaskList = memo2(
(BuiltMap<int, TaskEntity> taskMap, int clientId) =>
taskList(taskMap, clientId));
List<int> taskList(BuiltMap<int, TaskEntity> taskMap, int clientId) {
final list = taskMap.keys.where((taskId) {
final task = taskMap[taskId];
return task.isActive && task.clientId == clientId;
}).toList();
list.sort((idA, idB) =>
taskMap[idA].listDisplayName.compareTo(taskMap[idB].listDisplayName));
return list;
}
var memoizedDropdownTaskList = memo2( var memoizedDropdownTaskList = memo2(
(BuiltMap<int, TaskEntity> taskMap, BuiltList<int> taskList) => (BuiltMap<int, TaskEntity> taskMap, BuiltList<int> taskList) =>
dropdownTasksSelector(taskMap, taskList)); dropdownTasksSelector(taskMap, taskList));
@ -78,16 +94,13 @@ double taskRateSelector({CompanyEntity company, ProjectEntity project}) {
} }
var memoizedTaskStatsForClient = memo4((int clientId, var memoizedTaskStatsForClient = memo4((int clientId,
BuiltMap<int, TaskEntity> taskMap, BuiltMap<int, TaskEntity> taskMap,
String activeLabel, String activeLabel,
String archivedLabel) => String archivedLabel) =>
taskStatsForClient(clientId, taskMap, activeLabel, archivedLabel)); taskStatsForClient(clientId, taskMap, activeLabel, archivedLabel));
String taskStatsForClient( String taskStatsForClient(int clientId, BuiltMap<int, TaskEntity> taskMap,
int clientId, String activeLabel, String archivedLabel) {
BuiltMap<int, TaskEntity> taskMap,
String activeLabel,
String archivedLabel) {
int countActive = 0; int countActive = 0;
int countArchived = 0; int countArchived = 0;
taskMap.forEach((taskId, task) { taskMap.forEach((taskId, task) {
@ -114,7 +127,6 @@ String taskStatsForClient(
return str; return str;
} }
var memoizedTaskStatsForProject = memo4((int projectId, var memoizedTaskStatsForProject = memo4((int projectId,
BuiltMap<int, TaskEntity> taskMap, BuiltMap<int, TaskEntity> taskMap,
String activeLabel, String activeLabel,

View File

@ -140,6 +140,7 @@ class _InvoiceEditState extends State<InvoiceEdit>
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return InvoiceItemSelector( return InvoiceItemSelector(
clientId: invoice.clientId,
onItemsSelected: (items) { onItemsSelected: (items) {
viewModel.onItemsAdded(items); viewModel.onItemsAdded(items);
_controller.animateTo(kItemScreen); _controller.animateTo(kItemScreen);

View File

@ -3,16 +3,19 @@ import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/product/product_selectors.dart'; import 'package:invoiceninja_flutter/redux/product/product_selectors.dart';
import 'package:invoiceninja_flutter/redux/task/task_selectors.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
class InvoiceItemSelector extends StatefulWidget { class InvoiceItemSelector extends StatefulWidget {
const InvoiceItemSelector({ const InvoiceItemSelector({
@required this.clientId,
this.onItemsSelected, this.onItemsSelected,
}); });
final Function(List<InvoiceItemEntity>) onItemsSelected; final Function(List<InvoiceItemEntity>) onItemsSelected;
final int clientId;
@override @override
_InvoiceItemSelectorState createState() => new _InvoiceItemSelectorState(); _InvoiceItemSelectorState createState() => new _InvoiceItemSelectorState();
@ -136,10 +139,10 @@ class _InvoiceItemSelectorState extends State<InvoiceItemSelector>
); );
} }
Widget _entityList(EntityType entityType) { Widget _productList() {
final state = StoreProvider.of<AppState>(context).state; final state = StoreProvider.of<AppState>(context).state;
final matches = final matches =
memoizedProductList(state.productState.map).where((entityId) { memoizedProductList(state.productState.map).where((entityId) {
final entity = state.productState.map[entityId]; final entity = state.productState.map[entityId];
return entity.isActive && entity.matchesFilter(_filter); return entity.isActive && entity.matchesFilter(_filter);
}).toList(); }).toList();
@ -168,7 +171,57 @@ class _InvoiceItemSelectorState extends State<InvoiceItemSelector>
), ),
entity.listDisplayAmount != null entity.listDisplayAmount != null
? Text(formatNumber(entity.listDisplayAmount, context, ? Text(formatNumber(entity.listDisplayAmount, context,
formatNumberType: entity.listDisplayAmountType)) formatNumberType: entity.listDisplayAmountType))
: Container(),
],
),
subtitle: subtitle != null ? Text(subtitle, maxLines: 2) : null,
onTap: () {
if (_selected.isNotEmpty) {
_toggleEntity(entity);
} else {
_selected.add(entity);
_onItemsSelected(context);
}
},
);
},
);
}
Widget _taskList() {
final state = StoreProvider.of<AppState>(context).state;
final matches =
memoizedTaskList(state.taskState.map, widget.clientId).where((entityId) {
final entity = state.taskState.map[entityId];
return entity.isActive && entity.matchesFilter(_filter);
}).toList();
//matches.sort((idA, idB) =>
//state.productState.map[idA].compareTo(state.productState.map[idB]));
return ListView.builder(
shrinkWrap: true,
itemCount: matches.length,
itemBuilder: (BuildContext context, int index) {
final int entityId = matches[index];
final entity = state.taskState.map[entityId];
final String subtitle = entity.matchesFilterValue(_filter);
return ListTile(
dense: true,
leading: Checkbox(
activeColor: Theme.of(context).accentColor,
value: _selected.contains(entityId),
onChanged: (bool value) => _toggleEntity(entity),
),
title: Row(
children: <Widget>[
Expanded(
child: Text(entity.listDisplayName),
),
entity.listDisplayAmount != null
? Text(formatNumber(entity.listDisplayAmount, context,
formatNumberType: entity.listDisplayAmountType))
: Container(), : Container(),
], ],
), ),
@ -212,8 +265,8 @@ class _InvoiceItemSelectorState extends State<InvoiceItemSelector>
child: TabBarView( child: TabBarView(
controller: _tabController, controller: _tabController,
children: <Widget>[ children: <Widget>[
_entityList(EntityType.product), _productList(),
_entityList(EntityType.task), _taskList(),
], ],
), ),
), ),