This commit is contained in:
Hillel Coren 2019-10-31 12:54:29 +02:00
parent a0047acaa2
commit dab542e652
7 changed files with 189 additions and 12 deletions

View File

@ -141,6 +141,49 @@ String paymentStatsForClient(
return str; return str;
} }
var memoizedPaymentStatsForUser = memo5((String userId,
BuiltMap<String, PaymentEntity> paymentMap,
BuiltMap<String, InvoiceEntity> invoiceMap,
String activeLabel,
String archivedLabel) =>
paymentStatsForClient(
userId, paymentMap, invoiceMap, activeLabel, archivedLabel));
String paymentStatsForUser(
String userId,
BuiltMap<String, PaymentEntity> paymentMap,
BuiltMap<String, InvoiceEntity> invoiceMap,
String activeLabel,
String archivedLabel) {
int countActive = 0;
int countArchived = 0;
paymentMap.forEach((paymentId, payment) {
if (invoiceMap.containsKey(payment.invoiceId))
// TODO enable this code
//&& invoiceMap[payment.invoiceId].userId == userId)
{
if (payment.isActive) {
countActive++;
} else if (payment.isArchived) {
countArchived++;
}
}
});
String str = '';
if (countActive > 0) {
str = '$countActive $activeLabel';
if (countArchived > 0) {
str += '';
}
}
if (countArchived > 0) {
str += '$countArchived $archivedLabel';
}
return str;
}
bool hasPaymentChanges( bool hasPaymentChanges(
PaymentEntity payment, BuiltMap<String, PaymentEntity> paymentMap) => PaymentEntity payment, BuiltMap<String, PaymentEntity> paymentMap) =>
payment.isNew ? payment.isChanged : payment != paymentMap[payment.id]; payment.isNew ? payment.isChanged : payment != paymentMap[payment.id];

View File

@ -98,6 +98,44 @@ String quoteStatsForClient(
return str; return str;
} }
var memoizedQuoteStatsForUser = memo4((String userId,
BuiltMap<String, InvoiceEntity> quoteMap,
String activeLabel,
String archivedLabel) =>
quoteStatsForUser(userId, quoteMap, activeLabel, archivedLabel));
String quoteStatsForUser(
String userId,
BuiltMap<String, InvoiceEntity> quoteMap,
String activeLabel,
String archivedLabel) {
int countActive = 0;
int countArchived = 0;
quoteMap.forEach((quoteId, quote) {
// TODO change to user id match
if (quote.clientId == userId) {
if (quote.isActive) {
countActive++;
} else if (quote.isArchived) {
countArchived++;
}
}
});
String str = '';
if (countActive > 0) {
str = '$countActive $activeLabel';
if (countArchived > 0) {
str += '';
}
}
if (countArchived > 0) {
str += '$countArchived $archivedLabel';
}
return str;
}
bool hasQuoteChanges( bool hasQuoteChanges(
InvoiceEntity quote, BuiltMap<String, InvoiceEntity> quoteMap) => InvoiceEntity quote, BuiltMap<String, InvoiceEntity> quoteMap) =>
quote.isNew ? quote.isChanged : quote != quoteMap[quote.id]; quote.isNew ? quote.isChanged : quote != quoteMap[quote.id];

View File

@ -158,12 +158,12 @@ class SettingsList extends StatelessWidget {
viewModel: viewModel, viewModel: viewModel,
icon: FontAwesomeIcons.solidEnvelope, icon: FontAwesomeIcons.solidEnvelope,
), ),
/*
SettingsListTile( SettingsListTile(
section: kSettingsTemplatesAndReminders, section: kSettingsTemplatesAndReminders,
viewModel: viewModel, viewModel: viewModel,
icon: FontAwesomeIcons.solidClock, icon: FontAwesomeIcons.file,
), ),
/*
SettingsListTile( SettingsListTile(
section: kSettingsCreditCardsAndBanks, section: kSettingsCreditCardsAndBanks,
viewModel: viewModel, viewModel: viewModel,

View File

@ -1,8 +1,10 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart'; import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart';
class TemplatesAndReminders extends StatefulWidget { class TemplatesAndReminders extends StatefulWidget {
const TemplatesAndReminders({ const TemplatesAndReminders({
@ -18,8 +20,9 @@ class TemplatesAndReminders extends StatefulWidget {
class _TemplatesAndRemindersState extends State<TemplatesAndReminders> class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
//static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
FocusScopeNode _focusNode;
TabController _controller; TabController _controller;
bool autoValidate = false; bool autoValidate = false;
@ -31,11 +34,13 @@ class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_controller = TabController(vsync: this, length: 3); _focusNode = FocusScopeNode();
_controller = TabController(vsync: this, length: 7);
} }
@override @override
void dispose() { void dispose() {
_focusNode.dispose();
_controller.dispose(); _controller.dispose();
_controllers.forEach((dynamic controller) { _controllers.forEach((dynamic controller) {
controller.removeListener(_onChanged); controller.removeListener(_onChanged);
@ -75,12 +80,65 @@ class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
@override @override
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 state = viewModel.state;
return SettingsScaffold( return SettingsScaffold(
title: localization.templatesAndReminders, title: localization.templatesAndReminders,
onSavePressed: null, onSavePressed: viewModel.onSavePressed,
body: SizedBox(), appBarBottom: TabBar(
key: ValueKey(state.settingsUIState.updatedAt),
controller: _controller,
isScrollable: true,
tabs: [
Tab(
text: localization.invoices,
),
Tab(
text: localization.quotes,
),
Tab(
text: localization.payments,
),
Tab(
text: localization.firstReminder,
),
Tab(
text: localization.secondReminder,
),
Tab(
text: localization.thirdReminder,
),
Tab(
text: localization.endlessReminder,
),
],
),
body: AppTabForm(
tabController: _controller,
formKey: _formKey,
focusNode: _focusNode,
children: <Widget>[
TemplateEditor(),
TemplateEditor(),
TemplateEditor(),
TemplateEditor(),
TemplateEditor(),
TemplateEditor(),
TemplateEditor(),
],
),
);
}
}
class TemplateEditor extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
Text('test')
],
); );
} }
} }

View File

@ -2,7 +2,14 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders.dart'; import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
@ -27,6 +34,8 @@ class TemplatesAndRemindersScreen extends StatelessWidget {
class TemplatesAndRemindersVM { class TemplatesAndRemindersVM {
TemplatesAndRemindersVM({ TemplatesAndRemindersVM({
@required this.state, @required this.state,
@required this.settings,
@required this.onSettingsChanged,
@required this.onSavePressed, @required this.onSavePressed,
@required this.onCancelPressed, @required this.onCancelPressed,
}); });
@ -35,13 +44,37 @@ class TemplatesAndRemindersVM {
final state = store.state; final state = store.state;
return TemplatesAndRemindersVM( return TemplatesAndRemindersVM(
state: state, state: state,
onSavePressed: null, settings: state.uiState.settingsUIState.settings,
onCancelPressed: null, onSettingsChanged: (settings) {
); store.dispatch(UpdateSettings(settings: settings));
},
onCancelPressed: (context) => store.dispatch(ResetSettings()),
onSavePressed: (context) {
final settingsUIState = state.uiState.settingsUIState;
final completer = snackBarCompleter(
context, AppLocalization.of(context).savedSettings);
switch (settingsUIState.entityType) {
case EntityType.company:
store.dispatch(SaveCompanyRequest(
completer: completer,
company: settingsUIState.userCompany.company));
break;
case EntityType.group:
store.dispatch(SaveGroupRequest(
completer: completer, group: settingsUIState.group));
break;
case EntityType.client:
store.dispatch(SaveClientRequest(
completer: completer, client: settingsUIState.client));
break;
}
});
} }
final AppState state; final AppState state;
final SettingsEntity settings;
final Function(SettingsEntity) onSettingsChanged;
final Function(BuildContext) onSavePressed; final Function(BuildContext) onSavePressed;
final Function(BuildContext) onCancelPressed; final Function(BuildContext) onCancelPressed;
} }

View File

@ -2,6 +2,8 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart'; import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart'; import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
@ -29,6 +31,7 @@ class UserView extends StatelessWidget {
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final user = viewModel.user; final user = viewModel.user;
final state = StoreProvider.of<AppState>(context).state; final state = StoreProvider.of<AppState>(context).state;
final company = state.selectedCompany;
final userCompany = state.userCompany; final userCompany = state.userCompany;
return Scaffold( return Scaffold(
@ -100,7 +103,6 @@ class UserView extends StatelessWidget {
localization.active, localization.active,
localization.archived), localization.archived),
), ),
/*
EntityListTile( EntityListTile(
bottomPadding: 1, bottomPadding: 1,
icon: getEntityIcon(EntityType.payment), icon: getEntityIcon(EntityType.payment),
@ -131,6 +133,7 @@ class UserView extends StatelessWidget {
localization.archived), localization.archived),
) )
: Container(), : Container(),
/*
company.isModuleEnabled(EntityType.project) company.isModuleEnabled(EntityType.project)
? EntityListTile( ? EntityListTile(
bottomPadding: 1, bottomPadding: 1,

View File

@ -14,6 +14,7 @@ abstract class LocaleCodeAware {
mixin LocalizationsProvider on LocaleCodeAware { mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = { static final Map<String, Map<String, String>> _localizedValues = {
'en': { 'en': {
'endless_reminder': 'Endless Reminder',
'filtered_by_user': 'Filtered by User', 'filtered_by_user': 'Filtered by User',
'administrator': 'Administrator', 'administrator': 'Administrator',
'administrator_help': 'Allow user to manage users, change settings and modify all records', 'administrator_help': 'Allow user to manage users, change settings and modify all records',
@ -15404,6 +15405,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
String get filteredByUser => _localizedValues[localeCode]['filtered_by_user']; String get filteredByUser => _localizedValues[localeCode]['filtered_by_user'];
String get endlessReminder => _localizedValues[localeCode]['endless_reminder'];
String lookup(String key) { String lookup(String key) {
final lookupKey = toSnakeCase(key); final lookupKey = toSnakeCase(key);