import 'package:flutter/material.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_middleware.dart'; import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; import 'package:invoiceninja_flutter/redux/project/project_actions.dart'; import 'package:invoiceninja_flutter/redux/credit/credit_actions.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; import 'package:invoiceninja_flutter/ui/credit/edit/credit_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/credit/credit_email_vm.dart'; import 'package:invoiceninja_flutter/ui/credit/credit_screen.dart'; import 'package:invoiceninja_flutter/ui/credit/view/credit_view_vm.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/data/repositories/credit_repository.dart'; List> createStoreCreditsMiddleware([ CreditRepository repository = const CreditRepository(), ]) { final viewCreditList = _viewCreditList(); final viewCredit = _viewCredit(); final editCredit = _editCredit(); final showEmailCredit = _showEmailCredit(); final loadCredits = _loadCredits(repository); final loadCredit = _loadCredit(repository); final saveCredit = _saveCredit(repository); final archiveCredit = _archiveCredit(repository); final deleteCredit = _deleteCredit(repository); final restoreCredit = _restoreCredit(repository); final emailCredit = _emailCredit(repository); final markSentCredit = _markSentCredit(repository); return [ TypedMiddleware(viewCreditList), TypedMiddleware(viewCredit), TypedMiddleware(editCredit), TypedMiddleware(showEmailCredit), TypedMiddleware(loadCredits), TypedMiddleware(loadCredit), TypedMiddleware(saveCredit), TypedMiddleware(archiveCredit), TypedMiddleware(deleteCredit), TypedMiddleware(restoreCredit), TypedMiddleware(emailCredit), TypedMiddleware(markSentCredit), ]; } Middleware _viewCredit() { return (Store store, dynamic dynamicAction, NextDispatcher next) async { final action = dynamicAction as ViewCredit; if (!action.force && hasChanges(store: store, context: action.context, action: action)) { return; } next(action); store.dispatch(UpdateCurrentRoute(CreditViewScreen.route)); if (isMobile(action.context)) { await action.navigator.pushNamed(CreditViewScreen.route); } }; } Middleware _viewCreditList() { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as ViewCreditList; if (!action.force && hasChanges(store: store, context: action.context, action: action)) { return; } next(action); if (store.state.staticState.isStale) { store.dispatch(RefreshData()); } else if (store.state.creditState.isStale) { store.dispatch(LoadCredits()); } store.dispatch(UpdateCurrentRoute(CreditScreen.route)); if (isMobile(action.context)) { action.navigator.pushNamedAndRemoveUntil( CreditScreen.route, (Route route) => false); } }; } Middleware _editCredit() { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as EditCredit; if (!action.force && hasChanges(store: store, context: action.context, action: action)) { return; } next(action); store.dispatch(UpdateCurrentRoute(CreditEditScreen.route)); if (isMobile(action.context)) { action.navigator.pushNamed(CreditEditScreen.route); } }; } Middleware _showEmailCredit() { return (Store store, dynamic dynamicAction, NextDispatcher next) async { final action = dynamicAction as ShowEmailCredit; next(action); store.dispatch(UpdateCurrentRoute(CreditEmailScreen.route)); if (isMobile(action.context)) { final emailWasSent = await Navigator.of(action.context).pushNamed(CreditEmailScreen.route); if (action.completer != null && emailWasSent != null && emailWasSent) { action.completer.complete(null); } } }; } Middleware _archiveCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as ArchiveCreditsRequest; final prevCredits = action.creditIds.map((id) => store.state.creditState.map[id]).toList(); repository .bulkAction( store.state.credentials, action.creditIds, EntityAction.archive) .then((List credits) { store.dispatch(ArchiveCreditsSuccess(credits)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(ArchiveCreditsFailure(prevCredits)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _deleteCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as DeleteCreditsRequest; final prevCredits = action.creditIds.map((id) => store.state.creditState.map[id]).toList(); repository .bulkAction( store.state.credentials, action.creditIds, EntityAction.delete) .then((List credits) { store.dispatch(DeleteCreditsSuccess(credits)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(DeleteCreditsFailure(prevCredits)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _restoreCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as RestoreCreditsRequest; final prevCredits = action.creditIds.map((id) => store.state.creditState.map[id]).toList(); repository .bulkAction( store.state.credentials, action.creditIds, EntityAction.restore) .then((List credits) { store.dispatch(RestoreCreditsSuccess(credits)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(RestoreCreditsFailure(prevCredits)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _markSentCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as MarkSentCreditRequest; repository .bulkAction( store.state.credentials, action.creditIds, EntityAction.markSent) .then((credits) { store.dispatch(MarkSentCreditSuccess(credits)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(MarkSentCreditFailure(error)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _emailCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as EmailCreditRequest; final origCredit = store.state.creditState.map[action.creditId]; repository .emailCredit(store.state.credentials, origCredit, action.template, action.subject, action.body) .then((void _) { store.dispatch(EmailCreditSuccess()); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(EmailCreditFailure(error)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _saveCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as SaveCreditRequest; // remove any empty line items final updatedCredit = action.credit.rebuild((b) => b ..lineItems .replace(action.credit.lineItems.where((item) => !item.isEmpty))); repository .saveData(store.state.credentials, updatedCredit) .then((InvoiceEntity credit) { if (action.credit.isNew) { store.dispatch(AddCreditSuccess(credit)); } else { store.dispatch(SaveCreditSuccess(credit)); } action.completer.complete(credit); }).catchError((Object error) { print(error); store.dispatch(SaveCreditFailure(error)); action.completer.completeError(error); }); next(action); }; } Middleware _loadCredit(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as LoadCredit; final AppState state = store.state; if (state.isLoading) { next(action); return; } store.dispatch(LoadCreditRequest()); repository .loadItem(store.state.credentials, action.creditId) .then((credit) { store.dispatch(LoadCreditSuccess(credit)); if (action.completer != null) { action.completer.complete(null); } if (state.projectState.isStale) { store.dispatch(LoadProjects()); } }).catchError((Object error) { print(error); store.dispatch(LoadCreditFailure(error)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _loadCredits(CreditRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as LoadCredits; final AppState state = store.state; if (!state.creditState.isStale && !action.force) { next(action); return; } if (state.isLoading) { next(action); return; } final int updatedAt = (state.creditState.lastUpdated / 1000).round(); store.dispatch(LoadCreditsRequest()); repository.loadList(store.state.credentials, updatedAt).then((data) { store.dispatch(LoadCreditsSuccess(data)); if (action.completer != null) { action.completer.complete(null); } if (state.clientState.isStale) { store.dispatch(LoadClients()); } }).catchError((Object error) { print(error); store.dispatch(LoadCreditsFailure(error)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; }