Starter...
This commit is contained in:
parent
8fcb3129ab
commit
ea02d3082c
|
|
@ -103,6 +103,11 @@ const String kQuoteStatusDraft = '1';
|
|||
const String kQuoteStatusSent = '2';
|
||||
const String kQuoteStatusApproved = '4';
|
||||
|
||||
const String kCreditStatusDraft = '1';
|
||||
const String kCreditStatusSent = '2';
|
||||
const String kCreditStatusPartial = '3';
|
||||
const String kCreditStatusPaid = '4';
|
||||
|
||||
const String kGatewayTypeCreditCard = '1';
|
||||
const String kGatewayTypeBankTransfer = '2';
|
||||
const String kGatewayTypePayPal = '3';
|
||||
|
|
@ -267,6 +272,17 @@ class InvoiceStatusColors {
|
|||
};
|
||||
}
|
||||
|
||||
class CreditStatusColors {
|
||||
static const colors = {
|
||||
kCreditStatusDraft: Colors.grey,
|
||||
kCreditStatusSent: Colors.blue,
|
||||
//kInvoiceStatusViewed: Colors.orange,
|
||||
//kInvoiceStatusApproved: Colors.green,
|
||||
kCreditStatusPartial: Colors.deepPurple,
|
||||
kCreditStatusPaid: Colors.green,
|
||||
};
|
||||
}
|
||||
|
||||
class QuoteStatusColors {
|
||||
static const colors = {
|
||||
kQuoteStatusDraft: Colors.grey,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
|||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_selectors.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/client/client_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/client_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/client_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -1,138 +0,0 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:invoiceninja_flutter/ui/credit/credit_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/credit/credit_list_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/credit/credit_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/utils/icons.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
|
||||
class CreditList extends StatefulWidget {
|
||||
const CreditList({
|
||||
Key key,
|
||||
@required this.viewModel,
|
||||
}) : super(key: key);
|
||||
|
||||
final CreditListVM viewModel;
|
||||
|
||||
@override
|
||||
_CreditListState createState() => _CreditListState();
|
||||
}
|
||||
|
||||
class _CreditListState extends State<CreditList> {
|
||||
EntityDataTableSource dataTableSource;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final viewModel = widget.viewModel;
|
||||
|
||||
dataTableSource = EntityDataTableSource(
|
||||
context: context,
|
||||
entityType: EntityType.credit,
|
||||
editingId: viewModel.state.creditUIState.editing.id,
|
||||
tableColumns: viewModel.tableColumns,
|
||||
entityList: viewModel.creditList,
|
||||
entityMap: viewModel.creditMap,
|
||||
entityPresenter: CreditPresenter(),
|
||||
onTap: (BaseEntity credit) => viewModel.onCreditTap(context, credit));
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(CreditList oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
final viewModel = widget.viewModel;
|
||||
dataTableSource.editingId = viewModel.state.creditUIState.editing.id;
|
||||
dataTableSource.entityList = viewModel.creditList;
|
||||
dataTableSource.entityMap = viewModel.creditMap;
|
||||
|
||||
// ignore: invalid_use_of_visible_for_testing_member, invalid_use_of_protected_member
|
||||
dataTableSource.notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/*
|
||||
final localization = AppLocalization.of(context);
|
||||
final listState = viewModel.listState;
|
||||
final filteredClientId = listState.filterEntityId;
|
||||
final filteredClient =
|
||||
filteredClientId != null ? viewModel.clientMap[filteredClientId] : null;
|
||||
*/
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final viewModel = widget.viewModel;
|
||||
final listUIState = store.state.uiState.creditUIState.listUIState;
|
||||
final isInMultiselect = listUIState.isInMultiselect();
|
||||
final creditList = viewModel.creditList;
|
||||
|
||||
if (isNotMobile(context) &&
|
||||
creditList.isNotEmpty &&
|
||||
!state.uiState.isEditing &&
|
||||
!creditList.contains(state.creditUIState.selectedId)) {
|
||||
viewEntityById(
|
||||
context: context,
|
||||
entityType: EntityType.credit,
|
||||
entityId: creditList.first);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: !viewModel.isLoaded
|
||||
? LoadingIndicator()
|
||||
: RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: viewModel.creditList.isEmpty
|
||||
? HelpText(AppLocalization.of(context).noRecordsFound)
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.creditList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final creditId = viewModel.creditList[index];
|
||||
final credit = viewModel.creditMap[creditId];
|
||||
final userCompany = viewModel.userCompany;
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
userCompany: userCompany,
|
||||
entity: credit,
|
||||
context: context,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return CreditListItem(
|
||||
user: viewModel.userCompany.user,
|
||||
filter: viewModel.filter,
|
||||
credit: credit,
|
||||
onTap: () =>
|
||||
viewModel.onCreditTap(context, credit),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, credit, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/credit_model.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entity_state_label.dart';
|
||||
|
|
@ -7,6 +8,7 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/dismissible_entity.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
class CreditListItem extends StatelessWidget {
|
||||
const CreditListItem({
|
||||
|
|
@ -15,7 +17,9 @@ class CreditListItem extends StatelessWidget {
|
|||
@required this.onTap,
|
||||
@required this.onLongPress,
|
||||
@required this.credit,
|
||||
@required this.client,
|
||||
@required this.filter,
|
||||
@required this.hasDocuments,
|
||||
this.onCheckboxChanged,
|
||||
this.isChecked = false,
|
||||
});
|
||||
|
|
@ -25,34 +29,42 @@ class CreditListItem extends StatelessWidget {
|
|||
final GestureTapCallback onTap;
|
||||
final GestureTapCallback onLongPress;
|
||||
final InvoiceEntity credit;
|
||||
final ClientEntity client;
|
||||
final String filter;
|
||||
final bool hasDocuments;
|
||||
final Function(bool) onCheckboxChanged;
|
||||
final bool isChecked;
|
||||
|
||||
static final creditItemKey = (int id) => Key('__credit_item_${id}__');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final state = StoreProvider.of<AppState>(context).state;
|
||||
final uiState = state.uiState;
|
||||
final creditUIState = uiState.creditUIState;
|
||||
final listUIState = creditUIState.listUIState;
|
||||
final isInMultiselect = listUIState.isInMultiselect();
|
||||
final showCheckbox = onCheckboxChanged != null || isInMultiselect;
|
||||
|
||||
final localization = AppLocalization.of(context);
|
||||
final filterMatch = filter != null && filter.isNotEmpty
|
||||
? credit.matchesFilterValue(filter)
|
||||
? (credit.matchesFilterValue(filter) ??
|
||||
client.matchesFilterValue(filter))
|
||||
: null;
|
||||
final subtitle = filterMatch;
|
||||
|
||||
/*
|
||||
final creditStatusId = (credit.creditInvoiceId ?? '').isNotEmpty
|
||||
? kCreditStatusApproved
|
||||
: credit.statusId;
|
||||
*/
|
||||
// TODO handle if credit is lined to invoice
|
||||
final creditStatusId = credit.statusId;
|
||||
|
||||
return DismissibleEntity(
|
||||
userCompany: state.userCompany,
|
||||
entity: credit,
|
||||
isSelected: credit.id ==
|
||||
(uiState.isEditing
|
||||
? creditUIState.editing.id
|
||||
: creditUIState.selectedId),
|
||||
userCompany: state.userCompany,
|
||||
entity: credit,
|
||||
onEntityAction: onEntityAction,
|
||||
child: ListTile(
|
||||
onTap: isInMultiselect
|
||||
|
|
@ -61,14 +73,14 @@ class CreditListItem extends StatelessWidget {
|
|||
onLongPress: onLongPress,
|
||||
leading: showCheckbox
|
||||
? IgnorePointer(
|
||||
ignoring: listUIState.isInMultiselect(),
|
||||
child: Checkbox(
|
||||
value: isChecked,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
onChanged: (value) => onCheckboxChanged(value),
|
||||
activeColor: Theme.of(context).accentColor,
|
||||
),
|
||||
)
|
||||
ignoring: listUIState.isInMultiselect(),
|
||||
child: Checkbox(
|
||||
value: isChecked,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
onChanged: (value) => onCheckboxChanged(value),
|
||||
activeColor: Theme.of(context).accentColor,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
title: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
|
|
@ -76,11 +88,15 @@ class CreditListItem extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
credit.name,
|
||||
client.displayName,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
),
|
||||
Text(formatNumber(credit.listDisplayAmount, context),
|
||||
Text(
|
||||
formatNumber(
|
||||
credit.balance > 0 ? credit.balance : credit.amount,
|
||||
context,
|
||||
clientId: credit.clientId),
|
||||
style: Theme.of(context).textTheme.headline6),
|
||||
],
|
||||
),
|
||||
|
|
@ -88,13 +104,37 @@ class CreditListItem extends StatelessWidget {
|
|||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
subtitle != null && subtitle.isNotEmpty
|
||||
? Text(
|
||||
subtitle,
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: filterMatch == null
|
||||
? Text((credit.number +
|
||||
' • ' +
|
||||
formatDate(
|
||||
credit.dueDate.isNotEmpty
|
||||
? credit.dueDate
|
||||
: credit.date,
|
||||
context) +
|
||||
(hasDocuments ? ' 📎' : ''))
|
||||
.trim())
|
||||
: Text(
|
||||
filterMatch,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
: Container(),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
credit.isPastDue
|
||||
? localization.pastDue
|
||||
: localization
|
||||
.lookup('credit_status_$creditStatusId'),
|
||||
style: TextStyle(
|
||||
color: credit.isPastDue
|
||||
? Colors.red
|
||||
: CreditStatusColors.colors[creditStatusId],
|
||||
)),
|
||||
],
|
||||
),
|
||||
EntityStateLabel(credit),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,55 +1,75 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja_flutter/data/models/credit_model.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/credit/credit_selectors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/credit/credit_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/redux/credit/credit_selectors.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/ui/credit/credit_list.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart';
|
||||
|
||||
class CreditListBuilder extends StatelessWidget {
|
||||
const CreditListBuilder({Key key}) : super(key: key);
|
||||
|
||||
static const String route = '/credit/edit';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, CreditListVM>(
|
||||
converter: CreditListVM.fromStore,
|
||||
builder: (context, viewModel) {
|
||||
return CreditList(
|
||||
viewModel: viewModel,
|
||||
builder: (context, vm) {
|
||||
return InvoiceList(
|
||||
viewModel: vm,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CreditListVM {
|
||||
class CreditListVM extends EntityListVM {
|
||||
CreditListVM({
|
||||
@required this.state,
|
||||
@required this.userCompany,
|
||||
@required this.creditList,
|
||||
@required this.creditMap,
|
||||
@required this.filter,
|
||||
@required this.isLoading,
|
||||
@required this.isLoaded,
|
||||
@required this.onCreditTap,
|
||||
@required this.listState,
|
||||
@required this.onRefreshed,
|
||||
@required this.onEntityAction,
|
||||
@required this.tableColumns,
|
||||
@required this.onClearEntityFilterPressed,
|
||||
@required this.onViewEntityFilterPressed,
|
||||
});
|
||||
AppState state,
|
||||
UserEntity user,
|
||||
ListUIState listState,
|
||||
List<String> invoiceList,
|
||||
BuiltMap<String, InvoiceEntity> invoiceMap,
|
||||
BuiltMap<String, ClientEntity> clientMap,
|
||||
String filter,
|
||||
bool isLoading,
|
||||
bool isLoaded,
|
||||
Function(BuildContext, InvoiceEntity) onInvoiceTap,
|
||||
Function(BuildContext) onRefreshed,
|
||||
Function onClearEntityFilterPressed,
|
||||
Function(BuildContext) onViewEntityFilterPressed,
|
||||
Function(BuildContext, List<InvoiceEntity>, EntityAction) onEntityAction,
|
||||
List<String> tableColumns,
|
||||
EntityType entityType,
|
||||
}) : super(
|
||||
state: state,
|
||||
user: user,
|
||||
listState: listState,
|
||||
invoiceList: invoiceList,
|
||||
invoiceMap: invoiceMap,
|
||||
clientMap: clientMap,
|
||||
filter: filter,
|
||||
isLoading: isLoading,
|
||||
isLoaded: isLoaded,
|
||||
onInvoiceTap: onInvoiceTap,
|
||||
onRefreshed: onRefreshed,
|
||||
onClearEntityFilterPressed: onClearEntityFilterPressed,
|
||||
onViewEntityFilterPressed: onViewEntityFilterPressed,
|
||||
tableColumns: tableColumns,
|
||||
entityType: entityType,
|
||||
);
|
||||
|
||||
static CreditListVM fromStore(Store<AppState> store) {
|
||||
Future<Null> _handleRefresh(BuildContext context) {
|
||||
|
|
@ -66,45 +86,29 @@ class CreditListVM {
|
|||
|
||||
return CreditListVM(
|
||||
state: state,
|
||||
userCompany: state.userCompany,
|
||||
user: state.user,
|
||||
listState: state.creditListState,
|
||||
creditList: memoizedFilteredCreditList(state.creditState.map,
|
||||
invoiceList: memoizedFilteredCreditList(state.creditState.map,
|
||||
state.creditState.list, state.clientState.map, state.creditListState),
|
||||
creditMap: state.creditState.map,
|
||||
invoiceMap: state.creditState.map,
|
||||
clientMap: state.clientState.map,
|
||||
isLoading: state.isLoading,
|
||||
isLoaded: state.creditState.isLoaded,
|
||||
filter: state.creditUIState.listUIState.filter,
|
||||
isLoaded: state.creditState.isLoaded && state.clientState.isLoaded,
|
||||
filter: state.creditListState.filter,
|
||||
onInvoiceTap: (context, credit) {
|
||||
viewEntity(context: context, entity: credit);
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onClearEntityFilterPressed: () => store.dispatch(FilterCreditsByEntity()),
|
||||
onViewEntityFilterPressed: (BuildContext context) => viewEntityById(
|
||||
context: context,
|
||||
entityId: state.creditListState.filterEntityId,
|
||||
entityType: state.creditListState.filterEntityType),
|
||||
onCreditTap: (context, credit) {
|
||||
if (store.state.creditListState.isInMultiselect()) {
|
||||
handleCreditAction(context, [credit], EntityAction.toggleMultiselect);
|
||||
} else {
|
||||
viewEntity(context: context, entity: credit);
|
||||
}
|
||||
},
|
||||
onEntityAction: (BuildContext context, List<BaseEntity> credits,
|
||||
EntityAction action) =>
|
||||
EntityAction action) =>
|
||||
handleCreditAction(context, credits, action),
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
tableColumns: CreditPresenter.getTableFields(state.userCompany),
|
||||
entityType: EntityType.credit,
|
||||
);
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
final UserCompanyEntity userCompany;
|
||||
final List<String> creditList;
|
||||
final BuiltMap<String, InvoiceEntity> creditMap;
|
||||
final ListUIState listState;
|
||||
final String filter;
|
||||
final bool isLoading;
|
||||
final bool isLoaded;
|
||||
final Function(BuildContext, InvoiceEntity) onCreditTap;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
final Function(BuildContext, List<BaseEntity>, EntityAction) onEntityAction;
|
||||
final Function onClearEntityFilterPressed;
|
||||
final Function(BuildContext) onViewEntityFilterPressed;
|
||||
final List<String> tableColumns;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/expense/expense_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/expense_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/expense_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/expense_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/expense/expense_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/expense/expense_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/expense_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/expense_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/invoice/invoice_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/invoice/invoice_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/payment/payment_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment/payment_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment/payment_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment/payment_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/payment/payment_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment/payment_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment/payment_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/product/product_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/product_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/product_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/product_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
|||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/product/product_selectors.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/product/product_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/product_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/product/product_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/project/project_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/project/project_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/project/project_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/project/project_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/project/project_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/project/project_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/project/project_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/project/project_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/quote/quote_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/quote/quote_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/task/task_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/task/task_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/task/task_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/task/task_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/task/task_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/task/task_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/task/task_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/task/task_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/vendor/vendor_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/vendor/vendor_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/vendor/vendor_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/vendor/vendor_list_vm.dart';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_selectors.dart';
|
||||
import 'file:///C:/Users/hillel/Documents/flutter-mobile/lib/ui/vendor/vendor_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/vendor/vendor_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/vendor/vendor_list.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/stub/stub_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/stub/stub_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/stub/stub_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/stub/stub_list_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/stub/stub_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/utils/icons.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
|
||||
class StubList extends StatefulWidget {
|
||||
const StubList({
|
||||
|
|
@ -31,7 +30,6 @@ class StubList extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _StubListState extends State<StubList> {
|
||||
|
||||
EntityDataTableSource dataTableSource;
|
||||
|
||||
@override
|
||||
|
|
@ -48,8 +46,7 @@ class _StubListState extends State<StubList> {
|
|||
entityList: viewModel.stubList,
|
||||
entityMap: viewModel.stubMap,
|
||||
entityPresenter: StubPresenter(),
|
||||
onTap: (BaseEntity stub) =>
|
||||
viewModel.onStubTap(context, stub));
|
||||
onTap: (BaseEntity stub) => viewModel.onStubTap(context, stub));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -65,79 +62,106 @@ class _StubListState extends State<StubList> {
|
|||
dataTableSource.notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/*
|
||||
final localization = AppLocalization.of(context);
|
||||
final listState = viewModel.listState;
|
||||
final filteredClientId = listState.filterEntityId;
|
||||
final filteredClient =
|
||||
filteredClientId != null ? viewModel.clientMap[filteredClientId] : null;
|
||||
*/
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final viewModel = widget.viewModel;
|
||||
final listUIState = store.state.uiState.stubUIState.listUIState;
|
||||
final state = viewModel.state;
|
||||
final listUIState = state.uiState.stubUIState.listUIState;
|
||||
final isInMultiselect = listUIState.isInMultiselect();
|
||||
final isList = state.prefState.moduleLayout == ModuleLayout.list;
|
||||
final stubList = viewModel.stubList;
|
||||
|
||||
if (isNotMobile(context) &&
|
||||
stubList.isNotEmpty &&
|
||||
!state.uiState.isEditing &&
|
||||
!stubList.contains(state.stubUIState.selectedId)) {
|
||||
viewEntityById(
|
||||
context: context,
|
||||
entityType: EntityType.stub,
|
||||
entityId: stubList.first);
|
||||
if (!viewModel.isLoaded) {
|
||||
return viewModel.isLoading ? LoadingIndicator() : SizedBox();
|
||||
} else if (viewModel.stubMap.isEmpty) {
|
||||
return HelpText(AppLocalization.of(context).noRecordsFound);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
|
||||
Expanded(
|
||||
child: !viewModel.isLoaded
|
||||
? LoadingIndicator()
|
||||
: RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: viewModel.stubList.isEmpty
|
||||
? HelpText(AppLocalization.of(context).noRecordsFound)
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.stubList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final stubId = viewModel.stubList[index];
|
||||
final stub = viewModel.stubMap[stubId];
|
||||
final userCompany = viewModel.userCompany;
|
||||
if (state.shouldSelectEntity(
|
||||
entityType: EntityType.stub, hasRecords: stubList.isNotEmpty)) {
|
||||
viewEntityById(
|
||||
context: context,
|
||||
entityType: EntityType.stub,
|
||||
entityId: stubList.isEmpty ? null : stubList.first,
|
||||
);
|
||||
}
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
userCompany: userCompany,
|
||||
entity: stub,
|
||||
context: context,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
final listOrTable = () {
|
||||
if (isList) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.stubList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final stubId = viewModel.stubList[index];
|
||||
final stub = viewModel.stubMap[stubId];
|
||||
|
||||
return StubListItem(
|
||||
user: viewModel.userCompany.user,
|
||||
filter: viewModel.filter,
|
||||
stub: stub,
|
||||
onTap: () =>
|
||||
viewModel.onStubTap(context, stub),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, stub, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () =>
|
||||
showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
return StubListItem(
|
||||
user: viewModel.state.user,
|
||||
filter: viewModel.filter,
|
||||
stub: stub,
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
showEntityActionsDialog(
|
||||
entities: [stub],
|
||||
context: context,
|
||||
);
|
||||
} else {
|
||||
handleStubAction(context, [stub], action);
|
||||
}
|
||||
},
|
||||
onTap: () => viewModel.onStubTap(context, stub),
|
||||
onLongPress: () async {
|
||||
final longPressIsSelection =
|
||||
state.prefState.longPressSelectionIsDefault ?? true;
|
||||
if (longPressIsSelection && !isInMultiselect) {
|
||||
handleStubAction(
|
||||
context, [stub], EntityAction.toggleMultiselect);
|
||||
} else {
|
||||
showEntityActionsDialog(
|
||||
entities: [stub],
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
},
|
||||
isChecked: isInMultiselect && listUIState.isSelected(stub.id),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: PaginatedDataTable(
|
||||
onSelectAll: (value) {
|
||||
final stubs = viewModel.stubList
|
||||
.map<StubEntity>(
|
||||
(stubId) => viewModel.stubMap[stubId])
|
||||
.where((stub) => value != listUIState.isSelected(stub.id))
|
||||
.toList();
|
||||
handleStubAction(
|
||||
context, stubs, EntityAction.toggleMultiselect);
|
||||
},
|
||||
columns: [
|
||||
if (!listUIState.isInMultiselect()) DataColumn(label: SizedBox()),
|
||||
...viewModel.tableColumns.map((field) => DataColumn(
|
||||
label: Text(AppLocalization.of(context).lookup(field)),
|
||||
numeric: EntityPresenter.isFieldNumeric(field),
|
||||
onSort: (int columnIndex, bool ascending) =>
|
||||
store.dispatch(SortStubs(field)))),
|
||||
],
|
||||
source: dataTableSource,
|
||||
header: DatatableHeader(
|
||||
entityType: EntityType.stub,
|
||||
onClearPressed: viewModel.onClearEntityFilterPressed,
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: listOrTable(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue