Quotes
This commit is contained in:
parent
5ed5f85124
commit
128c025224
|
|
@ -17,8 +17,8 @@ Join the Android beta: https://play.google.com/apps/testing/com.invoiceninja.inv
|
||||||
- [x] Clients
|
- [x] Clients
|
||||||
- [x] Products
|
- [x] Products
|
||||||
- [x] Invoices
|
- [x] Invoices
|
||||||
|
- [x] Quotes
|
||||||
- [ ] Payments
|
- [ ] Payments
|
||||||
- [ ] Quotes
|
|
||||||
- [ ] Credits
|
- [ ] Credits
|
||||||
- [ ] Recurring
|
- [ ] Recurring
|
||||||
- [ ] Vendors
|
- [ ] Vendors
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/quote/quote_email_vm.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -146,6 +147,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
},
|
},
|
||||||
QuoteViewScreen.route: (context) => QuoteViewScreen(),
|
QuoteViewScreen.route: (context) => QuoteViewScreen(),
|
||||||
QuoteEditScreen.route: (context) => QuoteEditScreen(),
|
QuoteEditScreen.route: (context) => QuoteEditScreen(),
|
||||||
|
QuoteEmailScreen.route: (context) => QuoteEmailScreen(),
|
||||||
SettingsScreen.route: (context) => SettingsScreen(),
|
SettingsScreen.route: (context) => SettingsScreen(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
import 'package:invoiceninja_flutter/redux/quote/quote_actions.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/invoice/invoice_email_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
import 'package:invoiceninja_flutter/redux/quote/quote_actions.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/invoice/invoice_email_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/quote/edit/quote_edit_vm.dart';
|
import 'package:invoiceninja_flutter/ui/quote/edit/quote_edit_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/quote/quote_email_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/quote/quote_screen.dart';
|
import 'package:invoiceninja_flutter/ui/quote/quote_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
|
|
@ -68,7 +69,7 @@ Middleware<AppState> _editQuote() {
|
||||||
|
|
||||||
store.dispatch(UpdateCurrentRoute(QuoteEditScreen.route));
|
store.dispatch(UpdateCurrentRoute(QuoteEditScreen.route));
|
||||||
final quote =
|
final quote =
|
||||||
await Navigator.of(action.context).pushNamed(QuoteEditScreen.route);
|
await Navigator.of(action.context).pushNamed(QuoteEditScreen.route);
|
||||||
|
|
||||||
if (action.completer != null && quote != null) {
|
if (action.completer != null && quote != null) {
|
||||||
action.completer.complete(quote);
|
action.completer.complete(quote);
|
||||||
|
|
@ -80,7 +81,8 @@ Middleware<AppState> _showEmailQuote() {
|
||||||
return (Store<AppState> store, dynamic action, NextDispatcher next) async {
|
return (Store<AppState> store, dynamic action, NextDispatcher next) async {
|
||||||
next(action);
|
next(action);
|
||||||
|
|
||||||
final emailWasSent = await Navigator.of(action.context).pushNamed(InvoiceEmailScreen.route);
|
final emailWasSent =
|
||||||
|
await Navigator.of(action.context).pushNamed(QuoteEmailScreen.route);
|
||||||
|
|
||||||
if (action.completer != null && emailWasSent) {
|
if (action.completer != null && emailWasSent) {
|
||||||
action.completer.complete(null);
|
action.completer.complete(null);
|
||||||
|
|
@ -92,8 +94,8 @@ Middleware<AppState> _archiveQuote(QuoteRepository repository) {
|
||||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||||
final origQuote = store.state.quoteState.map[action.quoteId];
|
final origQuote = store.state.quoteState.map[action.quoteId];
|
||||||
repository
|
repository
|
||||||
.saveData(store.state.selectedCompany, store.state.authState,
|
.saveData(store.state.selectedCompany, store.state.authState, origQuote,
|
||||||
origQuote, EntityAction.archive)
|
EntityAction.archive)
|
||||||
.then((dynamic quote) {
|
.then((dynamic quote) {
|
||||||
store.dispatch(ArchiveQuoteSuccess(quote));
|
store.dispatch(ArchiveQuoteSuccess(quote));
|
||||||
if (action.completer != null) {
|
if (action.completer != null) {
|
||||||
|
|
@ -115,8 +117,8 @@ Middleware<AppState> _deleteQuote(QuoteRepository repository) {
|
||||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||||
final origQuote = store.state.quoteState.map[action.quoteId];
|
final origQuote = store.state.quoteState.map[action.quoteId];
|
||||||
repository
|
repository
|
||||||
.saveData(store.state.selectedCompany, store.state.authState,
|
.saveData(store.state.selectedCompany, store.state.authState, origQuote,
|
||||||
origQuote, EntityAction.delete)
|
EntityAction.delete)
|
||||||
.then((InvoiceEntity quote) {
|
.then((InvoiceEntity quote) {
|
||||||
store.dispatch(DeleteQuoteSuccess(quote));
|
store.dispatch(DeleteQuoteSuccess(quote));
|
||||||
store.dispatch(LoadClient(clientId: quote.clientId));
|
store.dispatch(LoadClient(clientId: quote.clientId));
|
||||||
|
|
@ -139,8 +141,8 @@ Middleware<AppState> _restoreQuote(QuoteRepository repository) {
|
||||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||||
final origQuote = store.state.quoteState.map[action.quoteId];
|
final origQuote = store.state.quoteState.map[action.quoteId];
|
||||||
repository
|
repository
|
||||||
.saveData(store.state.selectedCompany, store.state.authState,
|
.saveData(store.state.selectedCompany, store.state.authState, origQuote,
|
||||||
origQuote, EntityAction.restore)
|
EntityAction.restore)
|
||||||
.then((InvoiceEntity quote) {
|
.then((InvoiceEntity quote) {
|
||||||
store.dispatch(RestoreQuoteSuccess(quote));
|
store.dispatch(RestoreQuoteSuccess(quote));
|
||||||
store.dispatch(LoadClient(clientId: quote.clientId));
|
store.dispatch(LoadClient(clientId: quote.clientId));
|
||||||
|
|
@ -163,8 +165,8 @@ Middleware<AppState> _markSentQuote(QuoteRepository repository) {
|
||||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||||
final origQuote = store.state.quoteState.map[action.quoteId];
|
final origQuote = store.state.quoteState.map[action.quoteId];
|
||||||
repository
|
repository
|
||||||
.saveData(store.state.selectedCompany, store.state.authState,
|
.saveData(store.state.selectedCompany, store.state.authState, origQuote,
|
||||||
origQuote, EntityAction.markSent)
|
EntityAction.markSent)
|
||||||
.then((dynamic quote) {
|
.then((dynamic quote) {
|
||||||
store.dispatch(MarkSentQuoteSuccess(quote));
|
store.dispatch(MarkSentQuoteSuccess(quote));
|
||||||
store.dispatch(LoadClient(clientId: quote.clientId));
|
store.dispatch(LoadClient(clientId: quote.clientId));
|
||||||
|
|
@ -212,7 +214,7 @@ Middleware<AppState> _saveQuote(QuoteRepository repository) {
|
||||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||||
repository
|
repository
|
||||||
.saveData(
|
.saveData(
|
||||||
store.state.selectedCompany, store.state.authState, action.quote)
|
store.state.selectedCompany, store.state.authState, action.quote)
|
||||||
.then((dynamic quote) {
|
.then((dynamic quote) {
|
||||||
if (action.quote.isNew) {
|
if (action.quote.isNew) {
|
||||||
store.dispatch(AddQuoteSuccess(quote));
|
store.dispatch(AddQuoteSuccess(quote));
|
||||||
|
|
@ -275,7 +277,7 @@ Middleware<AppState> _loadQuotes(QuoteRepository repository) {
|
||||||
}
|
}
|
||||||
|
|
||||||
final int updatedAt =
|
final int updatedAt =
|
||||||
action.force ? 0 : (state.quoteState.lastUpdated / 1000).round();
|
action.force ? 0 : (state.quoteState.lastUpdated / 1000).round();
|
||||||
|
|
||||||
store.dispatch(LoadQuotesRequest());
|
store.dispatch(LoadQuotesRequest());
|
||||||
repository
|
repository
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/buttons/refresh_icon_button.dart';
|
import 'package:invoiceninja_flutter/ui/app/buttons/refresh_icon_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_vm.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
|
||||||
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/lists/activity_list_tile.dart';
|
import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart';
|
||||||
|
|
@ -14,7 +14,7 @@ import 'package:invoiceninja_flutter/utils/templates.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
|
|
||||||
class InvoiceEmailView extends StatefulWidget {
|
class InvoiceEmailView extends StatefulWidget {
|
||||||
final EmailInvoiceVM viewModel;
|
final EmailEntityVM viewModel;
|
||||||
|
|
||||||
const InvoiceEmailView({
|
const InvoiceEmailView({
|
||||||
Key key,
|
Key key,
|
||||||
|
|
@ -68,14 +68,20 @@ class _InvoiceEmailViewState extends State<InvoiceEmailView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadTemplate(EmailTemplate template) {
|
void loadTemplate(EmailTemplate template) {
|
||||||
final company = widget.viewModel.company;
|
final viewModel = widget.viewModel;
|
||||||
|
final company = viewModel.company;
|
||||||
|
|
||||||
selectedTemplate = template;
|
selectedTemplate = template;
|
||||||
|
|
||||||
switch (template) {
|
switch (template) {
|
||||||
case EmailTemplate.initial:
|
case EmailTemplate.initial:
|
||||||
emailSubject = company.emailSubjectInvoice;
|
if (viewModel.invoice.isQuote) {
|
||||||
emailBody = company.emailBodyInvoice;
|
emailSubject = company.emailSubjectQuote;
|
||||||
|
emailBody = company.emailBodyQuote;
|
||||||
|
} else {
|
||||||
|
emailSubject = company.emailSubjectInvoice;
|
||||||
|
emailBody = company.emailBodyInvoice;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EmailTemplate.reminder1:
|
case EmailTemplate.reminder1:
|
||||||
emailSubject = company.emailSubjectReminder1;
|
emailSubject = company.emailSubjectReminder1;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class InvoiceEmailScreen extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EmailInvoiceVM {
|
abstract class EmailEntityVM {
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
final bool isSaving;
|
final bool isSaving;
|
||||||
final CompanyEntity company;
|
final CompanyEntity company;
|
||||||
|
|
@ -49,7 +49,7 @@ class EmailInvoiceVM {
|
||||||
final ClientEntity client;
|
final ClientEntity client;
|
||||||
final Function(BuildContext, EmailTemplate, String, String) onSendPressed;
|
final Function(BuildContext, EmailTemplate, String, String) onSendPressed;
|
||||||
|
|
||||||
EmailInvoiceVM({
|
EmailEntityVM({
|
||||||
@required this.isLoading,
|
@required this.isLoading,
|
||||||
@required this.isSaving,
|
@required this.isSaving,
|
||||||
@required this.company,
|
@required this.company,
|
||||||
|
|
@ -57,6 +57,25 @@ class EmailInvoiceVM {
|
||||||
@required this.client,
|
@required this.client,
|
||||||
@required this.onSendPressed,
|
@required this.onSendPressed,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmailInvoiceVM extends EmailEntityVM {
|
||||||
|
|
||||||
|
EmailInvoiceVM({
|
||||||
|
bool isLoading,
|
||||||
|
bool isSaving,
|
||||||
|
CompanyEntity company,
|
||||||
|
InvoiceEntity invoice,
|
||||||
|
ClientEntity client,
|
||||||
|
Function(BuildContext, EmailTemplate, String, String) onSendPressed,
|
||||||
|
}): super(
|
||||||
|
isLoading: isLoading,
|
||||||
|
isSaving: isSaving,
|
||||||
|
company: company,
|
||||||
|
invoice: invoice,
|
||||||
|
client: client,
|
||||||
|
onSendPressed: onSendPressed,
|
||||||
|
);
|
||||||
|
|
||||||
factory EmailInvoiceVM.fromStore(
|
factory EmailInvoiceVM.fromStore(
|
||||||
Store<AppState> store, InvoiceEntity invoice) {
|
Store<AppState> store, InvoiceEntity invoice) {
|
||||||
|
|
@ -9,7 +9,6 @@ import 'package:invoiceninja_flutter/data/models/models.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/icon_message.dart';
|
import 'package:invoiceninja_flutter/ui/app/icon_message.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_item_view.dart';
|
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_item_view.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/two_value_header.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue