Sorting..
This commit is contained in:
parent
ef98ff9a4a
commit
ecc68040f1
|
|
@ -23,12 +23,12 @@ abstract class ProductItemResponse implements Built<ProductItemResponse, Product
|
|||
}
|
||||
|
||||
class ProductFields {
|
||||
static String productKey = 'productKey';
|
||||
static String notes = 'notes';
|
||||
static String cost = 'cost';
|
||||
static String updatedAt = 'updatedAt';
|
||||
static String archivedAt = 'archivedAt';
|
||||
static String isDeleted = 'isDeleted';
|
||||
static const String productKey = 'productKey';
|
||||
static const String notes = 'notes';
|
||||
static const String cost = 'cost';
|
||||
static const String updatedAt = 'updatedAt';
|
||||
static const String archivedAt = 'archivedAt';
|
||||
static const String isDeleted = 'isDeleted';
|
||||
}
|
||||
|
||||
abstract class ProductEntity implements Built<ProductEntity, ProductEntityBuilder> {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ class WebClient {
|
|||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
print('== pOST ==');
|
||||
print(data);
|
||||
try {
|
||||
final jsonResponse = json.decode(response.body);
|
||||
return jsonResponse;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class InvoiceNinjaApp extends StatelessWidget {
|
|||
..addAll(createStoreDashboardMiddleware())
|
||||
..addAll(createStoreProductsMiddleware())
|
||||
..addAll([
|
||||
LoggingMiddleware.printer(),
|
||||
//LoggingMiddleware.printer(),
|
||||
])
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,23 @@
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:built_value/serializer.dart';
|
||||
import 'package:invoiceninja/ui/app/action_popup_menu.dart';
|
||||
|
||||
part 'entity_ui_state.g.dart';
|
||||
|
||||
abstract class EntityUIState implements Built<EntityUIState, EntityUIStateBuilder> {
|
||||
|
||||
String get sortField;
|
||||
bool get sortAscending;
|
||||
BuiltList<int> get stateFilterIds;
|
||||
BuiltList<int> get statusFilterIds;
|
||||
|
||||
factory EntityUIState(sortField) {
|
||||
return _$EntityUIState._(
|
||||
sortField: sortField,
|
||||
sortAscending: true,
|
||||
stateFilterIds: BuiltList<int>(),
|
||||
statusFilterIds: BuiltList<int>(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,17 @@ class _$EntityUIStateSerializer implements StructuredSerializer<EntityUIState> {
|
|||
'sortField',
|
||||
serializers.serialize(object.sortField,
|
||||
specifiedType: const FullType(String)),
|
||||
'sortAscending',
|
||||
serializers.serialize(object.sortAscending,
|
||||
specifiedType: const FullType(bool)),
|
||||
'stateFilterIds',
|
||||
serializers.serialize(object.stateFilterIds,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(int)])),
|
||||
'statusFilterIds',
|
||||
serializers.serialize(object.statusFilterIds,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(int)])),
|
||||
];
|
||||
|
||||
return result;
|
||||
|
|
@ -50,6 +61,22 @@ class _$EntityUIStateSerializer implements StructuredSerializer<EntityUIState> {
|
|||
result.sortField = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'sortAscending':
|
||||
result.sortAscending = serializers.deserialize(value,
|
||||
specifiedType: const FullType(bool)) as bool;
|
||||
break;
|
||||
case 'stateFilterIds':
|
||||
result.stateFilterIds.replace(serializers.deserialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(int)]))
|
||||
as BuiltList);
|
||||
break;
|
||||
case 'statusFilterIds':
|
||||
result.statusFilterIds.replace(serializers.deserialize(value,
|
||||
specifiedType:
|
||||
const FullType(BuiltList, const [const FullType(int)]))
|
||||
as BuiltList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,13 +87,30 @@ class _$EntityUIStateSerializer implements StructuredSerializer<EntityUIState> {
|
|||
class _$EntityUIState extends EntityUIState {
|
||||
@override
|
||||
final String sortField;
|
||||
@override
|
||||
final bool sortAscending;
|
||||
@override
|
||||
final BuiltList<int> stateFilterIds;
|
||||
@override
|
||||
final BuiltList<int> statusFilterIds;
|
||||
|
||||
factory _$EntityUIState([void updates(EntityUIStateBuilder b)]) =>
|
||||
(new EntityUIStateBuilder()..update(updates)).build();
|
||||
|
||||
_$EntityUIState._({this.sortField}) : super._() {
|
||||
_$EntityUIState._(
|
||||
{this.sortField,
|
||||
this.sortAscending,
|
||||
this.stateFilterIds,
|
||||
this.statusFilterIds})
|
||||
: super._() {
|
||||
if (sortField == null)
|
||||
throw new BuiltValueNullFieldError('EntityUIState', 'sortField');
|
||||
if (sortAscending == null)
|
||||
throw new BuiltValueNullFieldError('EntityUIState', 'sortAscending');
|
||||
if (stateFilterIds == null)
|
||||
throw new BuiltValueNullFieldError('EntityUIState', 'stateFilterIds');
|
||||
if (statusFilterIds == null)
|
||||
throw new BuiltValueNullFieldError('EntityUIState', 'statusFilterIds');
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -80,18 +124,27 @@ class _$EntityUIState extends EntityUIState {
|
|||
bool operator ==(dynamic other) {
|
||||
if (identical(other, this)) return true;
|
||||
if (other is! EntityUIState) return false;
|
||||
return sortField == other.sortField;
|
||||
return sortField == other.sortField &&
|
||||
sortAscending == other.sortAscending &&
|
||||
stateFilterIds == other.stateFilterIds &&
|
||||
statusFilterIds == other.statusFilterIds;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return $jf($jc(0, sortField.hashCode));
|
||||
return $jf($jc(
|
||||
$jc($jc($jc(0, sortField.hashCode), sortAscending.hashCode),
|
||||
stateFilterIds.hashCode),
|
||||
statusFilterIds.hashCode));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (newBuiltValueToStringHelper('EntityUIState')
|
||||
..add('sortField', sortField))
|
||||
..add('sortField', sortField)
|
||||
..add('sortAscending', sortAscending)
|
||||
..add('stateFilterIds', stateFilterIds)
|
||||
..add('statusFilterIds', statusFilterIds))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -104,11 +157,31 @@ class EntityUIStateBuilder
|
|||
String get sortField => _$this._sortField;
|
||||
set sortField(String sortField) => _$this._sortField = sortField;
|
||||
|
||||
bool _sortAscending;
|
||||
bool get sortAscending => _$this._sortAscending;
|
||||
set sortAscending(bool sortAscending) =>
|
||||
_$this._sortAscending = sortAscending;
|
||||
|
||||
ListBuilder<int> _stateFilterIds;
|
||||
ListBuilder<int> get stateFilterIds =>
|
||||
_$this._stateFilterIds ??= new ListBuilder<int>();
|
||||
set stateFilterIds(ListBuilder<int> stateFilterIds) =>
|
||||
_$this._stateFilterIds = stateFilterIds;
|
||||
|
||||
ListBuilder<int> _statusFilterIds;
|
||||
ListBuilder<int> get statusFilterIds =>
|
||||
_$this._statusFilterIds ??= new ListBuilder<int>();
|
||||
set statusFilterIds(ListBuilder<int> statusFilterIds) =>
|
||||
_$this._statusFilterIds = statusFilterIds;
|
||||
|
||||
EntityUIStateBuilder();
|
||||
|
||||
EntityUIStateBuilder get _$this {
|
||||
if (_$v != null) {
|
||||
_sortField = _$v.sortField;
|
||||
_sortAscending = _$v.sortAscending;
|
||||
_stateFilterIds = _$v.stateFilterIds?.toBuilder();
|
||||
_statusFilterIds = _$v.statusFilterIds?.toBuilder();
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
|
|
@ -127,7 +200,27 @@ class EntityUIStateBuilder
|
|||
|
||||
@override
|
||||
_$EntityUIState build() {
|
||||
final _$result = _$v ?? new _$EntityUIState._(sortField: sortField);
|
||||
_$EntityUIState _$result;
|
||||
try {
|
||||
_$result = _$v ??
|
||||
new _$EntityUIState._(
|
||||
sortField: sortField,
|
||||
sortAscending: sortAscending,
|
||||
stateFilterIds: stateFilterIds.build(),
|
||||
statusFilterIds: statusFilterIds.build());
|
||||
} catch (_) {
|
||||
String _$failedField;
|
||||
try {
|
||||
_$failedField = 'stateFilterIds';
|
||||
stateFilterIds.build();
|
||||
_$failedField = 'statusFilterIds';
|
||||
statusFilterIds.build();
|
||||
} catch (e) {
|
||||
throw new BuiltValueNestedFieldError(
|
||||
'EntityUIState', _$failedField, e.toString());
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,4 +85,4 @@ class SaveProductFailure {
|
|||
class SortProducts {
|
||||
final String field;
|
||||
SortProducts(this.field);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:invoiceninja/redux/app/entity_ui_state.dart';
|
||||
import 'package:invoiceninja/ui/app/action_popup_menu.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja/redux/product/product_actions.dart';
|
||||
import 'package:invoiceninja/redux/product/product_state.dart';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja/data/models/models.dart';
|
||||
import 'package:invoiceninja/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja/redux/app/entity_ui_state.dart';
|
||||
import 'package:invoiceninja/redux/product/product_state.dart';
|
||||
|
||||
bool isLoadingSelector(AppState state) => state.isLoading;
|
||||
|
||||
|
|
@ -10,21 +13,26 @@ List<ProductEntity> productsSelector(AppState state) =>
|
|||
state.productState().list.map((id) => state.productState().map[id]);
|
||||
|
||||
List<ProductEntity> filteredProductsSelector(
|
||||
List<ProductEntity> products,
|
||||
//VisibilityFilter activeFilter,
|
||||
) {
|
||||
return products.where((product) {
|
||||
return true;
|
||||
/*
|
||||
if (activeFilter == VisibilityFilter.all) {
|
||||
return true;
|
||||
} else if (activeFilter == VisibilityFilter.active) {
|
||||
return !product.complete;
|
||||
} else if (activeFilter == VisibilityFilter.completed) {
|
||||
return product.complete;
|
||||
ProductState productState,
|
||||
EntityUIState productUIState) {
|
||||
|
||||
var list = productState.list.toList();
|
||||
|
||||
list.sort((productAId, productBId) {
|
||||
var productA = productState.map[productAId];
|
||||
var productB = productState.map[productBId];
|
||||
var sortField = productUIState.sortField;
|
||||
|
||||
switch (sortField) {
|
||||
case ProductFields.productKey:
|
||||
return productA.productKey.compareTo(productB.productKey);
|
||||
case ProductFields.cost:
|
||||
return productA.cost.compareTo(productB.cost);
|
||||
}
|
||||
*/
|
||||
}).toList();
|
||||
});
|
||||
|
||||
print('== SORTING LIST');
|
||||
return list.map((id) => productState.map[id]).toList();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6,12 +6,6 @@ enum ActionMenuButtonType {
|
|||
sort,
|
||||
}
|
||||
|
||||
class SortField {
|
||||
final String field;
|
||||
final String label;
|
||||
SortField(this.field, this.label);
|
||||
}
|
||||
|
||||
class ActionMenuChoice {
|
||||
const ActionMenuChoice(this.action, {this.label, this.icon});
|
||||
final String label;
|
||||
|
|
@ -24,8 +18,8 @@ class ActionMenuButton extends StatelessWidget {
|
|||
final List<ActionMenuChoice> actions;
|
||||
final Function onSelected;
|
||||
|
||||
final List<SortField> sortFields;
|
||||
final Function(String) onSelectedSort;
|
||||
final List<String> sortFields;
|
||||
final Function(String, Function) onSelectedSort;
|
||||
final String selectedSort;
|
||||
|
||||
ActionMenuButton({
|
||||
|
|
@ -38,30 +32,52 @@ class ActionMenuButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_showSortScreen() {
|
||||
print('=== BUILD ===');
|
||||
|
||||
showSortScreen() {
|
||||
scaffoldKey.currentState.showBottomSheet((context) {
|
||||
return Container(
|
||||
color: Colors.grey[200],
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: sortFields.map((sortField) {
|
||||
print('field: ' + sortField.field );
|
||||
print('match: ' + (sortField.field == selectedSort ? 'yes' : 'no'));
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
title: Text(sortField.label),
|
||||
title: Text(AppLocalization.of((context)).lookup(sortField)),
|
||||
groupValue: selectedSort,
|
||||
onChanged: (value) {
|
||||
print('value changed: ' + value);
|
||||
this.onSelectedSort(value);
|
||||
this.onSelectedSort(value, showSortScreen);
|
||||
},
|
||||
value: sortField.field,
|
||||
value: sortField,
|
||||
);
|
||||
}).toList()),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
showFIlterScree() {
|
||||
scaffoldKey.currentState.showBottomSheet((context) {
|
||||
bool _active = false;
|
||||
|
||||
return Container(
|
||||
color: Colors.grey[200],
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CheckboxListTile(
|
||||
value: true,
|
||||
title: Text('Active'),
|
||||
selected: _active,
|
||||
onChanged: (checked) {
|
||||
_active = ! checked;
|
||||
},
|
||||
),
|
||||
]
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return PopupMenuButton<ActionMenuChoice>(
|
||||
itemBuilder: (BuildContext context) {
|
||||
return actions.map((ActionMenuChoice choice) {
|
||||
|
|
@ -91,9 +107,10 @@ class ActionMenuButton extends StatelessWidget {
|
|||
onSelected: (ActionMenuChoice choice) {
|
||||
switch (choice.action) {
|
||||
case ActionMenuButtonType.sort:
|
||||
_showSortScreen();
|
||||
showSortScreen();
|
||||
break;
|
||||
case ActionMenuButtonType.filter:
|
||||
showFIlterScree();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja/utils/localization.dart';
|
||||
|
||||
/*
|
||||
enum BottomBarButtonType {
|
||||
filter,
|
||||
sort,
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
class _AppBottomBarChoice {
|
||||
const _AppBottomBarChoice (this.type, {this.label, this.icon});
|
||||
final String label;
|
||||
final IconData icon;
|
||||
final BottomBarButtonType type;
|
||||
}
|
||||
*/
|
||||
|
||||
class AppBottomBar extends StatelessWidget {
|
||||
final GlobalKey<ScaffoldState> scaffoldKey;
|
||||
//final List<ActionMenuChoice> actions;
|
||||
|
||||
final List<String> sortFields;
|
||||
final Function(String) onSelectedSort;
|
||||
final String selectedSort;
|
||||
|
||||
AppBottomBar(
|
||||
{
|
||||
//this.actions,
|
||||
//this.onSelected,
|
||||
this.scaffoldKey,
|
||||
this.sortFields,
|
||||
this.onSelectedSort,
|
||||
this.selectedSort});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new BottomAppBar(
|
||||
hasNotch: true,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
tooltip: AppLocalization.of((context)).sort,
|
||||
icon: Icon(Icons.sort_by_alpha),
|
||||
onPressed: () {
|
||||
scaffoldKey.currentState.showBottomSheet((context) {
|
||||
return Container(
|
||||
color: Colors.grey[200],
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: sortFields.map((sortField) {
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
title: Text(
|
||||
AppLocalization.of((context)).lookup(sortField)),
|
||||
groupValue: selectedSort,
|
||||
onChanged: (value) {
|
||||
this.onSelectedSort(value);
|
||||
},
|
||||
value: sortField,
|
||||
);
|
||||
}).toList()),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
tooltip: AppLocalization.of((context)).filter,
|
||||
icon: Icon(Icons.filter_list),
|
||||
onPressed: () {},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,9 +24,9 @@ class ProductList extends StatelessWidget {
|
|||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ListView.builder(
|
||||
key: NinjaKeys.productList,
|
||||
itemCount: viewModel.productState.list.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final product = viewModel.productState.map[viewModel.productState.list[index]];
|
||||
itemCount: viewModel.products.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
var product = viewModel.products[index];
|
||||
return Column(children: <Widget>[
|
||||
ProductItem(
|
||||
product: product,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja/redux/product/product_selectors.dart';
|
||||
import 'package:invoiceninja/ui/app/snackbar_row.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -30,14 +31,14 @@ class ProductListBuilder extends StatelessWidget {
|
|||
}
|
||||
|
||||
class ProductListVM {
|
||||
final ProductState productState;
|
||||
final List<ProductEntity> products;
|
||||
final bool isLoading;
|
||||
final Function(BuildContext, ProductEntity) onProductTap;
|
||||
final Function(BuildContext, ProductEntity, DismissDirection) onDismissed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
|
||||
ProductListVM({
|
||||
@required this.productState,
|
||||
@required this.products,
|
||||
@required this.isLoading,
|
||||
@required this.onProductTap,
|
||||
@required this.onDismissed,
|
||||
|
|
@ -58,13 +59,7 @@ class ProductListVM {
|
|||
}
|
||||
|
||||
return ProductListVM(
|
||||
productState: store.state.productState(),
|
||||
/*
|
||||
products: filteredProductsSelector(
|
||||
productsSelector(store.state),
|
||||
//activeFilterSelector(store.state),
|
||||
),
|
||||
*/
|
||||
products: filteredProductsSelector(store.state.productState(), store.state.productUIState()),
|
||||
isLoading: store.state.productState().lastUpdated == 0,
|
||||
onProductTap: (context, product) {
|
||||
store.dispatch(SelectProductAction(product));
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@ import 'package:flutter_redux/flutter_redux.dart';
|
|||
import 'package:invoiceninja/redux/product/product_actions.dart';
|
||||
import 'package:invoiceninja/ui/app/app_drawer_vm.dart';
|
||||
import 'package:invoiceninja/ui/app/action_popup_menu.dart';
|
||||
import 'package:invoiceninja/ui/app/app_bottom_bar.dart';
|
||||
|
||||
class ProductScreen extends StatelessWidget {
|
||||
ProductScreen() : super(key: NinjaKeys.productHome);
|
||||
|
||||
final _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
//static ActionMenuButtonType _activeSheet;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -27,34 +29,35 @@ class ProductScreen extends StatelessWidget {
|
|||
icon: Icon(Icons.search),
|
||||
onPressed: () {},
|
||||
),
|
||||
StoreConnector(
|
||||
converter: (Store<AppState> store) => store,
|
||||
builder: (context, store) {
|
||||
return ActionMenuButton(
|
||||
scaffoldKey: _scaffoldKey,
|
||||
onSelectedSort: (value) {
|
||||
store.dispatch(SortProducts(value));
|
||||
},
|
||||
selectedSort: store.state.productUIState().sortField,
|
||||
sortFields: [
|
||||
SortField(ProductFields.productKey,
|
||||
AppLocalization.of((context)).product),
|
||||
SortField(
|
||||
ProductFields.cost, AppLocalization.of((context)).cost),
|
||||
],
|
||||
actions: [
|
||||
ActionMenuChoice(ActionMenuButtonType.sort),
|
||||
ActionMenuChoice(ActionMenuButtonType.filter),
|
||||
],
|
||||
onSelected: (ActionMenuChoice choice) {},
|
||||
);
|
||||
/*
|
||||
ActionMenuButton(
|
||||
onSelectedSort: (value, callback) {
|
||||
StoreProvider.of<AppState>(context).dispatch(SortProducts(value));
|
||||
//callback();
|
||||
},
|
||||
), //FilterSelector(visible: activeTab == AppTab.products),
|
||||
//ExtraActionsContainer(),
|
||||
actions: [
|
||||
ActionMenuChoice(ActionMenuButtonType.sort),
|
||||
ActionMenuChoice(ActionMenuButtonType.filter),
|
||||
],
|
||||
onSelected: (ActionMenuChoice choice) {},
|
||||
)
|
||||
*/
|
||||
],
|
||||
),
|
||||
drawer: AppDrawerBuilder(),
|
||||
body: ProductListBuilder(),
|
||||
bottomNavigationBar: AppBottomBar(
|
||||
scaffoldKey: _scaffoldKey,
|
||||
selectedSort: StoreProvider.of<AppState>(context).state.productUIState().sortField,
|
||||
onSelectedSort: (value) {
|
||||
StoreProvider.of<AppState>(context).dispatch(SortProducts(value));
|
||||
},
|
||||
sortFields: [
|
||||
ProductFields.productKey,
|
||||
ProductFields.cost,
|
||||
],
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||
floatingActionButton: StoreConnector(
|
||||
converter: (Store<AppState> store) => store,
|
||||
builder: (context, store) {
|
||||
|
|
@ -67,7 +70,7 @@ class ProductScreen extends StatelessWidget {
|
|||
MaterialPageRoute(builder: (_) => ProductDetailsBuilder()));
|
||||
},
|
||||
child: Icon(Icons.add),
|
||||
//tooltip: ArchSampleLocalizations.of(context).addProduct,
|
||||
tooltip: AppLocalization.of(context).newProduct,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class AppLocalization {
|
|||
'new_product': 'New Product',
|
||||
'product': 'Product',
|
||||
'products': 'Products',
|
||||
'productKey': 'Product Key',
|
||||
'notes': 'Notes',
|
||||
'cost': 'Cost',
|
||||
'clients': 'Clients',
|
||||
|
|
@ -52,6 +53,7 @@ class AppLocalization {
|
|||
String get newProduct => _localizedValues[locale.languageCode]['new_product'];
|
||||
String get product => _localizedValues[locale.languageCode]['product'];
|
||||
String get products => _localizedValues[locale.languageCode]['products'];
|
||||
String get productKey => _localizedValues[locale.languageCode]['product_key'];
|
||||
String get notes => _localizedValues[locale.languageCode]['notes'];
|
||||
String get cost => _localizedValues[locale.languageCode]['cost'];
|
||||
String get clients => _localizedValues[locale.languageCode]['clients'];
|
||||
|
|
@ -62,7 +64,9 @@ class AppLocalization {
|
|||
String get successfullyDeletedProduct=> _localizedValues[locale.languageCode]['successfully_deleted_product'];
|
||||
String get successfullyRestoredProduct => _localizedValues[locale.languageCode]['successfully_restored_product'];
|
||||
|
||||
|
||||
String lookup(String key) {
|
||||
return _localizedValues[locale.languageCode][key] ?? 'Missing: ' + key;
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalization> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue