Starter...

This commit is contained in:
Hillel Coren 2020-03-02 20:23:22 +02:00
parent 8fcb3129ab
commit ea02d3082c
21 changed files with 252 additions and 306 deletions

View File

@ -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,

View File

@ -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';

View File

@ -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(),
);
},
),
),
),
],
);
}
}

View File

@ -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),
],
),

View File

@ -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;
}

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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(),
);
}
}