Working on clients
This commit is contained in:
parent
7c9af8e31a
commit
13e0bdfc6c
|
|
@ -28,6 +28,8 @@ class EntityType extends EnumClass {
|
||||||
static const EntityType country = _$country;
|
static const EntityType country = _$country;
|
||||||
static const EntityType currency = _$currency;
|
static const EntityType currency = _$currency;
|
||||||
static const EntityType language = _$language;
|
static const EntityType language = _$language;
|
||||||
|
static const EntityType industry = _$language;
|
||||||
|
static const EntityType size = _$language;
|
||||||
|
|
||||||
String get plural {
|
String get plural {
|
||||||
return toString() + 's';
|
return toString() + 's';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:built_collection/built_collection.dart';
|
import 'package:built_collection/built_collection.dart';
|
||||||
import 'package:built_value/built_value.dart';
|
import 'package:built_value/built_value.dart';
|
||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
|
||||||
part 'industry_model.g.dart';
|
part 'industry_model.g.dart';
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ class IndustryFields {
|
||||||
static const String name = 'name';
|
static const String name = 'name';
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class IndustryEntity implements Built<IndustryEntity, IndustryEntityBuilder> {
|
abstract class IndustryEntity extends Object with SelectableEntity implements Built<IndustryEntity, IndustryEntityBuilder> {
|
||||||
|
|
||||||
factory IndustryEntity() {
|
factory IndustryEntity() {
|
||||||
return _$IndustryEntity._(
|
return _$IndustryEntity._(
|
||||||
|
|
@ -38,8 +39,41 @@ abstract class IndustryEntity implements Built<IndustryEntity, IndustryEntityBui
|
||||||
}
|
}
|
||||||
IndustryEntity._();
|
IndustryEntity._();
|
||||||
|
|
||||||
int get id;
|
|
||||||
String get name;
|
String get name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool matchesFilter(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
if (name.toLowerCase().contains(filter)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String matchesFilterValue(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get listDisplayName {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get listDisplayAmount => null;
|
||||||
|
|
||||||
static Serializer<IndustryEntity> get serializer => _$industryEntitySerializer;
|
static Serializer<IndustryEntity> get serializer => _$industryEntitySerializer;
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:built_collection/built_collection.dart';
|
import 'package:built_collection/built_collection.dart';
|
||||||
import 'package:built_value/built_value.dart';
|
import 'package:built_value/built_value.dart';
|
||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
|
||||||
part 'size_model.g.dart';
|
part 'size_model.g.dart';
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ class SizeFields {
|
||||||
static const String name = 'name';
|
static const String name = 'name';
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class SizeEntity implements Built<SizeEntity, SizeEntityBuilder> {
|
abstract class SizeEntity extends Object with SelectableEntity implements Built<SizeEntity, SizeEntityBuilder> {
|
||||||
|
|
||||||
factory SizeEntity() {
|
factory SizeEntity() {
|
||||||
return _$SizeEntity._(
|
return _$SizeEntity._(
|
||||||
|
|
@ -38,9 +39,41 @@ abstract class SizeEntity implements Built<SizeEntity, SizeEntityBuilder> {
|
||||||
}
|
}
|
||||||
SizeEntity._();
|
SizeEntity._();
|
||||||
|
|
||||||
int get id;
|
|
||||||
|
|
||||||
String get name;
|
String get name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool matchesFilter(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
if (name.toLowerCase().contains(filter)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String matchesFilterValue(String filter) {
|
||||||
|
if (filter == null || filter.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = filter.toLowerCase();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get listDisplayName {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get listDisplayAmount => null;
|
||||||
|
|
||||||
static Serializer<SizeEntity> get serializer => _$sizeEntitySerializer;
|
static Serializer<SizeEntity> get serializer => _$sizeEntitySerializer;
|
||||||
}
|
}
|
||||||
|
|
@ -38,3 +38,27 @@ List<int> currencyList(BuiltMap<int, CurrencyEntity> currencyMap) {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var memoizedIndustryList = memo1((BuiltMap<int, IndustryEntity> industryMap) =>
|
||||||
|
industryList(industryMap));
|
||||||
|
|
||||||
|
List<int> industryList(BuiltMap<int, IndustryEntity> industryMap) {
|
||||||
|
final list = industryMap.keys.toList();
|
||||||
|
|
||||||
|
list.sort((idA, idB) => industryMap[idA].listDisplayName
|
||||||
|
.compareTo(industryMap[idB].listDisplayName));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
var memoizedSizeList = memo1((BuiltMap<int, SizeEntity> sizeMap) =>
|
||||||
|
sizeList(sizeMap));
|
||||||
|
|
||||||
|
List<int> sizeList(BuiltMap<int, SizeEntity> sizeMap) {
|
||||||
|
final list = sizeMap.keys.toList();
|
||||||
|
|
||||||
|
list.sort((idA, idB) => sizeMap[idA].listDisplayName
|
||||||
|
.compareTo(sizeMap[idB].listDisplayName));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,10 +125,10 @@ class ClientEditBillingAddressState extends State<ClientEditBillingAddress> {
|
||||||
),
|
),
|
||||||
EntityDropdown(
|
EntityDropdown(
|
||||||
entityType: EntityType.country,
|
entityType: EntityType.country,
|
||||||
entityMap: viewModel.countryMap,
|
entityMap: viewModel.staticState.countryMap,
|
||||||
entityList: memoizedCountryList(viewModel.countryMap),
|
entityList: memoizedCountryList(viewModel.staticState.countryMap),
|
||||||
labelText: localization.country,
|
labelText: localization.country,
|
||||||
initialValue: viewModel.countryMap[client.countryId]?.name,
|
initialValue: viewModel.staticState.countryMap[client.countryId]?.name,
|
||||||
onSelected: (int countryId) => viewModel
|
onSelected: (int countryId) => viewModel
|
||||||
.onChanged(client.rebuild((b) => b..countryId = countryId)),
|
.onChanged(client.rebuild((b) => b..countryId = countryId)),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
|
||||||
|
|
||||||
class ClientEditNotes extends StatefulWidget {
|
class ClientEditNotes extends StatefulWidget {
|
||||||
const ClientEditNotes({
|
const ClientEditNotes({
|
||||||
|
|
@ -66,6 +69,7 @@ class ClientEditNotesState extends State<ClientEditNotes> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
|
final client = viewModel.client;
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
|
@ -73,7 +77,7 @@ class ClientEditNotesState extends State<ClientEditNotes> {
|
||||||
FormCard(
|
FormCard(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
TextFormField(
|
TextFormField(
|
||||||
maxLines: 6,
|
maxLines: 4,
|
||||||
controller: _publicNotesController,
|
controller: _publicNotesController,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
|
@ -81,13 +85,31 @@ class ClientEditNotesState extends State<ClientEditNotes> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
maxLines: 6,
|
maxLines: 4,
|
||||||
controller: _privateNotesController,
|
controller: _privateNotesController,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: localization.privateNotes,
|
labelText: localization.privateNotes,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
EntityDropdown(
|
||||||
|
entityType: EntityType.size,
|
||||||
|
entityMap: viewModel.staticState.sizeMap,
|
||||||
|
entityList: memoizedSizeList(viewModel.staticState.sizeMap),
|
||||||
|
labelText: localization.size,
|
||||||
|
initialValue: viewModel.staticState.sizeMap[client.sizeId]?.name,
|
||||||
|
onSelected: (int sizeId) => viewModel
|
||||||
|
.onChanged(client.rebuild((b) => b..sizeId = sizeId)),
|
||||||
|
),
|
||||||
|
EntityDropdown(
|
||||||
|
entityType: EntityType.industry,
|
||||||
|
entityMap: viewModel.staticState.industryMap,
|
||||||
|
entityList: memoizedIndustryList(viewModel.staticState.industryMap),
|
||||||
|
labelText: localization.industry,
|
||||||
|
initialValue: viewModel.staticState.industryMap[client.industryId]?.name,
|
||||||
|
onSelected: (int industryId) => viewModel
|
||||||
|
.onChanged(client.rebuild((b) => b..industryId = industryId)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -77,19 +77,19 @@ class ClientEditSettingsState extends State<ClientEditSettings> {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
EntityDropdown(
|
EntityDropdown(
|
||||||
entityType: EntityType.currency,
|
entityType: EntityType.currency,
|
||||||
entityMap: viewModel.currencyMap,
|
entityMap: viewModel.staticState.currencyMap,
|
||||||
entityList: memoizedCurrencyList(viewModel.currencyMap),
|
entityList: memoizedCurrencyList(viewModel.staticState.currencyMap),
|
||||||
labelText: localization.currency,
|
labelText: localization.currency,
|
||||||
initialValue: viewModel.currencyMap[client.currencyId]?.name,
|
initialValue: viewModel.staticState.currencyMap[client.currencyId]?.name,
|
||||||
onSelected: (int currencyId) => viewModel
|
onSelected: (int currencyId) => viewModel
|
||||||
.onChanged(client.rebuild((b) => b..currencyId = currencyId)),
|
.onChanged(client.rebuild((b) => b..currencyId = currencyId)),
|
||||||
),
|
),
|
||||||
EntityDropdown(
|
EntityDropdown(
|
||||||
entityType: EntityType.language,
|
entityType: EntityType.language,
|
||||||
entityMap: viewModel.languageMap,
|
entityMap: viewModel.staticState.languageMap,
|
||||||
entityList: memoizedLanguageList(viewModel.languageMap),
|
entityList: memoizedLanguageList(viewModel.staticState.languageMap),
|
||||||
labelText: localization.language,
|
labelText: localization.language,
|
||||||
initialValue: viewModel.languageMap[client.languageId]?.name,
|
initialValue: viewModel.staticState.languageMap[client.languageId]?.name,
|
||||||
onSelected: (int languageId) => viewModel
|
onSelected: (int languageId) => viewModel
|
||||||
.onChanged(client.rebuild((b) => b..languageId = languageId)),
|
.onChanged(client.rebuild((b) => b..languageId = languageId)),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -125,10 +125,10 @@ class ClientEditShippingAddressState extends State<ClientEditShippingAddress> {
|
||||||
),
|
),
|
||||||
EntityDropdown(
|
EntityDropdown(
|
||||||
entityType: EntityType.country,
|
entityType: EntityType.country,
|
||||||
entityMap: viewModel.countryMap,
|
entityMap: viewModel.staticState.countryMap,
|
||||||
entityList: memoizedCountryList(viewModel.countryMap),
|
entityList: memoizedCountryList(viewModel.staticState.countryMap),
|
||||||
labelText: localization.country,
|
labelText: localization.country,
|
||||||
initialValue: viewModel.countryMap[client.shippingCountryId]?.name,
|
initialValue: viewModel.staticState.countryMap[client.shippingCountryId]?.name,
|
||||||
onSelected: (int countryId) => viewModel
|
onSelected: (int countryId) => viewModel
|
||||||
.onChanged(client.rebuild((b) => b..shippingCountryId = countryId)),
|
.onChanged(client.rebuild((b) => b..shippingCountryId = countryId)),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:built_collection/built_collection.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/client/client_screen.dart';
|
import 'package:invoiceninja_flutter/ui/client/client_screen.dart';
|
||||||
|
|
@ -42,9 +42,7 @@ class ClientEditVM {
|
||||||
final Function(ClientEntity) onChanged;
|
final Function(ClientEntity) onChanged;
|
||||||
final Function(BuildContext) onSavePressed;
|
final Function(BuildContext) onSavePressed;
|
||||||
final Function onBackPressed;
|
final Function onBackPressed;
|
||||||
final BuiltMap<int, CountryEntity> countryMap;
|
final StaticState staticState;
|
||||||
final BuiltMap<int, LanguageEntity> languageMap;
|
|
||||||
final BuiltMap<int, CurrencyEntity> currencyMap;
|
|
||||||
|
|
||||||
ClientEditVM({
|
ClientEditVM({
|
||||||
@required this.company,
|
@required this.company,
|
||||||
|
|
@ -54,9 +52,7 @@ class ClientEditVM {
|
||||||
@required this.onChanged,
|
@required this.onChanged,
|
||||||
@required this.onSavePressed,
|
@required this.onSavePressed,
|
||||||
@required this.onBackPressed,
|
@required this.onBackPressed,
|
||||||
@required this.countryMap,
|
@required this.staticState,
|
||||||
@required this.languageMap,
|
|
||||||
@required this.currencyMap,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
factory ClientEditVM.fromStore(Store<AppState> store) {
|
factory ClientEditVM.fromStore(Store<AppState> store) {
|
||||||
|
|
@ -67,9 +63,7 @@ class ClientEditVM {
|
||||||
company: state.selectedCompany,
|
company: state.selectedCompany,
|
||||||
client: client,
|
client: client,
|
||||||
origClient: state.clientState.map[client.id],
|
origClient: state.clientState.map[client.id],
|
||||||
countryMap: state.staticState.countryMap,
|
staticState: state.staticState,
|
||||||
languageMap: state.staticState.languageMap,
|
|
||||||
currencyMap: state.staticState.currencyMap,
|
|
||||||
isSaving: state.isSaving,
|
isSaving: state.isSaving,
|
||||||
onBackPressed: () =>
|
onBackPressed: () =>
|
||||||
store.dispatch(UpdateCurrentRoute(ClientScreen.route)),
|
store.dispatch(UpdateCurrentRoute(ClientScreen.route)),
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,12 @@ import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class InvoiceViewScreen extends StatelessWidget {
|
class InvoiceViewScreen extends StatelessWidget {
|
||||||
static const String route = '/invoice/view';
|
static const String route = '/invoice/view';
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,8 @@ class AppLocalization {
|
||||||
'no_records_found': 'No records found',
|
'no_records_found': 'No records found',
|
||||||
'clone': 'Clone',
|
'clone': 'Clone',
|
||||||
'loading': 'Loading',
|
'loading': 'Loading',
|
||||||
|
'industry': 'Industry',
|
||||||
|
'size': 'Size',
|
||||||
|
|
||||||
'payment': 'Payment',
|
'payment': 'Payment',
|
||||||
'payments': 'Payments',
|
'payments': 'Payments',
|
||||||
|
|
@ -413,6 +415,8 @@ class AppLocalization {
|
||||||
String get noRecordsFound => _localizedValues[locale.languageCode]['no_records_found'];
|
String get noRecordsFound => _localizedValues[locale.languageCode]['no_records_found'];
|
||||||
String get clone => _localizedValues[locale.languageCode]['clone'];
|
String get clone => _localizedValues[locale.languageCode]['clone'];
|
||||||
String get loading => _localizedValues[locale.languageCode]['loading'];
|
String get loading => _localizedValues[locale.languageCode]['loading'];
|
||||||
|
String get industry => _localizedValues[locale.languageCode]['industry'];
|
||||||
|
String get size => _localizedValues[locale.languageCode]['size'];
|
||||||
|
|
||||||
String get payment => _localizedValues[locale.languageCode]['payment'];
|
String get payment => _localizedValues[locale.languageCode]['payment'];
|
||||||
String get payments => _localizedValues[locale.languageCode]['payments'];
|
String get payments => _localizedValues[locale.languageCode]['payments'];
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
|
|
||||||
|
|
||||||
String getMapURL(BuildContext context) {
|
String getMapURL(BuildContext context) {
|
||||||
final bool iOS = Theme.of(context).platform == TargetPlatform.iOS;
|
final bool iOS = Theme.of(context).platform == TargetPlatform.iOS;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue