From ddcdcbb02ee4cfb60280f47d916d51e09af639fa Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 10:20:01 +0100 Subject: [PATCH 01/31] [#175266374] add navigation and bpddetail screen --- .../bonus/bpd/navigation/action/bpdTestNav.ts | 8 ---- .../bonus/bpd/navigation/action/iban.ts | 7 ---- .../{action/onboarding.ts => actions.ts} | 21 ++++++++++- ts/features/bonus/bpd/navigation/navigator.ts | 4 ++ ts/features/bonus/bpd/navigation/routes.ts | 1 + .../bpd/saga/orchestration/insertIban.ts | 4 +- .../orchestration/onboarding/enrollToBpd.ts | 3 +- .../onboarding/startOnboarding.ts | 2 +- .../bpd/screens/details/BpdDetailsScreen.tsx | 37 +++++++++++++++++++ .../bonus/bpd/screens/details/placeholder.txt | 0 10 files changed, 66 insertions(+), 21 deletions(-) delete mode 100644 ts/features/bonus/bpd/navigation/action/bpdTestNav.ts delete mode 100644 ts/features/bonus/bpd/navigation/action/iban.ts rename ts/features/bonus/bpd/navigation/{action/onboarding.ts => actions.ts} (67%) create mode 100644 ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx delete mode 100644 ts/features/bonus/bpd/screens/details/placeholder.txt diff --git a/ts/features/bonus/bpd/navigation/action/bpdTestNav.ts b/ts/features/bonus/bpd/navigation/action/bpdTestNav.ts deleted file mode 100644 index 5b3cdaec5cd..00000000000 --- a/ts/features/bonus/bpd/navigation/action/bpdTestNav.ts +++ /dev/null @@ -1,8 +0,0 @@ -// TODO: remove after the introduction of the bpd detail screen -import { NavigationActions } from "react-navigation"; -import BPD_ROUTES from "../routes"; - -export const navigateToBpdTestScreen = () => - NavigationActions.navigate({ - routeName: BPD_ROUTES.TEST - }); diff --git a/ts/features/bonus/bpd/navigation/action/iban.ts b/ts/features/bonus/bpd/navigation/action/iban.ts deleted file mode 100644 index f2d94996987..00000000000 --- a/ts/features/bonus/bpd/navigation/action/iban.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { NavigationActions } from "react-navigation"; -import BPD_ROUTES from "../routes"; - -export const navigateToBpdIbanInsertion = () => - NavigationActions.navigate({ - routeName: BPD_ROUTES.IBAN - }); diff --git a/ts/features/bonus/bpd/navigation/action/onboarding.ts b/ts/features/bonus/bpd/navigation/actions.ts similarity index 67% rename from ts/features/bonus/bpd/navigation/action/onboarding.ts rename to ts/features/bonus/bpd/navigation/actions.ts index 91c3fc29aef..a9a55674874 100644 --- a/ts/features/bonus/bpd/navigation/action/onboarding.ts +++ b/ts/features/bonus/bpd/navigation/actions.ts @@ -1,5 +1,5 @@ import { NavigationActions } from "react-navigation"; -import BPD_ROUTES from "../routes"; +import BPD_ROUTES from "./routes"; export const navigateToBpdOnboardingLoadActivationStatus = () => NavigationActions.navigate({ @@ -30,3 +30,22 @@ export const navigateToBpdOnboardingNoPaymentMethods = () => NavigationActions.navigate({ routeName: BPD_ROUTES.ONBOARDING.NO_PAYMENT_METHODS }); + +// IBAN +export const navigateToBpdIbanInsertion = () => + NavigationActions.navigate({ + routeName: BPD_ROUTES.IBAN + }); + +// TODO: remove after the introduction of the bpd detail screen +export const navigateToBpdTestScreen = () => + NavigationActions.navigate({ + routeName: BPD_ROUTES.TEST + }); + +// Details + +export const navigateToBpdDetails = () => + NavigationActions.navigate({ + routeName: BPD_ROUTES.DETAILS + }); diff --git a/ts/features/bonus/bpd/navigation/navigator.ts b/ts/features/bonus/bpd/navigation/navigator.ts index 8435bb81837..70721877a68 100644 --- a/ts/features/bonus/bpd/navigation/navigator.ts +++ b/ts/features/bonus/bpd/navigation/navigator.ts @@ -1,4 +1,5 @@ import { createStackNavigator } from "react-navigation"; +import BpdDetailsScreen from "../screens/details/BpdDetailsScreen"; import MainIbanScreen from "../screens/iban/MainIbanScreen"; import BpdInformationScreen from "../screens/onboarding/BpdInformationScreen"; import DeclarationScreen from "../screens/onboarding/declaration/DeclarationScreen"; @@ -32,6 +33,9 @@ const BpdNavigator = createStackNavigator( [BPD_ROUTES.IBAN]: { screen: MainIbanScreen }, + [BPD_ROUTES.DETAILS]: { + screen: BpdDetailsScreen + }, // TODO: remove after the introduction of the bpd detail screen [BPD_ROUTES.TEST]: { screen: TMPBpdScreen diff --git a/ts/features/bonus/bpd/navigation/routes.ts b/ts/features/bonus/bpd/navigation/routes.ts index f2992d3634a..66c16111f80 100644 --- a/ts/features/bonus/bpd/navigation/routes.ts +++ b/ts/features/bonus/bpd/navigation/routes.ts @@ -10,6 +10,7 @@ const BPD_ROUTES = { NO_PAYMENT_METHODS: "BPD_NO_PAYMENT_METHODS" }, IBAN: "BPD_IBAN", + DETAILS: "BPD_DETAILS", // TODO: remove after the introduction of the bpd detail screen TEST: "BPD_TEST" }; diff --git a/ts/features/bonus/bpd/saga/orchestration/insertIban.ts b/ts/features/bonus/bpd/saga/orchestration/insertIban.ts index 203491aa798..d285146131a 100644 --- a/ts/features/bonus/bpd/saga/orchestration/insertIban.ts +++ b/ts/features/bonus/bpd/saga/orchestration/insertIban.ts @@ -6,11 +6,11 @@ import { ActionType, getType, isActionOf } from "typesafe-actions"; import { navigationHistoryPop } from "../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../store/reducers/navigation"; import { walletsSelector } from "../../../../../store/reducers/wallet/wallets"; -import { navigateToBpdIbanInsertion } from "../../navigation/action/iban"; import { + navigateToBpdIbanInsertion, navigateToBpdOnboardingEnrollPaymentMethod, navigateToBpdOnboardingNoPaymentMethods -} from "../../navigation/action/onboarding"; +} from "../../navigation/actions"; import BPD_ROUTES from "../../navigation/routes"; import { bpdIbanInsertionCancel, diff --git a/ts/features/bonus/bpd/saga/orchestration/onboarding/enrollToBpd.ts b/ts/features/bonus/bpd/saga/orchestration/onboarding/enrollToBpd.ts index 6ebb09095bd..71c8d31dc39 100644 --- a/ts/features/bonus/bpd/saga/orchestration/onboarding/enrollToBpd.ts +++ b/ts/features/bonus/bpd/saga/orchestration/onboarding/enrollToBpd.ts @@ -4,7 +4,7 @@ import { call, put, race, select, take } from "redux-saga/effects"; import { ActionType } from "typesafe-actions"; import { navigationHistoryPop } from "../../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../../store/reducers/navigation"; -import { navigateToBpdOnboardingLoadActivate } from "../../../navigation/action/onboarding"; +import { navigateToBpdOnboardingLoadActivate } from "../../../navigation/actions"; import BPD_ROUTES from "../../../navigation/routes"; import { bpdIbanInsertionStart } from "../../../store/actions/iban"; import { @@ -34,7 +34,6 @@ function* enrollToBpdWorker() { ); if (enrollResult.payload.enabled) { - yield put(bpdIbanInsertionStart()); yield put(navigationHistoryPop(1)); } diff --git a/ts/features/bonus/bpd/saga/orchestration/onboarding/startOnboarding.ts b/ts/features/bonus/bpd/saga/orchestration/onboarding/startOnboarding.ts index cc5142eb3ae..b90f318fbf6 100644 --- a/ts/features/bonus/bpd/saga/orchestration/onboarding/startOnboarding.ts +++ b/ts/features/bonus/bpd/saga/orchestration/onboarding/startOnboarding.ts @@ -21,7 +21,7 @@ import { navigateToBpdOnboardingDeclaration, navigateToBpdOnboardingInformationTos, navigateToBpdOnboardingLoadActivationStatus -} from "../../../navigation/action/onboarding"; +} from "../../../navigation/actions"; import BPD_ROUTES from "../../../navigation/routes"; import { bpdLoadActivationStatus } from "../../../store/actions/details"; import { diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx new file mode 100644 index 00000000000..9377bcfc77e --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -0,0 +1,37 @@ +import * as React from "react"; +import { StyleSheet, View } from "react-native"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { H1 } from "../../../../../components/core/typography/H1"; +import DarkLayout from "../../../../../components/screens/DarkLayout"; +import I18n from "../../../../../i18n"; +import { GlobalState } from "../../../../../store/reducers/types"; + +export type Props = ReturnType & + ReturnType; + +const styles = StyleSheet.create({ + headerSpacer: { + height: 172 + } +}); + +const BpdDetailsScreen: React.FunctionComponent = () => ( + } + gradientHeader={true} + hideHeader={true} + > +

Ciao

+
+); + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(BpdDetailsScreen); diff --git a/ts/features/bonus/bpd/screens/details/placeholder.txt b/ts/features/bonus/bpd/screens/details/placeholder.txt deleted file mode 100644 index e69de29bb2d..00000000000 From 701eea7abd8924f61423505f176a05f7d1041613 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 11:26:30 +0100 Subject: [PATCH 02/31] [#175266374] stub for BpdPeriodSelector and BpdPeriodDetails --- locales/en/index.yml | 1 + locales/it/index.yml | 1 + .../bpd/screens/details/BpdDetailsScreen.tsx | 27 +++++++++++--- .../bpd/screens/details/BpdPeriodDetail.tsx | 27 ++++++++++++++ .../bpd/screens/details/BpdPeriodSelector.tsx | 36 +++++++++++++++++++ 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx create mode 100644 ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 6a930521a46..76536171db4 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1590,6 +1590,7 @@ bonus: content: !include bonus/bonusVacanze/bonus_tos.md bpd: title: Cashback Digital Payments + name: Cashback onboarding: loadingActivationStatus: title: Loading activation status diff --git a/locales/it/index.yml b/locales/it/index.yml index 1205696a935..0c591bf0aba 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1622,6 +1622,7 @@ bonus: content: !include bonus/bonusVacanze/bonus_tos.md bpd: title: Cashback Pagamenti Digitali + name: Cashback onboarding: loadingActivationStatus: title: Verifico lo stato di attivazione diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index 9377bcfc77e..9ea671c28e2 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -2,10 +2,11 @@ import * as React from "react"; import { StyleSheet, View } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; -import { H1 } from "../../../../../components/core/typography/H1"; import DarkLayout from "../../../../../components/screens/DarkLayout"; import I18n from "../../../../../i18n"; import { GlobalState } from "../../../../../store/reducers/types"; +import BpdPeriodDetail from "./BpdPeriodDetail"; +import BpdPeriodSelector from "./BpdPeriodSelector"; export type Props = ReturnType & ReturnType; @@ -13,20 +14,38 @@ export type Props = ReturnType & const styles = StyleSheet.create({ headerSpacer: { height: 172 + }, + selector: { + height: 192 + 10 + 16 + 16, + width: "100%", + position: "absolute", + top: 16, + zIndex: 7, + elevation: 7 + }, + selectorSpacer: { + height: 60 } }); - +/** + * The screen that allows the user to see all the details related to the bpd. + * @constructor + */ const BpdDetailsScreen: React.FunctionComponent = () => ( } gradientHeader={true} hideHeader={true} > -

Ciao

+ + + + +
); diff --git a/ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx b/ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx new file mode 100644 index 00000000000..a4fbe216ef7 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx @@ -0,0 +1,27 @@ +import { View } from "native-base"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { IOStyles } from "../../../../../components/core/variables/IOStyles"; +import { GlobalState } from "../../../../../store/reducers/types"; +import { H1 } from "../../../../../components/core/typography/H1"; + +export type Props = ReturnType & + ReturnType; + +/** + * The body and details for a specific cashback period. Will change if is Active, Inactive or Close + * @constructor + */ +const BpdPeriodDetail: React.FunctionComponent = () => ( + + {/* {TODO: will choose the right representation (different components) based on the period} */} +

Period details Placeholder!

+
+); + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(BpdPeriodDetail); diff --git a/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx b/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx new file mode 100644 index 00000000000..5d008045523 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx @@ -0,0 +1,36 @@ +import { View } from "native-base"; +import * as React from "react"; +import { StyleSheet } from "react-native"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { GlobalState } from "../../../../../store/reducers/types"; +import { H1 } from "../../../../../components/core/typography/H1"; + +export type Props = ReturnType & + ReturnType; + +const styles = StyleSheet.create({ + main: { + backgroundColor: "#AAFFFF66", + flex: 1, + alignItems: "center", + justifyContent: "center" + } +}); + +/** + * An horizontal snap scroll view used to select a specific period of bpd. + * Each period is represented as a BpdPeriodCard + * @constructor + */ +const BpdPeriodSelector: React.FunctionComponent = () => ( + +

Period selector placeholder!

+
+); + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(BpdPeriodSelector); From ae34d0c21b93bf2e07e3cb764f8087fc75000cf4 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 12:57:58 +0100 Subject: [PATCH 03/31] [#175266374] add different periods component and current period selector --- .../bpd/screens/details/BpdDetailsScreen.tsx | 2 +- .../details/periods/BpdActivePeriod.tsx | 20 +++++++++++++ .../details/periods/BpdClosedPeriod.tsx | 20 +++++++++++++ .../details/periods/BpdInactivePeriod.tsx | 20 +++++++++++++ .../details/{ => periods}/BpdPeriodDetail.tsx | 13 ++++---- ts/features/bonus/bpd/store/actions/index.ts | 8 +++-- .../bonus/bpd/store/actions/paymentMethods.ts | 2 +- .../bonus/bpd/store/actions/selectedPeriod.ts | 11 +++++++ .../bpd/store/reducers/details/amounts.ts | 16 ++++++++++ .../bonus/bpd/store/reducers/details/index.ts | 6 +++- .../store/reducers/details/selectedPeriod.ts | 30 +++++++++++++++++++ .../store/reducers/details/transactions.ts | 16 ++++++++++ 12 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx create mode 100644 ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx create mode 100644 ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx rename ts/features/bonus/bpd/screens/details/{ => periods}/BpdPeriodDetail.tsx (60%) create mode 100644 ts/features/bonus/bpd/store/actions/selectedPeriod.ts create mode 100644 ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index 9ea671c28e2..b46895c6f12 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -5,7 +5,7 @@ import { Dispatch } from "redux"; import DarkLayout from "../../../../../components/screens/DarkLayout"; import I18n from "../../../../../i18n"; import { GlobalState } from "../../../../../store/reducers/types"; -import BpdPeriodDetail from "./BpdPeriodDetail"; +import BpdPeriodDetail from "./periods/BpdPeriodDetail"; import BpdPeriodSelector from "./BpdPeriodSelector"; export type Props = ReturnType & diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx new file mode 100644 index 00000000000..7f25e666c2f --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx @@ -0,0 +1,20 @@ +import { View } from "native-base"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { GlobalState } from "../../../../../../store/reducers/types"; + +export type Props = ReturnType & + ReturnType; + +/** + * Render the details for a current active cashback period + * @constructor + */ +const BpdActivePeriod: React.FunctionComponent = () => ; + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(BpdActivePeriod); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx new file mode 100644 index 00000000000..d5a91b12032 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx @@ -0,0 +1,20 @@ +import { View } from "native-base"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { GlobalState } from "../../../../../../store/reducers/types"; + +export type Props = ReturnType & + ReturnType; + +/** + * Render the details for a completed and closed cashback periods + * @constructor + */ +const BpdClosedPeriod: React.FunctionComponent = () => ; + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(BpdClosedPeriod); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx new file mode 100644 index 00000000000..062aa049337 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx @@ -0,0 +1,20 @@ +import { View } from "native-base"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { GlobalState } from "../../../../../../store/reducers/types"; + +export type Props = ReturnType & + ReturnType; + +/** + * Render the details for a future cashback period + * @constructor + */ +const BpdInactivePeriod: React.FunctionComponent = () => ; + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(BpdInactivePeriod); diff --git a/ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx similarity index 60% rename from ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx rename to ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx index a4fbe216ef7..65711e236d2 100644 --- a/ts/features/bonus/bpd/screens/details/BpdPeriodDetail.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx @@ -2,15 +2,16 @@ import { View } from "native-base"; import * as React from "react"; import { connect } from "react-redux"; import { Dispatch } from "redux"; -import { IOStyles } from "../../../../../components/core/variables/IOStyles"; -import { GlobalState } from "../../../../../store/reducers/types"; -import { H1 } from "../../../../../components/core/typography/H1"; +import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; +import { GlobalState } from "../../../../../../store/reducers/types"; +import { H1 } from "../../../../../../components/core/typography/H1"; +import { bpdSelectedPeriodSelector } from "../../../store/reducers/details/selectedPeriod"; export type Props = ReturnType & ReturnType; /** - * The body and details for a specific cashback period. Will change if is Active, Inactive or Close + * The body and details for a specific cashback period. Will change if is Active, Inactive or Closed * @constructor */ const BpdPeriodDetail: React.FunctionComponent = () => ( @@ -22,6 +23,8 @@ const BpdPeriodDetail: React.FunctionComponent = () => ( const mapDispatchToProps = (_: Dispatch) => ({}); -const mapStateToProps = (_: GlobalState) => ({}); +const mapStateToProps = (state: GlobalState) => ({ + selectedPeriod: bpdSelectedPeriodSelector(state) +}); export default connect(mapStateToProps, mapDispatchToProps)(BpdPeriodDetail); diff --git a/ts/features/bonus/bpd/store/actions/index.ts b/ts/features/bonus/bpd/store/actions/index.ts index 76111823646..16ec949ef80 100644 --- a/ts/features/bonus/bpd/store/actions/index.ts +++ b/ts/features/bonus/bpd/store/actions/index.ts @@ -2,15 +2,17 @@ import { BpdAmountAction } from "./amount"; import { BpdDetailsActions } from "./details"; import { BpdIbanActions } from "./iban"; import { BpdOnboardingActions } from "./onboarding"; -import { BpdPaymentMethod } from "./paymentMethods"; +import { BpdPaymentMethodActions } from "./paymentMethods"; import { BpdPeriodsAction } from "./periods"; +import { BpdSelectPeriodAction } from "./selectedPeriod"; import { BpdTransactionsAction } from "./transactions"; export type BpdActions = | BpdOnboardingActions | BpdDetailsActions | BpdIbanActions - | BpdPaymentMethod + | BpdPaymentMethodActions | BpdPeriodsAction | BpdAmountAction - | BpdTransactionsAction; + | BpdTransactionsAction + | BpdSelectPeriodAction; diff --git a/ts/features/bonus/bpd/store/actions/paymentMethods.ts b/ts/features/bonus/bpd/store/actions/paymentMethods.ts index 0277c2befd6..c8d68583403 100644 --- a/ts/features/bonus/bpd/store/actions/paymentMethods.ts +++ b/ts/features/bonus/bpd/store/actions/paymentMethods.ts @@ -60,6 +60,6 @@ export const bpdUpdatePaymentMethodActivation = createAsyncAction( BpdPaymentMethodFailure >(); -export type BpdPaymentMethod = +export type BpdPaymentMethodActions = | ActionType | ActionType; diff --git a/ts/features/bonus/bpd/store/actions/selectedPeriod.ts b/ts/features/bonus/bpd/store/actions/selectedPeriod.ts new file mode 100644 index 00000000000..4a5258617ca --- /dev/null +++ b/ts/features/bonus/bpd/store/actions/selectedPeriod.ts @@ -0,0 +1,11 @@ +import { ActionType, createStandardAction } from "typesafe-actions"; +import { BpdPeriod } from "./periods"; + +/** + * Request the period list + */ +export const bpdSelectPeriod = createStandardAction("BPD_SELECT_PERIOD")< + BpdPeriod +>(); + +export type BpdSelectPeriodAction = ActionType; diff --git a/ts/features/bonus/bpd/store/reducers/details/amounts.ts b/ts/features/bonus/bpd/store/reducers/details/amounts.ts index fcb34c0d9f4..5571e8de13d 100644 --- a/ts/features/bonus/bpd/store/reducers/details/amounts.ts +++ b/ts/features/bonus/bpd/store/reducers/details/amounts.ts @@ -1,3 +1,4 @@ +import { fromNullable } from "fp-ts/lib/Option"; import * as pot from "italia-ts-commons/lib/pot"; import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; @@ -11,6 +12,7 @@ import { import { GlobalState } from "../../../../../../store/reducers/types"; import { BpdAmount, bpdAmountLoad } from "../../actions/amount"; import { AwardPeriodId } from "../../actions/periods"; +import { bpdSelectedPeriodSelector } from "./selectedPeriod"; /** * Store the amounts (cashback and transaction count) foreach period @@ -51,3 +53,17 @@ export const bpdAmountSelector = createSelector( [bpdAmountByPeriodSelector], maybePotAmount => maybePotAmount ?? pot.none ); + +/** + * Return the BpdAmount for the selected period (current displayed) + */ +export const bpdAmountForSelectedPeriod = createSelector( + [ + (state: GlobalState) => state.bonus.bpd.details.amounts, + bpdSelectedPeriodSelector + ], + (amounts, period) => + fromNullable(period) + .map(p => amounts[p.awardPeriodId]) + .getOrElse(pot.none) +); diff --git a/ts/features/bonus/bpd/store/reducers/details/index.ts b/ts/features/bonus/bpd/store/reducers/details/index.ts index ec23db1c6d3..11503ac49a2 100644 --- a/ts/features/bonus/bpd/store/reducers/details/index.ts +++ b/ts/features/bonus/bpd/store/reducers/details/index.ts @@ -2,7 +2,7 @@ import * as pot from "italia-ts-commons/lib/pot"; import { Action, combineReducers } from "redux"; import { IndexedById } from "../../../../../../store/helpers/indexer"; import { BpdAmount } from "../../actions/amount"; -import { BpdPeriod } from "../../actions/periods"; +import { AwardPeriodId, BpdPeriod } from "../../actions/periods"; import { BpdTransaction } from "../../actions/transactions"; import bpdActivationReducer, { BpdActivation } from "./activation"; import { bpdAmountsReducer } from "./amounts"; @@ -11,12 +11,14 @@ import { BpdPotPaymentMethodActivation } from "./paymentMethods"; import { bpdPeriodsReducer } from "./periods"; +import { bpdSelectedPeriodsReducer } from "./selectedPeriod"; import { bpdTransactionsReducer } from "./transactions"; export type BpdDetailsState = { activation: BpdActivation; paymentMethods: IndexedById; periods: pot.Pot, Error>; + selectedPeriod: BpdPeriod | null; amounts: IndexedById>; transactions: IndexedById, Error>>; }; @@ -28,6 +30,8 @@ const bpdDetailsReducer = combineReducers({ paymentMethods: bpdPaymentMethodsReducer, // All the periods of the cashback periods: bpdPeriodsReducer, + // the current period displayed, selected by the user + selectedPeriod: bpdSelectedPeriodsReducer, // The amounts (transactions and amount) foreach cashback period amounts: bpdAmountsReducer, transactions: bpdTransactionsReducer diff --git a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts new file mode 100644 index 00000000000..afc800081cb --- /dev/null +++ b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts @@ -0,0 +1,30 @@ +import { createSelector } from "reselect"; +import { getType } from "typesafe-actions"; +import { Action } from "../../../../../../store/actions/types"; +import { GlobalState } from "../../../../../../store/reducers/types"; +import { BpdPeriod } from "../../actions/periods"; +import { bpdSelectPeriod } from "../../actions/selectedPeriod"; + +/** + * Store the current period selected by the user (current displayed) + * @param state + * @param action + */ +export const bpdSelectedPeriodsReducer = ( + state: BpdPeriod | null = null, + action: Action +): BpdPeriod | null => { + switch (action.type) { + case getType(bpdSelectPeriod): + return action.payload; + } + return state; +}; + +/** + * Return current period selected by the user (current displayed) + */ +export const bpdSelectedPeriodSelector = createSelector( + [(state: GlobalState) => state.bonus.bpd.details.selectedPeriod], + period => (period === null ? undefined : period) +); diff --git a/ts/features/bonus/bpd/store/reducers/details/transactions.ts b/ts/features/bonus/bpd/store/reducers/details/transactions.ts index a34c98b5233..0ca267ea2fa 100644 --- a/ts/features/bonus/bpd/store/reducers/details/transactions.ts +++ b/ts/features/bonus/bpd/store/reducers/details/transactions.ts @@ -1,3 +1,4 @@ +import { fromNullable, none } from "fp-ts/lib/Option"; import * as pot from "italia-ts-commons/lib/pot"; import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; @@ -14,6 +15,7 @@ import { BpdTransaction, bpdTransactionsLoad } from "../../actions/transactions"; +import { bpdSelectedPeriodSelector } from "./selectedPeriod"; /** * Store the transactions foreach period @@ -58,3 +60,17 @@ export const bpdTransactionsSelector = createSelector( [bpdTransactionsByPeriodSelector], maybePotTransactions => maybePotTransactions ?? pot.none ); + +/** + * Return the list of transactions for the selected period (current displayed) + */ +export const bpdTransactionsForSelectedPeriod = createSelector( + [ + (state: GlobalState) => state.bonus.bpd.details.transactions, + bpdSelectedPeriodSelector + ], + (transactions, period) => + fromNullable(period) + .map(p => transactions[p.awardPeriodId]) + .getOrElse(pot.none) +); From 869a0a8e60340962a40356d8833b09300c498c12 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 13:15:13 +0100 Subject: [PATCH 04/31] [#175266374] convert AwardPeriodId to number --- ts/features/bonus/bpd/saga/networking/periods.ts | 2 +- ts/features/bonus/bpd/store/actions/periods.ts | 2 +- ts/features/bonus/bpd/store/reducers/details/index.ts | 2 +- .../bonus/bpd/store/reducers/details/transactions.ts | 2 +- ts/screens/wallet/WalletHomeScreen.tsx | 2 +- ts/store/reducers/IndexedByIdPot.ts | 10 +++++----- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ts/features/bonus/bpd/saga/networking/periods.ts b/ts/features/bonus/bpd/saga/networking/periods.ts index aeae53040e0..13086222c34 100644 --- a/ts/features/bonus/bpd/saga/networking/periods.ts +++ b/ts/features/bonus/bpd/saga/networking/periods.ts @@ -28,7 +28,7 @@ const convertPeriod = ( statusFallback: BpdPeriodStatus = "Inactive" ): BpdPeriod => ({ ...networkPeriod, - awardPeriodId: networkPeriod.awardPeriodId.toString() as AwardPeriodId, + awardPeriodId: networkPeriod.awardPeriodId as AwardPeriodId, superCashbackAmount: 0, // this field isn't yet present in AwardPeriodResource status: fromNullable(periodStatusMap.get(networkPeriod.status)).getOrElse( statusFallback diff --git a/ts/features/bonus/bpd/store/actions/periods.ts b/ts/features/bonus/bpd/store/actions/periods.ts index 257057beedf..c53642c46f6 100644 --- a/ts/features/bonus/bpd/store/actions/periods.ts +++ b/ts/features/bonus/bpd/store/actions/periods.ts @@ -1,7 +1,7 @@ import { IUnitTag } from "italia-ts-commons/lib/units"; import { ActionType, createAsyncAction } from "typesafe-actions"; -export type AwardPeriodId = string & IUnitTag<"AwardPeriodId">; +export type AwardPeriodId = number & IUnitTag<"AwardPeriodId">; /** * The possible state for a period: diff --git a/ts/features/bonus/bpd/store/reducers/details/index.ts b/ts/features/bonus/bpd/store/reducers/details/index.ts index 11503ac49a2..368dc938c13 100644 --- a/ts/features/bonus/bpd/store/reducers/details/index.ts +++ b/ts/features/bonus/bpd/store/reducers/details/index.ts @@ -2,7 +2,7 @@ import * as pot from "italia-ts-commons/lib/pot"; import { Action, combineReducers } from "redux"; import { IndexedById } from "../../../../../../store/helpers/indexer"; import { BpdAmount } from "../../actions/amount"; -import { AwardPeriodId, BpdPeriod } from "../../actions/periods"; +import { BpdPeriod } from "../../actions/periods"; import { BpdTransaction } from "../../actions/transactions"; import bpdActivationReducer, { BpdActivation } from "./activation"; import { bpdAmountsReducer } from "./amounts"; diff --git a/ts/features/bonus/bpd/store/reducers/details/transactions.ts b/ts/features/bonus/bpd/store/reducers/details/transactions.ts index 0ca267ea2fa..d4cb0599d70 100644 --- a/ts/features/bonus/bpd/store/reducers/details/transactions.ts +++ b/ts/features/bonus/bpd/store/reducers/details/transactions.ts @@ -1,4 +1,4 @@ -import { fromNullable, none } from "fp-ts/lib/Option"; +import { fromNullable } from "fp-ts/lib/Option"; import * as pot from "italia-ts-commons/lib/pot"; import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; diff --git a/ts/screens/wallet/WalletHomeScreen.tsx b/ts/screens/wallet/WalletHomeScreen.tsx index 832a0f2b49a..26a359a5911 100644 --- a/ts/screens/wallet/WalletHomeScreen.tsx +++ b/ts/screens/wallet/WalletHomeScreen.tsx @@ -36,7 +36,7 @@ import { } from "../../features/bonus/bonusVacanze/store/actions/bonusVacanze"; import { allBonusActiveSelector } from "../../features/bonus/bonusVacanze/store/reducers/allActive"; import { availableBonusTypesSelector } from "../../features/bonus/bonusVacanze/store/reducers/availableBonusesTypes"; -import { navigateToBpdTestScreen } from "../../features/bonus/bpd/navigation/action/bpdTestNav"; +import { navigateToBpdTestScreen } from "../../features/bonus/bpd/navigation/actions"; import I18n from "../../i18n"; import { navigateBack, diff --git a/ts/store/reducers/IndexedByIdPot.ts b/ts/store/reducers/IndexedByIdPot.ts index 706bcfed1d6..8f16fc0e9fd 100644 --- a/ts/store/reducers/IndexedByIdPot.ts +++ b/ts/store/reducers/IndexedByIdPot.ts @@ -12,7 +12,7 @@ import { IndexedById } from "../helpers/indexer"; * @param data */ export const readPot = ( - id: string, + id: string | number, data: IndexedById> ): pot.Pot => fromNullable(data[id]).getOrElse(pot.none); @@ -22,7 +22,7 @@ export const readPot = ( * @param data */ export const toLoading = ( - id: string, + id: string | number, data: IndexedById> ): IndexedById> => ({ ...data, @@ -36,7 +36,7 @@ export const toLoading = ( * @param value */ export const toSome = ( - id: string, + id: string | number, data: IndexedById>, value: T ): IndexedById> => ({ @@ -51,7 +51,7 @@ export const toSome = ( * @param value */ export const toError = ( - id: string, + id: string | number, data: IndexedById>, value: E ): IndexedById> => ({ @@ -66,7 +66,7 @@ export const toError = ( * @param value */ export const toUpdating = ( - id: string, + id: string | number, data: IndexedById>, value: T ): IndexedById> => ({ From 152547d9dc6c8d77cc7801c3026b7063d810a1c4 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 14:50:34 +0100 Subject: [PATCH 05/31] [#175266374] wip --- ts/features/bonus/bpd/navigation/actions.ts | 6 ++++-- .../bonus/bpd/store/reducers/details/selectedPeriod.ts | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ts/features/bonus/bpd/navigation/actions.ts b/ts/features/bonus/bpd/navigation/actions.ts index a9a55674874..d26746ffc93 100644 --- a/ts/features/bonus/bpd/navigation/actions.ts +++ b/ts/features/bonus/bpd/navigation/actions.ts @@ -1,4 +1,5 @@ import { NavigationActions } from "react-navigation"; +import { BpdPeriod } from "../store/actions/periods"; import BPD_ROUTES from "./routes"; export const navigateToBpdOnboardingLoadActivationStatus = () => @@ -45,7 +46,8 @@ export const navigateToBpdTestScreen = () => // Details -export const navigateToBpdDetails = () => +export const navigateToBpdDetails = (specificPeriod?: BpdPeriod) => NavigationActions.navigate({ - routeName: BPD_ROUTES.DETAILS + routeName: BPD_ROUTES.DETAILS, + params: { specificPeriod } }); diff --git a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts index afc800081cb..b577d19d3ee 100644 --- a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts +++ b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts @@ -2,6 +2,7 @@ import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; import { Action } from "../../../../../../store/actions/types"; import { GlobalState } from "../../../../../../store/reducers/types"; +import { navigateToBpdDetails } from "../../../navigation/actions"; import { BpdPeriod } from "../../actions/periods"; import { bpdSelectPeriod } from "../../actions/selectedPeriod"; @@ -17,6 +18,8 @@ export const bpdSelectedPeriodsReducer = ( switch (action.type) { case getType(bpdSelectPeriod): return action.payload; + case getType(navigateToBpdDetails): + return action.params; } return state; }; From de9085458dbcb89acf89828dfe376c6bef60e01a Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 17:45:33 +0100 Subject: [PATCH 06/31] [#175266374] add periods navigation --- .../bonus/bpd/screens/test/TMPPeriods.tsx | 72 +++++++++++++++++++ .../bpd/store/reducers/details/periods.ts | 4 +- .../store/reducers/details/selectedPeriod.ts | 11 ++- ts/screens/wallet/WalletHomeScreen.tsx | 17 +++-- 4 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/test/TMPPeriods.tsx diff --git a/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx b/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx new file mode 100644 index 00000000000..16cc1cbe9fc --- /dev/null +++ b/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx @@ -0,0 +1,72 @@ +import { Button, View } from "native-base"; +import * as pot from "italia-ts-commons/lib/pot"; +import { useEffect } from "react"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { H1 } from "../../../../../components/core/typography/H1"; +import { Label } from "../../../../../components/core/typography/Label"; +import { GlobalState } from "../../../../../store/reducers/types"; +import { navigateToBpdDetails } from "../../navigation/actions"; +import { BpdPeriod, bpdPeriodsLoad } from "../../store/actions/periods"; +import { bpdPeriodsSelector } from "../../store/reducers/details/periods"; + +export type Props = ReturnType & + ReturnType; + +const foldPeriods = ( + potPeriods: pot.Pot, Error>, + action: (id: BpdPeriod) => void +) => + pot.fold( + potPeriods, + () => null, + () =>

Loading...

, + _ => null, + error =>

Error {error.message}

, + value => + value ? renderPeriods(value, action) :

Periods Undefined

, + _ => null, + _ => null, + _ => null + ); + +const renderPeriods = ( + periods: ReadonlyArray, + action: (id: BpdPeriod) => void +) => + periods.map(p => ( + + )); + +/** + * A temp component to render the bpd periods as button and navigate to bpdDetails with the selected period + * TODO: Complete after the completion of the bpd cards + * @constructor + */ +const TmpPeriods: React.FunctionComponent = props => { + // for test purpose, just load at the startup (no retry case) + useEffect(() => { + props.loadPeriods(); + }, []); + + return ( + + {foldPeriods(props.periods, props.navigateToBpdDetails)} + + ); +}; + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + loadPeriods: () => dispatch(bpdPeriodsLoad.request()), + navigateToBpdDetails: (period: BpdPeriod) => + dispatch(navigateToBpdDetails(period)) +}); + +const mapStateToProps = (state: GlobalState) => ({ + periods: bpdPeriodsSelector(state) +}); + +export default connect(mapStateToProps, mapDispatchToProps)(TmpPeriods); diff --git a/ts/features/bonus/bpd/store/reducers/details/periods.ts b/ts/features/bonus/bpd/store/reducers/details/periods.ts index a27e01285de..d90963e9a09 100644 --- a/ts/features/bonus/bpd/store/reducers/details/periods.ts +++ b/ts/features/bonus/bpd/store/reducers/details/periods.ts @@ -4,6 +4,7 @@ import { getType } from "typesafe-actions"; import { Action } from "../../../../../../store/actions/types"; import { IndexedById } from "../../../../../../store/helpers/indexer"; import { GlobalState } from "../../../../../../store/reducers/types"; +import { isDefined } from "../../../../../../utils/guards"; import { AwardPeriodId, BpdPeriod, @@ -44,7 +45,8 @@ export const bpdPeriodsReducer = ( */ export const bpdPeriodsSelector = createSelector( [(state: GlobalState) => state.bonus.bpd.details.periods], - potValue => potValue + potValue => + pot.map(potValue, potValue => Object.values(potValue).filter(isDefined)) ); /** diff --git a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts index b577d19d3ee..b51100828f6 100644 --- a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts +++ b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts @@ -1,8 +1,9 @@ +import { NavigationActions } from "react-navigation"; import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; import { Action } from "../../../../../../store/actions/types"; import { GlobalState } from "../../../../../../store/reducers/types"; -import { navigateToBpdDetails } from "../../../navigation/actions"; +import BPD_ROUTES from "../../../navigation/routes"; import { BpdPeriod } from "../../actions/periods"; import { bpdSelectPeriod } from "../../actions/selectedPeriod"; @@ -18,8 +19,12 @@ export const bpdSelectedPeriodsReducer = ( switch (action.type) { case getType(bpdSelectPeriod): return action.payload; - case getType(navigateToBpdDetails): - return action.params; + case NavigationActions.NAVIGATE: + if (action.routeName === BPD_ROUTES.DETAILS) { + return action.params?.specificPeriod + ? action.params?.specificPeriod + : null; + } } return state; }; diff --git a/ts/screens/wallet/WalletHomeScreen.tsx b/ts/screens/wallet/WalletHomeScreen.tsx index 26a359a5911..e5863c3be06 100644 --- a/ts/screens/wallet/WalletHomeScreen.tsx +++ b/ts/screens/wallet/WalletHomeScreen.tsx @@ -37,6 +37,7 @@ import { import { allBonusActiveSelector } from "../../features/bonus/bonusVacanze/store/reducers/allActive"; import { availableBonusTypesSelector } from "../../features/bonus/bonusVacanze/store/reducers/availableBonusesTypes"; import { navigateToBpdTestScreen } from "../../features/bonus/bpd/navigation/actions"; +import TmpPeriods from "../../features/bonus/bpd/screens/test/TMPPeriods"; import I18n from "../../i18n"; import { navigateBack, @@ -514,12 +515,16 @@ class WalletHomeScreen extends React.PureComponent { > {/* TODO: temp only, for test purpose,to be removed with bpd details */} {bpdEnabled && ( - + <> + + {/* TODO: temp only, temporary display bpd periods */} + + )} {this.newMethodAdded ? this.newMethodAddedContent : transactionContent} {bonusVacanzeEnabled && ( From 0c0bc635d0ae76afad69944a0a9065eba995407d Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 19:34:27 +0100 Subject: [PATCH 07/31] [#175266374] add draft selector --- .../bpd/screens/details/BpdDetailsScreen.tsx | 1 + .../bpd/screens/details/BpdPeriodSelector.tsx | 28 +++++++++++++++---- .../details/periods/BpdActivePeriod.tsx | 6 ++-- .../details/periods/BpdClosedPeriod.tsx | 6 ++-- .../details/periods/BpdInactivePeriod.tsx | 6 ++-- .../details/periods/BpdPeriodDetail.tsx | 21 +++++++++++--- .../bonus/bpd/screens/test/TMPPeriods.tsx | 18 ++++++++++-- .../store/reducers/details/selectedPeriod.ts | 2 ++ 8 files changed, 70 insertions(+), 18 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index b46895c6f12..c1bdb796c23 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -16,6 +16,7 @@ const styles = StyleSheet.create({ height: 172 }, selector: { + // TODO: temp, as placeholder from invision, waiting for the components height: 192 + 10 + 16 + 16, width: "100%", position: "absolute", diff --git a/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx b/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx index 5d008045523..9a25edfa00a 100644 --- a/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdPeriodSelector.tsx @@ -3,8 +3,14 @@ import * as React from "react"; import { StyleSheet } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; -import { GlobalState } from "../../../../../store/reducers/types"; import { H1 } from "../../../../../components/core/typography/H1"; +import { H3 } from "../../../../../components/core/typography/H3"; +import { GlobalState } from "../../../../../store/reducers/types"; +import { BpdPeriod } from "../../store/actions/periods"; +import { bpdSelectPeriod } from "../../store/actions/selectedPeriod"; +import { bpdPeriodsSelector } from "../../store/reducers/details/periods"; +import { bpdSelectedPeriodSelector } from "../../store/reducers/details/selectedPeriod"; +import { TMPBpdPeriodsAsButtons } from "../test/TMPPeriods"; export type Props = ReturnType & ReturnType; @@ -20,17 +26,29 @@ const styles = StyleSheet.create({ /** * An horizontal snap scroll view used to select a specific period of bpd. - * Each period is represented as a BpdPeriodCard + * Each period is represented as a BpdPeriodCard. * @constructor */ -const BpdPeriodSelector: React.FunctionComponent = () => ( +const BpdPeriodSelector: React.FunctionComponent = props => (

Period selector placeholder!

+ +

Current period: {props.selectedPeriod?.awardPeriodId}

+

{props.selectedPeriod?.startDate.toDateString()}

+

{props.selectedPeriod?.endDate.toDateString()}

); -const mapDispatchToProps = (_: Dispatch) => ({}); +const mapDispatchToProps = (dispatch: Dispatch) => ({ + changeSelectPeriod: (period: BpdPeriod) => dispatch(bpdSelectPeriod(period)) +}); -const mapStateToProps = (_: GlobalState) => ({}); +const mapStateToProps = (state: GlobalState) => ({ + periods: bpdPeriodsSelector(state), + selectedPeriod: bpdSelectedPeriodSelector(state) +}); export default connect(mapStateToProps, mapDispatchToProps)(BpdPeriodSelector); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx index 7f25e666c2f..9ecbb6e4b28 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx @@ -1,7 +1,7 @@ -import { View } from "native-base"; import * as React from "react"; import { connect } from "react-redux"; import { Dispatch } from "redux"; +import { H1 } from "../../../../../../components/core/typography/H1"; import { GlobalState } from "../../../../../../store/reducers/types"; export type Props = ReturnType & @@ -11,7 +11,9 @@ export type Props = ReturnType & * Render the details for a current active cashback period * @constructor */ -const BpdActivePeriod: React.FunctionComponent = () => ; +const BpdActivePeriod: React.FunctionComponent = () => ( +

Active Period!

+); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx index d5a91b12032..f7b7a40457d 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx @@ -1,7 +1,7 @@ -import { View } from "native-base"; import * as React from "react"; import { connect } from "react-redux"; import { Dispatch } from "redux"; +import { H1 } from "../../../../../../components/core/typography/H1"; import { GlobalState } from "../../../../../../store/reducers/types"; export type Props = ReturnType & @@ -11,7 +11,9 @@ export type Props = ReturnType & * Render the details for a completed and closed cashback periods * @constructor */ -const BpdClosedPeriod: React.FunctionComponent = () => ; +const BpdClosedPeriod: React.FunctionComponent = () => ( +

Closed Period!

+); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx index 062aa049337..feaf385ef46 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx @@ -1,7 +1,7 @@ -import { View } from "native-base"; import * as React from "react"; import { connect } from "react-redux"; import { Dispatch } from "redux"; +import { H1 } from "../../../../../../components/core/typography/H1"; import { GlobalState } from "../../../../../../store/reducers/types"; export type Props = ReturnType & @@ -11,7 +11,9 @@ export type Props = ReturnType & * Render the details for a future cashback period * @constructor */ -const BpdInactivePeriod: React.FunctionComponent = () => ; +const BpdInactivePeriod: React.FunctionComponent = () => ( +

Inactive Period!

+); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx index 65711e236d2..d352dbc7e0f 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdPeriodDetail.tsx @@ -4,20 +4,33 @@ import { connect } from "react-redux"; import { Dispatch } from "redux"; import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; import { GlobalState } from "../../../../../../store/reducers/types"; -import { H1 } from "../../../../../../components/core/typography/H1"; +import { BpdPeriod } from "../../../store/actions/periods"; import { bpdSelectedPeriodSelector } from "../../../store/reducers/details/selectedPeriod"; +import BpdActivePeriod from "./BpdActivePeriod"; +import BpdClosedPeriod from "./BpdClosedPeriod"; +import BpdInactivePeriod from "./BpdInactivePeriod"; export type Props = ReturnType & ReturnType; +const selectPeriodScreen = (period: BpdPeriod) => { + switch (period.status) { + case "Active": + return ; + case "Closed": + return ; + case "Inactive": + return ; + } +}; + /** * The body and details for a specific cashback period. Will change if is Active, Inactive or Closed * @constructor */ -const BpdPeriodDetail: React.FunctionComponent = () => ( +const BpdPeriodDetail: React.FunctionComponent = props => ( - {/* {TODO: will choose the right representation (different components) based on the period} */} -

Period details Placeholder!

+ {props.selectedPeriod && selectPeriodScreen(props.selectedPeriod)}
); diff --git a/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx b/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx index 16cc1cbe9fc..86cfee1f6c7 100644 --- a/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx +++ b/ts/features/bonus/bpd/screens/test/TMPPeriods.tsx @@ -41,6 +41,17 @@ const renderPeriods = ( )); +type OwnProps = { + potPeriods: pot.Pot, Error>; + onPeriodSelected: (period: BpdPeriod) => void; +}; + +export const TMPBpdPeriodsAsButtons = (props: OwnProps) => ( + + {foldPeriods(props.potPeriods, props.onPeriodSelected)} + +); + /** * A temp component to render the bpd periods as button and navigate to bpdDetails with the selected period * TODO: Complete after the completion of the bpd cards @@ -53,9 +64,10 @@ const TmpPeriods: React.FunctionComponent = props => { }, []); return ( - - {foldPeriods(props.periods, props.navigateToBpdDetails)} - + ); }; diff --git a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts index b51100828f6..04aad8320e1 100644 --- a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts +++ b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts @@ -31,6 +31,8 @@ export const bpdSelectedPeriodsReducer = ( /** * Return current period selected by the user (current displayed) + * TODO: if null(generic navigation to cashback), return the current period ( start_date < today < end_date ) + * if no period match the date interval, return the nearest */ export const bpdSelectedPeriodSelector = createSelector( [(state: GlobalState) => state.bonus.bpd.details.selectedPeriod], From fc3eff8612493d1bd5884cbb012bf2208ef4bde2 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 29 Oct 2020 19:47:49 +0100 Subject: [PATCH 08/31] [#175266374] add placeholder string --- .../bonus/bpd/screens/details/periods/BpdActivePeriod.tsx | 2 +- .../bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx | 2 +- .../bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx index 9ecbb6e4b28..0dcaa57755e 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx @@ -12,7 +12,7 @@ export type Props = ReturnType & * @constructor */ const BpdActivePeriod: React.FunctionComponent = () => ( -

Active Period!

+

Active Period placeholder!

); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx index f7b7a40457d..f0f7514745b 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdClosedPeriod.tsx @@ -12,7 +12,7 @@ export type Props = ReturnType & * @constructor */ const BpdClosedPeriod: React.FunctionComponent = () => ( -

Closed Period!

+

Closed Period placeholder!

); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx index feaf385ef46..45a74259f7b 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdInactivePeriod.tsx @@ -12,7 +12,7 @@ export type Props = ReturnType & * @constructor */ const BpdInactivePeriod: React.FunctionComponent = () => ( -

Inactive Period!

+

Inactive Period placeholder!

); const mapDispatchToProps = (_: Dispatch) => ({}); From 4f14e6d67bc6a0da592606643aeae79865fdd665 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 10:17:51 +0100 Subject: [PATCH 09/31] [#175266374] simplify code --- .../bonus/bpd/store/reducers/details/selectedPeriod.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts index 04aad8320e1..f58f44a4c74 100644 --- a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts +++ b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts @@ -21,9 +21,7 @@ export const bpdSelectedPeriodsReducer = ( return action.payload; case NavigationActions.NAVIGATE: if (action.routeName === BPD_ROUTES.DETAILS) { - return action.params?.specificPeriod - ? action.params?.specificPeriod - : null; + return action.params?.specificPeriod ?? null; } } return state; From 3cffb83db56d57875d34a4b0c1864268019687c6 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 15:16:47 +0100 Subject: [PATCH 10/31] [#174848741] add IbanComponent logic --- locales/en/index.yml | 7 ++ locales/it/index.yml | 7 ++ .../bpd/components/PaymentMethodBpdList.tsx | 1 - ts/features/bonus/bpd/model/RemoteValue.ts | 7 +- .../bpd/saga/orchestration/insertIban.ts | 2 + .../bpd/screens/details/BpdDetailsScreen.tsx | 2 +- .../iban/BaseIbanInformationComponent.tsx | 71 +++++++++++++++++++ .../iban/IbanInformationComponent.tsx | 70 ++++++++++++++++++ .../details/periods/BpdActivePeriod.tsx | 8 ++- .../bonus/bpd/screens/test/TMPBpdScreen.tsx | 3 +- .../bonus/bpd/store/actions/onboarding.ts | 10 ++- .../reducers/details/activation/index.ts | 12 ++++ .../details/activation/payoffInstrument.ts | 3 + .../bpd/store/reducers/onboarding/ongoing.ts | 10 ++- ts/screens/showroom/OthersShowroom.tsx | 2 + .../showroom/core/SelectionShowroom.tsx | 2 + 16 files changed, 207 insertions(+), 10 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx create mode 100644 ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 90cf0ef29c0..838154f5900 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -66,6 +66,7 @@ global: search: Search skip: "Skip" add: Add + edit: "Edit" navigator: messages: messages wallet: payments @@ -1640,6 +1641,12 @@ bonus: text2: "identify a current account that is not registered in your tax code: are you sure you want to use this IBAN?" loading: "We are verifying your IBAN\n\nPlease wait." + details: + components: + iban: + title: "IBAN for accreditation" + noIbanBody: "Set your IBAN in order to receive the accumulated cashback" + button: "Set IBAN" webView: error: missingParams: Not all information necessary to access this page are available diff --git a/locales/it/index.yml b/locales/it/index.yml index 6ee1cdf271f..d55d2c0061a 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -66,6 +66,7 @@ global: search: Ricerca skip: "Salta" add: Aggiungi + edit: "Modifica" navigator: messages: messaggi wallet: pagamenti @@ -1672,6 +1673,12 @@ bonus: text2: "identifica un conto corrente che non risulta intestato al tuo codice fiscale: sei sicuro di voler usare questo IBAN?" loading: "Stiamo verificando il tuo IBAN\n\nTi preghiamo di attendere." + details: + components: + iban: + title: "IBAN per l’accredito" + noIbanBody: "Imposta il tuo IBAN per poter ricevere il cashback accumulato" + button: "Imposta IBAN" webView: error: missingParams: Non sono presenti le informazioni necessarie per accedere a questa pagina diff --git a/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx b/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx index 3d332f6baee..32d71377b4b 100644 --- a/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx +++ b/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx @@ -11,7 +11,6 @@ type Props = { /** * Render a {@link ReadOnlyArray} of {@link Wallet} using {@link PaymentMethodBpdToggle} - * TODO: after v2, extract foreach Walletv2 the information to render the element * @param props * @constructor */ diff --git a/ts/features/bonus/bpd/model/RemoteValue.ts b/ts/features/bonus/bpd/model/RemoteValue.ts index 3b6951d651d..7ed912d018b 100644 --- a/ts/features/bonus/bpd/model/RemoteValue.ts +++ b/ts/features/bonus/bpd/model/RemoteValue.ts @@ -61,11 +61,12 @@ export const remoteError = (e: E): RemoteError => ({ }); export const fold = ( + rm: RemoteValue, onUndefined: () => B, onLoading: () => B, - onReady: (error: T) => B, - onError: (value: E) => B -) => (rm: RemoteValue): B => { + onReady: (value: T) => B, + onError: (error: E) => B +): B => { switch (rm.kind) { case "undefined": { return onUndefined(); diff --git a/ts/features/bonus/bpd/saga/orchestration/insertIban.ts b/ts/features/bonus/bpd/saga/orchestration/insertIban.ts index d285146131a..f4d906334b8 100644 --- a/ts/features/bonus/bpd/saga/orchestration/insertIban.ts +++ b/ts/features/bonus/bpd/saga/orchestration/insertIban.ts @@ -16,6 +16,7 @@ import { bpdIbanInsertionCancel, bpdIbanInsertionContinue } from "../../store/actions/iban"; +import { bpdOnboardingCompleted } from "../../store/actions/onboarding"; import { isBpdOnboardingOngoing } from "../../store/reducers/onboarding/ongoing"; // TODO: if isOnboarding===true, change with an action that triggers a saga that choose @@ -66,6 +67,7 @@ export function* bpdIbanInsertionWorker() { : navigateToBpdOnboardingNoPaymentMethods(); yield put(nextAction); yield put(navigationHistoryPop(1)); + yield put(bpdOnboardingCompleted()); } else { yield put(NavigationActions.back()); } diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index c1bdb796c23..a9c21ddd14a 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -5,8 +5,8 @@ import { Dispatch } from "redux"; import DarkLayout from "../../../../../components/screens/DarkLayout"; import I18n from "../../../../../i18n"; import { GlobalState } from "../../../../../store/reducers/types"; -import BpdPeriodDetail from "./periods/BpdPeriodDetail"; import BpdPeriodSelector from "./BpdPeriodSelector"; +import BpdPeriodDetail from "./periods/BpdPeriodDetail"; export type Props = ReturnType & ReturnType; diff --git a/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx new file mode 100644 index 00000000000..f240aa585d6 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx @@ -0,0 +1,71 @@ +import { Button, View } from "native-base"; +import * as React from "react"; +import { StyleSheet } from "react-native"; +import { InfoBox } from "../../../../../../../components/box/InfoBox"; +import { Body } from "../../../../../../../components/core/typography/Body"; +import { H4 } from "../../../../../../../components/core/typography/H4"; +import { Label } from "../../../../../../../components/core/typography/Label"; +import { Link } from "../../../../../../../components/core/typography/Link"; +import { Monospace } from "../../../../../../../components/core/typography/Monospace"; +import { IOStyles } from "../../../../../../../components/core/variables/IOStyles"; +import I18n from "../../../../../../../i18n"; + +export type BaseIbanProps = { + iban: string | undefined; + onInsertIban: () => void; +}; + +const styles = StyleSheet.create({ + row: { flexDirection: "row", justifyContent: "space-between" }, + insertIbanButton: { width: "100%" } +}); + +/** + * Render a Infobox that warns the user that should insert the IBAN to receive + * the cashback amount + * @param props + * @constructor + */ +const NoIbanComponent = (props: { onPress: () => void }) => ( + <> + + {I18n.t("bonus.bpd.details.components.iban.noIbanBody")} + + + + +); + +/** + * Display the current IBAN + * @constructor + */ +const IbanComponent = (props: { iban: string }) => ( + {props.iban} +); + +export const BaseIbanInformationComponent: React.FunctionComponent = props => ( + + +

{I18n.t("bonus.bpd.details.components.iban.title")}

+ {props.iban !== undefined && ( + + {I18n.t("global.buttons.edit").toLowerCase()} + + )} +
+ + {props.iban ? ( + + ) : ( + + )} + {/* */} + {/* */} + + +); diff --git a/ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx b/ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx new file mode 100644 index 00000000000..aabfcf98514 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx @@ -0,0 +1,70 @@ +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import Placeholder from "rn-placeholder"; +import { GlobalState } from "../../../../../../../store/reducers/types"; +import { fold, RemoteValue } from "../../../../model/RemoteValue"; +import { bpdIbanInsertionStart } from "../../../../store/actions/iban"; +import { bpdIbanSelector } from "../../../../store/reducers/details/activation"; +import { + BaseIbanInformationComponent, + BaseIbanProps +} from "./BaseIbanInformationComponent"; + +export type Props = ReturnType & + ReturnType; + +const LoadingIban = () => ; + +/** + * Render the Iban based on the RemoteValue. + * For safeness, even undefined, remote and error cases are managed, although the iban detail + * screen is only accessible if bpd has been activated. + * @param props + * @constructor + */ +const RenderRemoteIban = ( + props: { iban: RemoteValue } & Omit< + BaseIbanProps, + "iban" + > +) => + fold( + props.iban, + () => null, + () => , + value => ( + + ), + _ => null + ); + +/** + * Link {@link BaseIbanInformationComponent} to the business logic + * Read the iban RemoteValue from the store + * Dispatch bpdIbanInsertionStart() in case of new iban insertion (or modification + * @param props + * @constructor + */ +const IbanInformationComponent: React.FunctionComponent = props => ( + +); + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + startIbanOnboarding: () => dispatch(bpdIbanInsertionStart()) +}); + +const mapStateToProps = (state: GlobalState) => ({ + iban: bpdIbanSelector(state) +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(IbanInformationComponent); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx index 0dcaa57755e..c0dbd32c682 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx @@ -1,8 +1,11 @@ import * as React from "react"; +import { View } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; import { H1 } from "../../../../../../components/core/typography/H1"; +import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; import { GlobalState } from "../../../../../../store/reducers/types"; +import IbanInformationComponent from "../components/iban/IbanInformationComponent"; export type Props = ReturnType & ReturnType; @@ -12,7 +15,10 @@ export type Props = ReturnType & * @constructor */ const BpdActivePeriod: React.FunctionComponent = () => ( -

Active Period placeholder!

+ +

Active Period placeholder!

+ +
); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx b/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx index eea2ae8d684..d1ffa84e7ce 100644 --- a/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx +++ b/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx @@ -32,6 +32,7 @@ export type Props = ReturnType & const renderBpdActive = (value: RemoteValue) => fold( + value, () => Sconosciuta, () => In caricamento, active => ( @@ -40,7 +41,7 @@ const renderBpdActive = (value: RemoteValue) => ), _ => Errore durante il caricamento - )(value); + ); const renderPaymentMethod = ( potWallets: pot.Pot, Error> diff --git a/ts/features/bonus/bpd/store/actions/onboarding.ts b/ts/features/bonus/bpd/store/actions/onboarding.ts index 71bdf2f2bfa..7034ffcadc6 100644 --- a/ts/features/bonus/bpd/store/actions/onboarding.ts +++ b/ts/features/bonus/bpd/store/actions/onboarding.ts @@ -16,7 +16,7 @@ export const bpdEnrollUserToProgram = createAsyncAction( )(); /** - * delete user from bpd program + * Delete user from bpd program */ export const bpdDeleteUserFromProgram = createAsyncAction( "BPD_DELETE_REQUEST", @@ -45,6 +45,13 @@ export const bpdOnboardingCancel = createStandardAction( "BPD_ONBOARDING_CANCEL" )(); +/** + * The user completed the final step of the onboarding (choose to add iban) + */ +export const bpdOnboardingCompleted = createStandardAction( + "BPD_ONBOARDING_COMPLETED" +)(); + /** * The user accepts and confirms the declaration */ @@ -58,4 +65,5 @@ export type BpdOnboardingActions = | ActionType | ActionType | ActionType + | ActionType | ActionType; diff --git a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts index 388cc55fcb2..6adac994698 100644 --- a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts +++ b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts @@ -1,4 +1,5 @@ import { combineReducers } from "redux"; +import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; import { Action } from "../../../../../../../store/actions/types"; import { GlobalState } from "../../../../../../../store/reducers/types"; @@ -66,4 +67,15 @@ export const bpdEnabledSelector = ( state: GlobalState ): RemoteValue => state.bonus.bpd.details.activation.enabled; +/** + * Return the Iban that the user has entered to receive the cashback amount + */ +export const bpdIbanSelector = createSelector( + [ + (state: GlobalState) => + state.bonus.bpd.details.activation.payoffInstr.enrolledValue + ], + iban => iban +); + export default bpdActivationReducer; diff --git a/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts b/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts index 15626c4a09d..e342b62231b 100644 --- a/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts +++ b/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts @@ -17,6 +17,7 @@ import { bpdIbanInsertionResetScreen, bpdUpsertIban } from "../../../actions/iban"; +import { bpdDeleteUserFromProgram } from "../../../actions/onboarding"; type UpsertIBAN = { // the results of the upsert operation @@ -43,6 +44,8 @@ const paymentInstrumentValueReducer = ( action: Action ): RemoteValue => { switch (action.type) { + case getType(bpdDeleteUserFromProgram.success): + return remoteUndefined; case getType(bpdLoadActivationStatus.request): return remoteLoading; case getType(bpdLoadActivationStatus.success): diff --git a/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts b/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts index d6c95473497..0e0e593e52f 100644 --- a/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts +++ b/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts @@ -2,7 +2,12 @@ import { getType } from "typesafe-actions"; import { Action } from "../../../../../../store/actions/types"; import { GlobalState } from "../../../../../../store/reducers/types"; import { bpdLoadActivationStatus } from "../../actions/details"; -import { bpdOnboardingCancel, bpdUserActivate } from "../../actions/onboarding"; +import { bpdIbanInsertionCancel } from "../../actions/iban"; +import { + bpdOnboardingCancel, + bpdOnboardingCompleted, + bpdUserActivate +} from "../../actions/onboarding"; /** * This reducers is used to know if a current onboarding is ongoing @@ -17,10 +22,11 @@ const ongoingOnboardingReducer = ( case getType(bpdUserActivate): return true; case getType(bpdOnboardingCancel): + case getType(bpdOnboardingCompleted): + case getType(bpdIbanInsertionCancel): return false; case getType(bpdLoadActivationStatus.success): return action.payload.enabled ? false : state; - // TODO: check when moving the bpdLoadActivationStatus.success in the wallet if the value is ok } return state; }; diff --git a/ts/screens/showroom/OthersShowroom.tsx b/ts/screens/showroom/OthersShowroom.tsx index 827f2dea6ab..acbc690c22e 100644 --- a/ts/screens/showroom/OthersShowroom.tsx +++ b/ts/screens/showroom/OthersShowroom.tsx @@ -3,6 +3,7 @@ import * as React from "react"; import { StyleSheet } from "react-native"; import { InfoBox } from "../../components/box/InfoBox"; import { Body } from "../../components/core/typography/Body"; +import { Label } from "../../components/core/typography/Label"; import { IOStyles } from "../../components/core/variables/IOStyles"; import { ShowroomSection } from "./ShowroomSection"; @@ -19,6 +20,7 @@ const styles = StyleSheet.create({ export const OthersShowroom = () => ( + Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod diff --git a/ts/screens/showroom/core/SelectionShowroom.tsx b/ts/screens/showroom/core/SelectionShowroom.tsx index e6b306d635c..37c459d943c 100644 --- a/ts/screens/showroom/core/SelectionShowroom.tsx +++ b/ts/screens/showroom/core/SelectionShowroom.tsx @@ -2,6 +2,7 @@ import { View } from "native-base"; import * as React from "react"; import { StyleSheet } from "react-native"; import { CheckBox } from "../../../components/core/selection/CheckBox"; +import { Label } from "../../../components/core/typography/Label"; import { ShowroomSection } from "../ShowroomSection"; const styles = StyleSheet.create({ @@ -16,6 +17,7 @@ const styles = StyleSheet.create({ export const SelectionShowroom = () => ( + From 6bea7d4a77ec0ef2fe15febcbd63b3a2edad25d7 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 15:30:30 +0100 Subject: [PATCH 11/31] [#174848741] fix --- .../bonus/bpd/store/reducers/details/activation/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts index 6adac994698..c36b97a5992 100644 --- a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts +++ b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts @@ -46,7 +46,7 @@ const enabledReducer = ( case getType(bpdEnrollUserToProgram.success): return remoteReady(action.payload.enabled); case getType(bpdDeleteUserFromProgram.success): - return remoteReady(false); + return remoteUndefined; case getType(bpdLoadActivationStatus.failure): case getType(bpdEnrollUserToProgram.failure): return remoteError(action.payload); From ae1aafb45ae3805f1720133cae0f1de7f95db3c6 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 15:42:07 +0100 Subject: [PATCH 12/31] [#174848741] clean comments --- .../details/components/iban/BaseIbanInformationComponent.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx index f240aa585d6..eea342d2672 100644 --- a/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx +++ b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx @@ -64,8 +64,6 @@ export const BaseIbanInformationComponent: React.FunctionComponent )} - {/* */} - {/* */} ); From ca6ce69572d7b431cef28c3f78182b503d062b75 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 16:19:28 +0100 Subject: [PATCH 13/31] [#175515542] Stub for bpdtransactionScreen --- locales/en/index.yml | 2 ++ locales/it/index.yml | 2 ++ ts/features/bonus/bpd/navigation/actions.ts | 6 ++++ ts/features/bonus/bpd/navigation/navigator.ts | 4 +++ ts/features/bonus/bpd/navigation/routes.ts | 1 + .../transaction/BpdTransactionsScreen.tsx | 33 +++++++++++++++++++ 6 files changed, 48 insertions(+) create mode 100644 ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 838154f5900..306e246f6b0 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1647,6 +1647,8 @@ bonus: title: "IBAN for accreditation" noIbanBody: "Set your IBAN in order to receive the accumulated cashback" button: "Set IBAN" + transaction: + title: "Your transactions" webView: error: missingParams: Not all information necessary to access this page are available diff --git a/locales/it/index.yml b/locales/it/index.yml index d55d2c0061a..2e9d9ff42b3 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1679,6 +1679,8 @@ bonus: title: "IBAN per l’accredito" noIbanBody: "Imposta il tuo IBAN per poter ricevere il cashback accumulato" button: "Imposta IBAN" + transaction: + title: "Le tue transazioni" webView: error: missingParams: Non sono presenti le informazioni necessarie per accedere a questa pagina diff --git a/ts/features/bonus/bpd/navigation/actions.ts b/ts/features/bonus/bpd/navigation/actions.ts index d26746ffc93..25340e57a41 100644 --- a/ts/features/bonus/bpd/navigation/actions.ts +++ b/ts/features/bonus/bpd/navigation/actions.ts @@ -51,3 +51,9 @@ export const navigateToBpdDetails = (specificPeriod?: BpdPeriod) => routeName: BPD_ROUTES.DETAILS, params: { specificPeriod } }); + +// Transactions +export const navigateToBpdTransactions = () => + NavigationActions.navigate({ + routeName: BPD_ROUTES.TRANSACTIONS + }); diff --git a/ts/features/bonus/bpd/navigation/navigator.ts b/ts/features/bonus/bpd/navigation/navigator.ts index 70721877a68..e2f603ef751 100644 --- a/ts/features/bonus/bpd/navigation/navigator.ts +++ b/ts/features/bonus/bpd/navigation/navigator.ts @@ -1,5 +1,6 @@ import { createStackNavigator } from "react-navigation"; import BpdDetailsScreen from "../screens/details/BpdDetailsScreen"; +import BpdTransactionsScreen from "../screens/details/transaction/BpdTransactionsScreen"; import MainIbanScreen from "../screens/iban/MainIbanScreen"; import BpdInformationScreen from "../screens/onboarding/BpdInformationScreen"; import DeclarationScreen from "../screens/onboarding/declaration/DeclarationScreen"; @@ -36,6 +37,9 @@ const BpdNavigator = createStackNavigator( [BPD_ROUTES.DETAILS]: { screen: BpdDetailsScreen }, + [BPD_ROUTES.TRANSACTIONS]: { + screen: BpdTransactionsScreen + }, // TODO: remove after the introduction of the bpd detail screen [BPD_ROUTES.TEST]: { screen: TMPBpdScreen diff --git a/ts/features/bonus/bpd/navigation/routes.ts b/ts/features/bonus/bpd/navigation/routes.ts index 66c16111f80..71482b1e029 100644 --- a/ts/features/bonus/bpd/navigation/routes.ts +++ b/ts/features/bonus/bpd/navigation/routes.ts @@ -11,6 +11,7 @@ const BPD_ROUTES = { }, IBAN: "BPD_IBAN", DETAILS: "BPD_DETAILS", + TRANSACTIONS: "BPD_TRANSACTIONS", // TODO: remove after the introduction of the bpd detail screen TEST: "BPD_TEST" }; diff --git a/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx new file mode 100644 index 00000000000..595fdd8cf33 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx @@ -0,0 +1,33 @@ +import * as React from "react"; +import { SafeAreaView } from "react-native"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { H1 } from "../../../../../../components/core/typography/H1"; +import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; +import BaseScreenComponent from "../../../../../../components/screens/BaseScreenComponent"; +import I18n from "../../../../../../i18n"; +import { GlobalState } from "../../../../../../store/reducers/types"; + +export type Props = ReturnType & + ReturnType; + +/** + * Display all the transactions for a specific period + * @constructor + */ +const BpdTransactionsScreen: React.FunctionComponent = () => ( + + +

{I18n.t("bonus.bpd.details.transaction.title")}

+
+
+); + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(BpdTransactionsScreen); From 6b10d6ec1f87794d6c7d5728ae8bf8e7a6fbb3b6 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:28:27 +0100 Subject: [PATCH 14/31] [#175515542] GoToTransactionsButton --- locales/en/index.yml | 1 + locales/it/index.yml | 1 + .../base/PaymentMethodBpdToggle.tsx | 2 - .../bonus/bpd/saga/networking/transactions.ts | 24 ++++++- .../bpd/screens/details/BpdDetailsScreen.tsx | 3 + .../transaction/BpdTransactionsScreen.tsx | 8 ++- .../details/transaction/GoToTransactions.tsx | 69 +++++++++++++++++++ ts/features/bonus/bpd/store/actions/amount.ts | 6 +- .../store/reducers/details/transactions.ts | 2 +- ts/utils/hooks/usePotValue.ts | 61 ++++++++++++++++ 10 files changed, 170 insertions(+), 7 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx create mode 100644 ts/utils/hooks/usePotValue.ts diff --git a/locales/en/index.yml b/locales/en/index.yml index 306e246f6b0..da91054b709 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1649,6 +1649,7 @@ bonus: button: "Set IBAN" transaction: title: "Your transactions" + goToButton: "Transactions detail" webView: error: missingParams: Not all information necessary to access this page are available diff --git a/locales/it/index.yml b/locales/it/index.yml index 2e9d9ff42b3..ce42b444aea 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1681,6 +1681,7 @@ bonus: button: "Imposta IBAN" transaction: title: "Le tue transazioni" + goToButton: "Dettaglio transazioni" webView: error: missingParams: Non sono presenti le informazioni necessarie per accedere a questa pagina diff --git a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx index 6b5422e7e64..c114c44c5e8 100644 --- a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx +++ b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx @@ -151,10 +151,8 @@ const PaymentMethodActivationToggle: React.FunctionComponent = props => { <> - {/* TODO: The image will be received by props / redux state */} - {/* TODO: The Text will be received by props / redux state */} {props.caption} ) { yield delay(1000); + yield put( - bpdTransactionsLoad.success({ awardPeriodId: action.payload, results: [] }) + bpdTransactionsLoad.failure({ + awardPeriodId: action.payload, + error: new Error() + }) ); + + // yield put( + // bpdTransactionsLoad.success({ + // awardPeriodId: action.payload, + // results: [ + // { + // awardPeriodId: action.payload, + // amount: 100, + // cashback: 10, + // circuitType: "Mastercard", + // hashPan: "1515" as HPan, + // idTrxAcquirer: "123", + // idTrxIssuer: "123", + // trxDate: new Date() + // } + // ] + // }) + // ); } diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index a9c21ddd14a..9f533bb74a9 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -7,6 +7,7 @@ import I18n from "../../../../../i18n"; import { GlobalState } from "../../../../../store/reducers/types"; import BpdPeriodSelector from "./BpdPeriodSelector"; import BpdPeriodDetail from "./periods/BpdPeriodDetail"; +import GoToTransactions from "./transaction/GoToTransactions"; export type Props = ReturnType & ReturnType; @@ -28,6 +29,7 @@ const styles = StyleSheet.create({ height: 60 } }); + /** * The screen that allows the user to see all the details related to the bpd. * @constructor @@ -41,6 +43,7 @@ const BpdDetailsScreen: React.FunctionComponent = () => ( topContent={} gradientHeader={true} hideHeader={true} + footerContent={} > diff --git a/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx index 595fdd8cf33..9aa2ec2964d 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { SafeAreaView } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; +import { View } from "native-base"; import { H1 } from "../../../../../../components/core/typography/H1"; import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; import BaseScreenComponent from "../../../../../../components/screens/BaseScreenComponent"; @@ -16,9 +17,12 @@ export type Props = ReturnType & * @constructor */ const BpdTransactionsScreen: React.FunctionComponent = () => ( - + -

{I18n.t("bonus.bpd.details.transaction.title")}

+ + +

{I18n.t("bonus.bpd.details.transaction.title")}

+
); diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx new file mode 100644 index 00000000000..28d02e6d215 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -0,0 +1,69 @@ +import { fromNullable } from "fp-ts/lib/Option"; +import * as pot from "italia-ts-commons/lib/pot"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import ButtonDefaultOpacity from "../../../../../../components/ButtonDefaultOpacity"; +import { Label } from "../../../../../../components/core/typography/Label"; +import IconFont from "../../../../../../components/ui/IconFont"; +import I18n from "../../../../../../i18n"; +import { GlobalState } from "../../../../../../store/reducers/types"; +import { useLoadPotValue } from "../../../../../../utils/hooks/usePotValue"; +import { navigateToBpdTransactions } from "../../../navigation/actions"; +import { AwardPeriodId } from "../../../store/actions/periods"; +import { bpdTransactionsLoad } from "../../../store/actions/transactions"; +import { bpdSelectedPeriodSelector } from "../../../store/reducers/details/selectedPeriod"; +import { bpdTransactionsForSelectedPeriod } from "../../../store/reducers/details/transactions"; + +type Props = ReturnType & + ReturnType; + +/** + * Display the transactions button only if the transactions number are > 0 + * (never displayed for inactive period) + * @param props + * @constructor + */ +const GoToTransactions: React.FunctionComponent = props => { + // Load the transactions if not pot.some + + const periodId = fromNullable(props.selectedPeriod) + .map(period => period.awardPeriodId.toString()) + .getOrElse("undefined"); + + useLoadPotValue(periodId, props.transactions, () => + fromNullable(props.selectedPeriod).map(period => + props.loadTransactionsByPeriod(period.awardPeriodId) + ) + ); + const canRenderButton = pot.getOrElse( + pot.map(props.transactions, val => val.length > 0), + false + ); + + return canRenderButton ? ( + + + + + ) : null; +}; + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + goToTransactions: () => dispatch(navigateToBpdTransactions()), + loadTransactionsByPeriod: (periodId: AwardPeriodId) => + dispatch(bpdTransactionsLoad.request(periodId)) +}); + +const mapStateToProps = (state: GlobalState) => ({ + transactions: bpdTransactionsForSelectedPeriod(state), + selectedPeriod: bpdSelectedPeriodSelector(state) +}); + +export default connect(mapStateToProps, mapDispatchToProps)(GoToTransactions); diff --git a/ts/features/bonus/bpd/store/actions/amount.ts b/ts/features/bonus/bpd/store/actions/amount.ts index d1262eb5650..c448fb1b37a 100644 --- a/ts/features/bonus/bpd/store/actions/amount.ts +++ b/ts/features/bonus/bpd/store/actions/amount.ts @@ -1,4 +1,8 @@ -import { ActionType, createAsyncAction } from "typesafe-actions"; +import { + ActionType, + createAsyncAction, + createStandardAction +} from "typesafe-actions"; import { AwardPeriodId, WithAwardPeriodId } from "./periods"; /** diff --git a/ts/features/bonus/bpd/store/reducers/details/transactions.ts b/ts/features/bonus/bpd/store/reducers/details/transactions.ts index d4cb0599d70..e05378191d5 100644 --- a/ts/features/bonus/bpd/store/reducers/details/transactions.ts +++ b/ts/features/bonus/bpd/store/reducers/details/transactions.ts @@ -71,6 +71,6 @@ export const bpdTransactionsForSelectedPeriod = createSelector( ], (transactions, period) => fromNullable(period) - .map(p => transactions[p.awardPeriodId]) + .map(p => fromNullable(transactions[p.awardPeriodId]).getOrElse(pot.none)) .getOrElse(pot.none) ); diff --git a/ts/utils/hooks/usePotValue.ts b/ts/utils/hooks/usePotValue.ts new file mode 100644 index 00000000000..95279b0c7fa --- /dev/null +++ b/ts/utils/hooks/usePotValue.ts @@ -0,0 +1,61 @@ +/* eslint-disable functional/immutable-data */ +import * as pot from "italia-ts-commons/lib/pot"; +import { Millisecond } from "italia-ts-commons/lib/units"; +import { useContext, useEffect, useRef, useState } from "react"; +import { NavigationContext } from "react-navigation"; + +const retryTimeout = 5000 as Millisecond; + +/** + * Load the pot value using the loadAction until is some. Automatically retry using the {@link retryTimeout} + * @param potValue + * @param loadAction + */ +export const useLoadPotValue = ( + id: string, + potValue: pot.Pot, + loadAction: () => void +) => { + const [idState, setId] = useState(""); + const timerRetry = useRef(undefined); + const navigation = useContext(NavigationContext); + const retry = () => { + timerRetry.current = undefined; + loadAction(); + }; + + /** + * When the focus change, clear the timer (if any) and reset the value to undefined + * focus: true -> a new schedule is allowed + * focus: false -> clear all the pending schedule + */ + useEffect(() => { + clearTimeout(timerRetry.current); + timerRetry.current = undefined; + }, [navigation.isFocused(), idState]); + + useEffect(() => { + setId(id); + // Initial state, request the state + if (potValue === pot.none) { + loadAction(); + } else if ( + pot.isNone(potValue) && + pot.isError(potValue) && + timerRetry.current === undefined && + navigation.isFocused() + ) { + // If the pot is NoneError, the navigation focus is on the element + // and no other retry are scheduled + timerRetry.current = setTimeout(retry, retryTimeout); + } + }, [potValue, timerRetry.current, navigation.isFocused(), idState]); + + // Component unmount, clear scheduled + useEffect( + () => () => { + clearTimeout(timerRetry.current); + }, + [] + ); +}; From dd2465dbbf79c00718b5610aecb0967b685222ad Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:33:04 +0100 Subject: [PATCH 15/31] [#175515542] clean --- .../bpd/screens/details/transaction/GoToTransactions.tsx | 2 +- ts/features/bonus/bpd/store/actions/amount.ts | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx index 28d02e6d215..0173da5d62b 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -19,7 +19,7 @@ type Props = ReturnType & ReturnType; /** - * Display the transactions button only if the transactions number are > 0 + * Display the transactions button only if the transactions number are > 0 for the selected period * (never displayed for inactive period) * @param props * @constructor diff --git a/ts/features/bonus/bpd/store/actions/amount.ts b/ts/features/bonus/bpd/store/actions/amount.ts index c448fb1b37a..d1262eb5650 100644 --- a/ts/features/bonus/bpd/store/actions/amount.ts +++ b/ts/features/bonus/bpd/store/actions/amount.ts @@ -1,8 +1,4 @@ -import { - ActionType, - createAsyncAction, - createStandardAction -} from "typesafe-actions"; +import { ActionType, createAsyncAction } from "typesafe-actions"; import { AwardPeriodId, WithAwardPeriodId } from "./periods"; /** From b0840e0a3a6a93d15dafeabc410bbf70828c1660 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:41:53 +0100 Subject: [PATCH 16/31] [#175515542] documentation --- .../base/PaymentMethodBpdToggle.tsx | 2 ++ ts/utils/hooks/usePotValue.ts | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx index c114c44c5e8..18a0f89b091 100644 --- a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx +++ b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx @@ -58,6 +58,8 @@ const styles = StyleSheet.create({ const retryTimeout = 5000 as Millisecond; /** * This custom hook handles the load of the initial state and the retry in case of error. + * TODO: refactor with {@link useLoadPotValue} + * @deprecated * @param props */ const useInitialValue = (props: Props) => { diff --git a/ts/utils/hooks/usePotValue.ts b/ts/utils/hooks/usePotValue.ts index 95279b0c7fa..2a8cb946ec2 100644 --- a/ts/utils/hooks/usePotValue.ts +++ b/ts/utils/hooks/usePotValue.ts @@ -8,8 +8,9 @@ const retryTimeout = 5000 as Millisecond; /** * Load the pot value using the loadAction until is some. Automatically retry using the {@link retryTimeout} - * @param potValue - * @param loadAction + * @param id - the loadRequestId. Should be always the same for the same pot and different, for different pots. + * @param potValue - the value that we would ensure that should be loaded + * @param loadAction - the action that trigger the load of the pot */ export const useLoadPotValue = ( id: string, @@ -25,7 +26,8 @@ export const useLoadPotValue = ( }; /** - * When the focus change, clear the timer (if any) and reset the value to undefined + * When the focus change or the idRequest changes, clear the timer (if any) + * and reset the value to undefined. * focus: true -> a new schedule is allowed * focus: false -> clear all the pending schedule */ From 82f60a38aae28af98f92031a8d27cd803ee9e874 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:53:24 +0100 Subject: [PATCH 17/31] [#175515542] rename --- ts/utils/hooks/{usePotValue.ts => useLoadPotValue.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ts/utils/hooks/{usePotValue.ts => useLoadPotValue.ts} (100%) diff --git a/ts/utils/hooks/usePotValue.ts b/ts/utils/hooks/useLoadPotValue.ts similarity index 100% rename from ts/utils/hooks/usePotValue.ts rename to ts/utils/hooks/useLoadPotValue.ts From 8469eced45cd6d31bb2a4e197ae4db584800e774 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:56:57 +0100 Subject: [PATCH 18/31] [#175515542] fix import --- .../bonus/bpd/screens/details/transaction/GoToTransactions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx index 0173da5d62b..238fe3a4fa6 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -8,7 +8,7 @@ import { Label } from "../../../../../../components/core/typography/Label"; import IconFont from "../../../../../../components/ui/IconFont"; import I18n from "../../../../../../i18n"; import { GlobalState } from "../../../../../../store/reducers/types"; -import { useLoadPotValue } from "../../../../../../utils/hooks/usePotValue"; +import { useLoadPotValue } from "../../../../../../utils/hooks/useLoadPotValue"; import { navigateToBpdTransactions } from "../../../navigation/actions"; import { AwardPeriodId } from "../../../store/actions/periods"; import { bpdTransactionsLoad } from "../../../store/actions/transactions"; From eaef18372b4382bd7d494e24528d7b89a8b65869 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 20:01:23 +0100 Subject: [PATCH 19/31] [#175266374] added comment --- ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts index f58f44a4c74..62f90dbdd5f 100644 --- a/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts +++ b/ts/features/bonus/bpd/store/reducers/details/selectedPeriod.ts @@ -17,8 +17,11 @@ export const bpdSelectedPeriodsReducer = ( action: Action ): BpdPeriod | null => { switch (action.type) { + // The user manually selected a specific period case getType(bpdSelectPeriod): return action.payload; + // The user navigate to BpdDetailsScreen. We use the payload to update the + // selectedPeriod based on the payload case NavigationActions.NAVIGATE: if (action.routeName === BPD_ROUTES.DETAILS) { return action.params?.specificPeriod ?? null; From 53c78c080410329a4b455f4cf4d2c18723b4f434 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 15:16:47 +0100 Subject: [PATCH 20/31] [#174848741] add IbanComponent logic --- locales/en/index.yml | 7 ++ locales/it/index.yml | 7 ++ .../bpd/components/PaymentMethodBpdList.tsx | 1 - ts/features/bonus/bpd/model/RemoteValue.ts | 7 +- .../bpd/saga/orchestration/insertIban.ts | 2 + .../bpd/screens/details/BpdDetailsScreen.tsx | 2 +- .../iban/BaseIbanInformationComponent.tsx | 71 +++++++++++++++++++ .../iban/IbanInformationComponent.tsx | 70 ++++++++++++++++++ .../details/periods/BpdActivePeriod.tsx | 8 ++- .../bonus/bpd/screens/test/TMPBpdScreen.tsx | 3 +- .../bonus/bpd/store/actions/onboarding.ts | 10 ++- .../reducers/details/activation/index.ts | 12 ++++ .../details/activation/payoffInstrument.ts | 3 + .../bpd/store/reducers/onboarding/ongoing.ts | 10 ++- ts/screens/showroom/OthersShowroom.tsx | 2 + .../showroom/core/SelectionShowroom.tsx | 2 + 16 files changed, 207 insertions(+), 10 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx create mode 100644 ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 90cf0ef29c0..838154f5900 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -66,6 +66,7 @@ global: search: Search skip: "Skip" add: Add + edit: "Edit" navigator: messages: messages wallet: payments @@ -1640,6 +1641,12 @@ bonus: text2: "identify a current account that is not registered in your tax code: are you sure you want to use this IBAN?" loading: "We are verifying your IBAN\n\nPlease wait." + details: + components: + iban: + title: "IBAN for accreditation" + noIbanBody: "Set your IBAN in order to receive the accumulated cashback" + button: "Set IBAN" webView: error: missingParams: Not all information necessary to access this page are available diff --git a/locales/it/index.yml b/locales/it/index.yml index 6ee1cdf271f..d55d2c0061a 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -66,6 +66,7 @@ global: search: Ricerca skip: "Salta" add: Aggiungi + edit: "Modifica" navigator: messages: messaggi wallet: pagamenti @@ -1672,6 +1673,12 @@ bonus: text2: "identifica un conto corrente che non risulta intestato al tuo codice fiscale: sei sicuro di voler usare questo IBAN?" loading: "Stiamo verificando il tuo IBAN\n\nTi preghiamo di attendere." + details: + components: + iban: + title: "IBAN per l’accredito" + noIbanBody: "Imposta il tuo IBAN per poter ricevere il cashback accumulato" + button: "Imposta IBAN" webView: error: missingParams: Non sono presenti le informazioni necessarie per accedere a questa pagina diff --git a/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx b/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx index 3d332f6baee..32d71377b4b 100644 --- a/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx +++ b/ts/features/bonus/bpd/components/PaymentMethodBpdList.tsx @@ -11,7 +11,6 @@ type Props = { /** * Render a {@link ReadOnlyArray} of {@link Wallet} using {@link PaymentMethodBpdToggle} - * TODO: after v2, extract foreach Walletv2 the information to render the element * @param props * @constructor */ diff --git a/ts/features/bonus/bpd/model/RemoteValue.ts b/ts/features/bonus/bpd/model/RemoteValue.ts index 3b6951d651d..7ed912d018b 100644 --- a/ts/features/bonus/bpd/model/RemoteValue.ts +++ b/ts/features/bonus/bpd/model/RemoteValue.ts @@ -61,11 +61,12 @@ export const remoteError = (e: E): RemoteError => ({ }); export const fold = ( + rm: RemoteValue, onUndefined: () => B, onLoading: () => B, - onReady: (error: T) => B, - onError: (value: E) => B -) => (rm: RemoteValue): B => { + onReady: (value: T) => B, + onError: (error: E) => B +): B => { switch (rm.kind) { case "undefined": { return onUndefined(); diff --git a/ts/features/bonus/bpd/saga/orchestration/insertIban.ts b/ts/features/bonus/bpd/saga/orchestration/insertIban.ts index d285146131a..f4d906334b8 100644 --- a/ts/features/bonus/bpd/saga/orchestration/insertIban.ts +++ b/ts/features/bonus/bpd/saga/orchestration/insertIban.ts @@ -16,6 +16,7 @@ import { bpdIbanInsertionCancel, bpdIbanInsertionContinue } from "../../store/actions/iban"; +import { bpdOnboardingCompleted } from "../../store/actions/onboarding"; import { isBpdOnboardingOngoing } from "../../store/reducers/onboarding/ongoing"; // TODO: if isOnboarding===true, change with an action that triggers a saga that choose @@ -66,6 +67,7 @@ export function* bpdIbanInsertionWorker() { : navigateToBpdOnboardingNoPaymentMethods(); yield put(nextAction); yield put(navigationHistoryPop(1)); + yield put(bpdOnboardingCompleted()); } else { yield put(NavigationActions.back()); } diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index c1bdb796c23..a9c21ddd14a 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -5,8 +5,8 @@ import { Dispatch } from "redux"; import DarkLayout from "../../../../../components/screens/DarkLayout"; import I18n from "../../../../../i18n"; import { GlobalState } from "../../../../../store/reducers/types"; -import BpdPeriodDetail from "./periods/BpdPeriodDetail"; import BpdPeriodSelector from "./BpdPeriodSelector"; +import BpdPeriodDetail from "./periods/BpdPeriodDetail"; export type Props = ReturnType & ReturnType; diff --git a/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx new file mode 100644 index 00000000000..f240aa585d6 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx @@ -0,0 +1,71 @@ +import { Button, View } from "native-base"; +import * as React from "react"; +import { StyleSheet } from "react-native"; +import { InfoBox } from "../../../../../../../components/box/InfoBox"; +import { Body } from "../../../../../../../components/core/typography/Body"; +import { H4 } from "../../../../../../../components/core/typography/H4"; +import { Label } from "../../../../../../../components/core/typography/Label"; +import { Link } from "../../../../../../../components/core/typography/Link"; +import { Monospace } from "../../../../../../../components/core/typography/Monospace"; +import { IOStyles } from "../../../../../../../components/core/variables/IOStyles"; +import I18n from "../../../../../../../i18n"; + +export type BaseIbanProps = { + iban: string | undefined; + onInsertIban: () => void; +}; + +const styles = StyleSheet.create({ + row: { flexDirection: "row", justifyContent: "space-between" }, + insertIbanButton: { width: "100%" } +}); + +/** + * Render a Infobox that warns the user that should insert the IBAN to receive + * the cashback amount + * @param props + * @constructor + */ +const NoIbanComponent = (props: { onPress: () => void }) => ( + <> + + {I18n.t("bonus.bpd.details.components.iban.noIbanBody")} + + + + +); + +/** + * Display the current IBAN + * @constructor + */ +const IbanComponent = (props: { iban: string }) => ( + {props.iban} +); + +export const BaseIbanInformationComponent: React.FunctionComponent = props => ( + + +

{I18n.t("bonus.bpd.details.components.iban.title")}

+ {props.iban !== undefined && ( + + {I18n.t("global.buttons.edit").toLowerCase()} + + )} +
+ + {props.iban ? ( + + ) : ( + + )} + {/* */} + {/* */} + + +); diff --git a/ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx b/ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx new file mode 100644 index 00000000000..aabfcf98514 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/components/iban/IbanInformationComponent.tsx @@ -0,0 +1,70 @@ +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import Placeholder from "rn-placeholder"; +import { GlobalState } from "../../../../../../../store/reducers/types"; +import { fold, RemoteValue } from "../../../../model/RemoteValue"; +import { bpdIbanInsertionStart } from "../../../../store/actions/iban"; +import { bpdIbanSelector } from "../../../../store/reducers/details/activation"; +import { + BaseIbanInformationComponent, + BaseIbanProps +} from "./BaseIbanInformationComponent"; + +export type Props = ReturnType & + ReturnType; + +const LoadingIban = () => ; + +/** + * Render the Iban based on the RemoteValue. + * For safeness, even undefined, remote and error cases are managed, although the iban detail + * screen is only accessible if bpd has been activated. + * @param props + * @constructor + */ +const RenderRemoteIban = ( + props: { iban: RemoteValue } & Omit< + BaseIbanProps, + "iban" + > +) => + fold( + props.iban, + () => null, + () => , + value => ( + + ), + _ => null + ); + +/** + * Link {@link BaseIbanInformationComponent} to the business logic + * Read the iban RemoteValue from the store + * Dispatch bpdIbanInsertionStart() in case of new iban insertion (or modification + * @param props + * @constructor + */ +const IbanInformationComponent: React.FunctionComponent = props => ( + +); + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + startIbanOnboarding: () => dispatch(bpdIbanInsertionStart()) +}); + +const mapStateToProps = (state: GlobalState) => ({ + iban: bpdIbanSelector(state) +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(IbanInformationComponent); diff --git a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx index 0dcaa57755e..c0dbd32c682 100644 --- a/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx +++ b/ts/features/bonus/bpd/screens/details/periods/BpdActivePeriod.tsx @@ -1,8 +1,11 @@ import * as React from "react"; +import { View } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; import { H1 } from "../../../../../../components/core/typography/H1"; +import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; import { GlobalState } from "../../../../../../store/reducers/types"; +import IbanInformationComponent from "../components/iban/IbanInformationComponent"; export type Props = ReturnType & ReturnType; @@ -12,7 +15,10 @@ export type Props = ReturnType & * @constructor */ const BpdActivePeriod: React.FunctionComponent = () => ( -

Active Period placeholder!

+ +

Active Period placeholder!

+ +
); const mapDispatchToProps = (_: Dispatch) => ({}); diff --git a/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx b/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx index eea2ae8d684..d1ffa84e7ce 100644 --- a/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx +++ b/ts/features/bonus/bpd/screens/test/TMPBpdScreen.tsx @@ -32,6 +32,7 @@ export type Props = ReturnType & const renderBpdActive = (value: RemoteValue) => fold( + value, () => Sconosciuta, () => In caricamento, active => ( @@ -40,7 +41,7 @@ const renderBpdActive = (value: RemoteValue) => ), _ => Errore durante il caricamento - )(value); + ); const renderPaymentMethod = ( potWallets: pot.Pot, Error> diff --git a/ts/features/bonus/bpd/store/actions/onboarding.ts b/ts/features/bonus/bpd/store/actions/onboarding.ts index 71bdf2f2bfa..7034ffcadc6 100644 --- a/ts/features/bonus/bpd/store/actions/onboarding.ts +++ b/ts/features/bonus/bpd/store/actions/onboarding.ts @@ -16,7 +16,7 @@ export const bpdEnrollUserToProgram = createAsyncAction( )(); /** - * delete user from bpd program + * Delete user from bpd program */ export const bpdDeleteUserFromProgram = createAsyncAction( "BPD_DELETE_REQUEST", @@ -45,6 +45,13 @@ export const bpdOnboardingCancel = createStandardAction( "BPD_ONBOARDING_CANCEL" )(); +/** + * The user completed the final step of the onboarding (choose to add iban) + */ +export const bpdOnboardingCompleted = createStandardAction( + "BPD_ONBOARDING_COMPLETED" +)(); + /** * The user accepts and confirms the declaration */ @@ -58,4 +65,5 @@ export type BpdOnboardingActions = | ActionType | ActionType | ActionType + | ActionType | ActionType; diff --git a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts index 388cc55fcb2..6adac994698 100644 --- a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts +++ b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts @@ -1,4 +1,5 @@ import { combineReducers } from "redux"; +import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; import { Action } from "../../../../../../../store/actions/types"; import { GlobalState } from "../../../../../../../store/reducers/types"; @@ -66,4 +67,15 @@ export const bpdEnabledSelector = ( state: GlobalState ): RemoteValue => state.bonus.bpd.details.activation.enabled; +/** + * Return the Iban that the user has entered to receive the cashback amount + */ +export const bpdIbanSelector = createSelector( + [ + (state: GlobalState) => + state.bonus.bpd.details.activation.payoffInstr.enrolledValue + ], + iban => iban +); + export default bpdActivationReducer; diff --git a/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts b/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts index 15626c4a09d..e342b62231b 100644 --- a/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts +++ b/ts/features/bonus/bpd/store/reducers/details/activation/payoffInstrument.ts @@ -17,6 +17,7 @@ import { bpdIbanInsertionResetScreen, bpdUpsertIban } from "../../../actions/iban"; +import { bpdDeleteUserFromProgram } from "../../../actions/onboarding"; type UpsertIBAN = { // the results of the upsert operation @@ -43,6 +44,8 @@ const paymentInstrumentValueReducer = ( action: Action ): RemoteValue => { switch (action.type) { + case getType(bpdDeleteUserFromProgram.success): + return remoteUndefined; case getType(bpdLoadActivationStatus.request): return remoteLoading; case getType(bpdLoadActivationStatus.success): diff --git a/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts b/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts index d6c95473497..0e0e593e52f 100644 --- a/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts +++ b/ts/features/bonus/bpd/store/reducers/onboarding/ongoing.ts @@ -2,7 +2,12 @@ import { getType } from "typesafe-actions"; import { Action } from "../../../../../../store/actions/types"; import { GlobalState } from "../../../../../../store/reducers/types"; import { bpdLoadActivationStatus } from "../../actions/details"; -import { bpdOnboardingCancel, bpdUserActivate } from "../../actions/onboarding"; +import { bpdIbanInsertionCancel } from "../../actions/iban"; +import { + bpdOnboardingCancel, + bpdOnboardingCompleted, + bpdUserActivate +} from "../../actions/onboarding"; /** * This reducers is used to know if a current onboarding is ongoing @@ -17,10 +22,11 @@ const ongoingOnboardingReducer = ( case getType(bpdUserActivate): return true; case getType(bpdOnboardingCancel): + case getType(bpdOnboardingCompleted): + case getType(bpdIbanInsertionCancel): return false; case getType(bpdLoadActivationStatus.success): return action.payload.enabled ? false : state; - // TODO: check when moving the bpdLoadActivationStatus.success in the wallet if the value is ok } return state; }; diff --git a/ts/screens/showroom/OthersShowroom.tsx b/ts/screens/showroom/OthersShowroom.tsx index 827f2dea6ab..acbc690c22e 100644 --- a/ts/screens/showroom/OthersShowroom.tsx +++ b/ts/screens/showroom/OthersShowroom.tsx @@ -3,6 +3,7 @@ import * as React from "react"; import { StyleSheet } from "react-native"; import { InfoBox } from "../../components/box/InfoBox"; import { Body } from "../../components/core/typography/Body"; +import { Label } from "../../components/core/typography/Label"; import { IOStyles } from "../../components/core/variables/IOStyles"; import { ShowroomSection } from "./ShowroomSection"; @@ -19,6 +20,7 @@ const styles = StyleSheet.create({ export const OthersShowroom = () => ( + Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod diff --git a/ts/screens/showroom/core/SelectionShowroom.tsx b/ts/screens/showroom/core/SelectionShowroom.tsx index e6b306d635c..37c459d943c 100644 --- a/ts/screens/showroom/core/SelectionShowroom.tsx +++ b/ts/screens/showroom/core/SelectionShowroom.tsx @@ -2,6 +2,7 @@ import { View } from "native-base"; import * as React from "react"; import { StyleSheet } from "react-native"; import { CheckBox } from "../../../components/core/selection/CheckBox"; +import { Label } from "../../../components/core/typography/Label"; import { ShowroomSection } from "../ShowroomSection"; const styles = StyleSheet.create({ @@ -16,6 +17,7 @@ const styles = StyleSheet.create({ export const SelectionShowroom = () => ( + From bfa0886da127311d51434ce253d6bf330a2df40a Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 15:30:30 +0100 Subject: [PATCH 21/31] [#174848741] fix --- .../bonus/bpd/store/reducers/details/activation/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts index 6adac994698..c36b97a5992 100644 --- a/ts/features/bonus/bpd/store/reducers/details/activation/index.ts +++ b/ts/features/bonus/bpd/store/reducers/details/activation/index.ts @@ -46,7 +46,7 @@ const enabledReducer = ( case getType(bpdEnrollUserToProgram.success): return remoteReady(action.payload.enabled); case getType(bpdDeleteUserFromProgram.success): - return remoteReady(false); + return remoteUndefined; case getType(bpdLoadActivationStatus.failure): case getType(bpdEnrollUserToProgram.failure): return remoteError(action.payload); From d43655fd8878d5e7e0bd5d0e0093928ab5917358 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 15:42:07 +0100 Subject: [PATCH 22/31] [#174848741] clean comments --- .../details/components/iban/BaseIbanInformationComponent.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx index f240aa585d6..eea342d2672 100644 --- a/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx +++ b/ts/features/bonus/bpd/screens/details/components/iban/BaseIbanInformationComponent.tsx @@ -64,8 +64,6 @@ export const BaseIbanInformationComponent: React.FunctionComponent )} - {/* */} - {/* */} ); From 30a71103e5d84e21d6eb9f02c656c4a9438b64f3 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 16:19:28 +0100 Subject: [PATCH 23/31] [#175515542] Stub for bpdtransactionScreen --- locales/en/index.yml | 2 ++ locales/it/index.yml | 2 ++ ts/features/bonus/bpd/navigation/actions.ts | 6 ++++ ts/features/bonus/bpd/navigation/navigator.ts | 4 +++ ts/features/bonus/bpd/navigation/routes.ts | 1 + .../transaction/BpdTransactionsScreen.tsx | 33 +++++++++++++++++++ 6 files changed, 48 insertions(+) create mode 100644 ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 838154f5900..306e246f6b0 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1647,6 +1647,8 @@ bonus: title: "IBAN for accreditation" noIbanBody: "Set your IBAN in order to receive the accumulated cashback" button: "Set IBAN" + transaction: + title: "Your transactions" webView: error: missingParams: Not all information necessary to access this page are available diff --git a/locales/it/index.yml b/locales/it/index.yml index d55d2c0061a..2e9d9ff42b3 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1679,6 +1679,8 @@ bonus: title: "IBAN per l’accredito" noIbanBody: "Imposta il tuo IBAN per poter ricevere il cashback accumulato" button: "Imposta IBAN" + transaction: + title: "Le tue transazioni" webView: error: missingParams: Non sono presenti le informazioni necessarie per accedere a questa pagina diff --git a/ts/features/bonus/bpd/navigation/actions.ts b/ts/features/bonus/bpd/navigation/actions.ts index d26746ffc93..25340e57a41 100644 --- a/ts/features/bonus/bpd/navigation/actions.ts +++ b/ts/features/bonus/bpd/navigation/actions.ts @@ -51,3 +51,9 @@ export const navigateToBpdDetails = (specificPeriod?: BpdPeriod) => routeName: BPD_ROUTES.DETAILS, params: { specificPeriod } }); + +// Transactions +export const navigateToBpdTransactions = () => + NavigationActions.navigate({ + routeName: BPD_ROUTES.TRANSACTIONS + }); diff --git a/ts/features/bonus/bpd/navigation/navigator.ts b/ts/features/bonus/bpd/navigation/navigator.ts index 70721877a68..e2f603ef751 100644 --- a/ts/features/bonus/bpd/navigation/navigator.ts +++ b/ts/features/bonus/bpd/navigation/navigator.ts @@ -1,5 +1,6 @@ import { createStackNavigator } from "react-navigation"; import BpdDetailsScreen from "../screens/details/BpdDetailsScreen"; +import BpdTransactionsScreen from "../screens/details/transaction/BpdTransactionsScreen"; import MainIbanScreen from "../screens/iban/MainIbanScreen"; import BpdInformationScreen from "../screens/onboarding/BpdInformationScreen"; import DeclarationScreen from "../screens/onboarding/declaration/DeclarationScreen"; @@ -36,6 +37,9 @@ const BpdNavigator = createStackNavigator( [BPD_ROUTES.DETAILS]: { screen: BpdDetailsScreen }, + [BPD_ROUTES.TRANSACTIONS]: { + screen: BpdTransactionsScreen + }, // TODO: remove after the introduction of the bpd detail screen [BPD_ROUTES.TEST]: { screen: TMPBpdScreen diff --git a/ts/features/bonus/bpd/navigation/routes.ts b/ts/features/bonus/bpd/navigation/routes.ts index 66c16111f80..71482b1e029 100644 --- a/ts/features/bonus/bpd/navigation/routes.ts +++ b/ts/features/bonus/bpd/navigation/routes.ts @@ -11,6 +11,7 @@ const BPD_ROUTES = { }, IBAN: "BPD_IBAN", DETAILS: "BPD_DETAILS", + TRANSACTIONS: "BPD_TRANSACTIONS", // TODO: remove after the introduction of the bpd detail screen TEST: "BPD_TEST" }; diff --git a/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx new file mode 100644 index 00000000000..595fdd8cf33 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx @@ -0,0 +1,33 @@ +import * as React from "react"; +import { SafeAreaView } from "react-native"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { H1 } from "../../../../../../components/core/typography/H1"; +import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; +import BaseScreenComponent from "../../../../../../components/screens/BaseScreenComponent"; +import I18n from "../../../../../../i18n"; +import { GlobalState } from "../../../../../../store/reducers/types"; + +export type Props = ReturnType & + ReturnType; + +/** + * Display all the transactions for a specific period + * @constructor + */ +const BpdTransactionsScreen: React.FunctionComponent = () => ( + + +

{I18n.t("bonus.bpd.details.transaction.title")}

+
+
+); + +const mapDispatchToProps = (_: Dispatch) => ({}); + +const mapStateToProps = (_: GlobalState) => ({}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(BpdTransactionsScreen); From 32d345b9599093ac3598758008a423ff768d3c8b Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:28:27 +0100 Subject: [PATCH 24/31] [#175515542] GoToTransactionsButton --- locales/en/index.yml | 1 + locales/it/index.yml | 1 + .../base/PaymentMethodBpdToggle.tsx | 2 - .../bonus/bpd/saga/networking/transactions.ts | 24 ++++++- .../bpd/screens/details/BpdDetailsScreen.tsx | 3 + .../transaction/BpdTransactionsScreen.tsx | 8 ++- .../details/transaction/GoToTransactions.tsx | 69 +++++++++++++++++++ ts/features/bonus/bpd/store/actions/amount.ts | 6 +- .../store/reducers/details/transactions.ts | 2 +- ts/utils/hooks/usePotValue.ts | 61 ++++++++++++++++ 10 files changed, 170 insertions(+), 7 deletions(-) create mode 100644 ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx create mode 100644 ts/utils/hooks/usePotValue.ts diff --git a/locales/en/index.yml b/locales/en/index.yml index 306e246f6b0..da91054b709 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1649,6 +1649,7 @@ bonus: button: "Set IBAN" transaction: title: "Your transactions" + goToButton: "Transactions detail" webView: error: missingParams: Not all information necessary to access this page are available diff --git a/locales/it/index.yml b/locales/it/index.yml index 2e9d9ff42b3..ce42b444aea 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1681,6 +1681,7 @@ bonus: button: "Imposta IBAN" transaction: title: "Le tue transazioni" + goToButton: "Dettaglio transazioni" webView: error: missingParams: Non sono presenti le informazioni necessarie per accedere a questa pagina diff --git a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx index 6b5422e7e64..c114c44c5e8 100644 --- a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx +++ b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx @@ -151,10 +151,8 @@ const PaymentMethodActivationToggle: React.FunctionComponent = props => { <> - {/* TODO: The image will be received by props / redux state */} - {/* TODO: The Text will be received by props / redux state */} {props.caption} ) { yield delay(1000); + yield put( - bpdTransactionsLoad.success({ awardPeriodId: action.payload, results: [] }) + bpdTransactionsLoad.failure({ + awardPeriodId: action.payload, + error: new Error() + }) ); + + // yield put( + // bpdTransactionsLoad.success({ + // awardPeriodId: action.payload, + // results: [ + // { + // awardPeriodId: action.payload, + // amount: 100, + // cashback: 10, + // circuitType: "Mastercard", + // hashPan: "1515" as HPan, + // idTrxAcquirer: "123", + // idTrxIssuer: "123", + // trxDate: new Date() + // } + // ] + // }) + // ); } diff --git a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx index a9c21ddd14a..9f533bb74a9 100644 --- a/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/BpdDetailsScreen.tsx @@ -7,6 +7,7 @@ import I18n from "../../../../../i18n"; import { GlobalState } from "../../../../../store/reducers/types"; import BpdPeriodSelector from "./BpdPeriodSelector"; import BpdPeriodDetail from "./periods/BpdPeriodDetail"; +import GoToTransactions from "./transaction/GoToTransactions"; export type Props = ReturnType & ReturnType; @@ -28,6 +29,7 @@ const styles = StyleSheet.create({ height: 60 } }); + /** * The screen that allows the user to see all the details related to the bpd. * @constructor @@ -41,6 +43,7 @@ const BpdDetailsScreen: React.FunctionComponent = () => ( topContent={} gradientHeader={true} hideHeader={true} + footerContent={} > diff --git a/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx index 595fdd8cf33..9aa2ec2964d 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/BpdTransactionsScreen.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { SafeAreaView } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; +import { View } from "native-base"; import { H1 } from "../../../../../../components/core/typography/H1"; import { IOStyles } from "../../../../../../components/core/variables/IOStyles"; import BaseScreenComponent from "../../../../../../components/screens/BaseScreenComponent"; @@ -16,9 +17,12 @@ export type Props = ReturnType & * @constructor */ const BpdTransactionsScreen: React.FunctionComponent = () => ( - + -

{I18n.t("bonus.bpd.details.transaction.title")}

+ + +

{I18n.t("bonus.bpd.details.transaction.title")}

+
); diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx new file mode 100644 index 00000000000..28d02e6d215 --- /dev/null +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -0,0 +1,69 @@ +import { fromNullable } from "fp-ts/lib/Option"; +import * as pot from "italia-ts-commons/lib/pot"; +import * as React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import ButtonDefaultOpacity from "../../../../../../components/ButtonDefaultOpacity"; +import { Label } from "../../../../../../components/core/typography/Label"; +import IconFont from "../../../../../../components/ui/IconFont"; +import I18n from "../../../../../../i18n"; +import { GlobalState } from "../../../../../../store/reducers/types"; +import { useLoadPotValue } from "../../../../../../utils/hooks/usePotValue"; +import { navigateToBpdTransactions } from "../../../navigation/actions"; +import { AwardPeriodId } from "../../../store/actions/periods"; +import { bpdTransactionsLoad } from "../../../store/actions/transactions"; +import { bpdSelectedPeriodSelector } from "../../../store/reducers/details/selectedPeriod"; +import { bpdTransactionsForSelectedPeriod } from "../../../store/reducers/details/transactions"; + +type Props = ReturnType & + ReturnType; + +/** + * Display the transactions button only if the transactions number are > 0 + * (never displayed for inactive period) + * @param props + * @constructor + */ +const GoToTransactions: React.FunctionComponent = props => { + // Load the transactions if not pot.some + + const periodId = fromNullable(props.selectedPeriod) + .map(period => period.awardPeriodId.toString()) + .getOrElse("undefined"); + + useLoadPotValue(periodId, props.transactions, () => + fromNullable(props.selectedPeriod).map(period => + props.loadTransactionsByPeriod(period.awardPeriodId) + ) + ); + const canRenderButton = pot.getOrElse( + pot.map(props.transactions, val => val.length > 0), + false + ); + + return canRenderButton ? ( + + + + + ) : null; +}; + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + goToTransactions: () => dispatch(navigateToBpdTransactions()), + loadTransactionsByPeriod: (periodId: AwardPeriodId) => + dispatch(bpdTransactionsLoad.request(periodId)) +}); + +const mapStateToProps = (state: GlobalState) => ({ + transactions: bpdTransactionsForSelectedPeriod(state), + selectedPeriod: bpdSelectedPeriodSelector(state) +}); + +export default connect(mapStateToProps, mapDispatchToProps)(GoToTransactions); diff --git a/ts/features/bonus/bpd/store/actions/amount.ts b/ts/features/bonus/bpd/store/actions/amount.ts index d1262eb5650..c448fb1b37a 100644 --- a/ts/features/bonus/bpd/store/actions/amount.ts +++ b/ts/features/bonus/bpd/store/actions/amount.ts @@ -1,4 +1,8 @@ -import { ActionType, createAsyncAction } from "typesafe-actions"; +import { + ActionType, + createAsyncAction, + createStandardAction +} from "typesafe-actions"; import { AwardPeriodId, WithAwardPeriodId } from "./periods"; /** diff --git a/ts/features/bonus/bpd/store/reducers/details/transactions.ts b/ts/features/bonus/bpd/store/reducers/details/transactions.ts index d4cb0599d70..e05378191d5 100644 --- a/ts/features/bonus/bpd/store/reducers/details/transactions.ts +++ b/ts/features/bonus/bpd/store/reducers/details/transactions.ts @@ -71,6 +71,6 @@ export const bpdTransactionsForSelectedPeriod = createSelector( ], (transactions, period) => fromNullable(period) - .map(p => transactions[p.awardPeriodId]) + .map(p => fromNullable(transactions[p.awardPeriodId]).getOrElse(pot.none)) .getOrElse(pot.none) ); diff --git a/ts/utils/hooks/usePotValue.ts b/ts/utils/hooks/usePotValue.ts new file mode 100644 index 00000000000..95279b0c7fa --- /dev/null +++ b/ts/utils/hooks/usePotValue.ts @@ -0,0 +1,61 @@ +/* eslint-disable functional/immutable-data */ +import * as pot from "italia-ts-commons/lib/pot"; +import { Millisecond } from "italia-ts-commons/lib/units"; +import { useContext, useEffect, useRef, useState } from "react"; +import { NavigationContext } from "react-navigation"; + +const retryTimeout = 5000 as Millisecond; + +/** + * Load the pot value using the loadAction until is some. Automatically retry using the {@link retryTimeout} + * @param potValue + * @param loadAction + */ +export const useLoadPotValue = ( + id: string, + potValue: pot.Pot, + loadAction: () => void +) => { + const [idState, setId] = useState(""); + const timerRetry = useRef(undefined); + const navigation = useContext(NavigationContext); + const retry = () => { + timerRetry.current = undefined; + loadAction(); + }; + + /** + * When the focus change, clear the timer (if any) and reset the value to undefined + * focus: true -> a new schedule is allowed + * focus: false -> clear all the pending schedule + */ + useEffect(() => { + clearTimeout(timerRetry.current); + timerRetry.current = undefined; + }, [navigation.isFocused(), idState]); + + useEffect(() => { + setId(id); + // Initial state, request the state + if (potValue === pot.none) { + loadAction(); + } else if ( + pot.isNone(potValue) && + pot.isError(potValue) && + timerRetry.current === undefined && + navigation.isFocused() + ) { + // If the pot is NoneError, the navigation focus is on the element + // and no other retry are scheduled + timerRetry.current = setTimeout(retry, retryTimeout); + } + }, [potValue, timerRetry.current, navigation.isFocused(), idState]); + + // Component unmount, clear scheduled + useEffect( + () => () => { + clearTimeout(timerRetry.current); + }, + [] + ); +}; From 1a5557ea992a176b92765b392bd8f2f616113eb4 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:33:04 +0100 Subject: [PATCH 25/31] [#175515542] clean --- .../bpd/screens/details/transaction/GoToTransactions.tsx | 2 +- ts/features/bonus/bpd/store/actions/amount.ts | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx index 28d02e6d215..0173da5d62b 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -19,7 +19,7 @@ type Props = ReturnType & ReturnType; /** - * Display the transactions button only if the transactions number are > 0 + * Display the transactions button only if the transactions number are > 0 for the selected period * (never displayed for inactive period) * @param props * @constructor diff --git a/ts/features/bonus/bpd/store/actions/amount.ts b/ts/features/bonus/bpd/store/actions/amount.ts index c448fb1b37a..d1262eb5650 100644 --- a/ts/features/bonus/bpd/store/actions/amount.ts +++ b/ts/features/bonus/bpd/store/actions/amount.ts @@ -1,8 +1,4 @@ -import { - ActionType, - createAsyncAction, - createStandardAction -} from "typesafe-actions"; +import { ActionType, createAsyncAction } from "typesafe-actions"; import { AwardPeriodId, WithAwardPeriodId } from "./periods"; /** From adb979e5bc015e0a9147331ebc6b11779dac32d5 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:41:53 +0100 Subject: [PATCH 26/31] [#175515542] documentation --- .../base/PaymentMethodBpdToggle.tsx | 2 ++ ts/utils/hooks/usePotValue.ts | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx index c114c44c5e8..18a0f89b091 100644 --- a/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx +++ b/ts/features/bonus/bpd/components/paymentMethodActivationToggle/base/PaymentMethodBpdToggle.tsx @@ -58,6 +58,8 @@ const styles = StyleSheet.create({ const retryTimeout = 5000 as Millisecond; /** * This custom hook handles the load of the initial state and the retry in case of error. + * TODO: refactor with {@link useLoadPotValue} + * @deprecated * @param props */ const useInitialValue = (props: Props) => { diff --git a/ts/utils/hooks/usePotValue.ts b/ts/utils/hooks/usePotValue.ts index 95279b0c7fa..2a8cb946ec2 100644 --- a/ts/utils/hooks/usePotValue.ts +++ b/ts/utils/hooks/usePotValue.ts @@ -8,8 +8,9 @@ const retryTimeout = 5000 as Millisecond; /** * Load the pot value using the loadAction until is some. Automatically retry using the {@link retryTimeout} - * @param potValue - * @param loadAction + * @param id - the loadRequestId. Should be always the same for the same pot and different, for different pots. + * @param potValue - the value that we would ensure that should be loaded + * @param loadAction - the action that trigger the load of the pot */ export const useLoadPotValue = ( id: string, @@ -25,7 +26,8 @@ export const useLoadPotValue = ( }; /** - * When the focus change, clear the timer (if any) and reset the value to undefined + * When the focus change or the idRequest changes, clear the timer (if any) + * and reset the value to undefined. * focus: true -> a new schedule is allowed * focus: false -> clear all the pending schedule */ From c22133127177b90dcf33eedd09e3c447e0200181 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:53:24 +0100 Subject: [PATCH 27/31] [#175515542] rename --- ts/utils/hooks/{usePotValue.ts => useLoadPotValue.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ts/utils/hooks/{usePotValue.ts => useLoadPotValue.ts} (100%) diff --git a/ts/utils/hooks/usePotValue.ts b/ts/utils/hooks/useLoadPotValue.ts similarity index 100% rename from ts/utils/hooks/usePotValue.ts rename to ts/utils/hooks/useLoadPotValue.ts From 33091b0b4f5e966a85088a5e29c5b328e70dafc4 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 30 Oct 2020 19:56:57 +0100 Subject: [PATCH 28/31] [#175515542] fix import --- .../bonus/bpd/screens/details/transaction/GoToTransactions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx index 0173da5d62b..238fe3a4fa6 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -8,7 +8,7 @@ import { Label } from "../../../../../../components/core/typography/Label"; import IconFont from "../../../../../../components/ui/IconFont"; import I18n from "../../../../../../i18n"; import { GlobalState } from "../../../../../../store/reducers/types"; -import { useLoadPotValue } from "../../../../../../utils/hooks/usePotValue"; +import { useLoadPotValue } from "../../../../../../utils/hooks/useLoadPotValue"; import { navigateToBpdTransactions } from "../../../navigation/actions"; import { AwardPeriodId } from "../../../store/actions/periods"; import { bpdTransactionsLoad } from "../../../store/actions/transactions"; From 41e5e5e6546b8ae3606ca676c8a61772f49c2ad1 Mon Sep 17 00:00:00 2001 From: fabriziofff Date: Wed, 4 Nov 2020 18:43:58 +0100 Subject: [PATCH 29/31] Update ts/features/bonus/bpd/store/reducers/details/transactions.ts Co-authored-by: Matteo Boschi --- ts/features/bonus/bpd/store/reducers/details/transactions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/bonus/bpd/store/reducers/details/transactions.ts b/ts/features/bonus/bpd/store/reducers/details/transactions.ts index e05378191d5..38f034690ff 100644 --- a/ts/features/bonus/bpd/store/reducers/details/transactions.ts +++ b/ts/features/bonus/bpd/store/reducers/details/transactions.ts @@ -71,6 +71,6 @@ export const bpdTransactionsForSelectedPeriod = createSelector( ], (transactions, period) => fromNullable(period) - .map(p => fromNullable(transactions[p.awardPeriodId]).getOrElse(pot.none)) + .chain(p => fromNullable(transactions[p.awardPeriodId])) .getOrElse(pot.none) ); From 993de172b56f3561d8c680c3b47c0f85b1b353c9 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 4 Nov 2020 18:45:21 +0100 Subject: [PATCH 30/31] [#175515542] remove useLoadPotValue --- .../screens/details/transaction/GoToTransactions.tsx | 12 ------------ ts/utils/hooks/useLoadPotValue.ts | 1 + 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx index 238fe3a4fa6..d213f04cdb6 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -8,7 +8,6 @@ import { Label } from "../../../../../../components/core/typography/Label"; import IconFont from "../../../../../../components/ui/IconFont"; import I18n from "../../../../../../i18n"; import { GlobalState } from "../../../../../../store/reducers/types"; -import { useLoadPotValue } from "../../../../../../utils/hooks/useLoadPotValue"; import { navigateToBpdTransactions } from "../../../navigation/actions"; import { AwardPeriodId } from "../../../store/actions/periods"; import { bpdTransactionsLoad } from "../../../store/actions/transactions"; @@ -25,17 +24,6 @@ type Props = ReturnType & * @constructor */ const GoToTransactions: React.FunctionComponent = props => { - // Load the transactions if not pot.some - - const periodId = fromNullable(props.selectedPeriod) - .map(period => period.awardPeriodId.toString()) - .getOrElse("undefined"); - - useLoadPotValue(periodId, props.transactions, () => - fromNullable(props.selectedPeriod).map(period => - props.loadTransactionsByPeriod(period.awardPeriodId) - ) - ); const canRenderButton = pot.getOrElse( pot.map(props.transactions, val => val.length > 0), false diff --git a/ts/utils/hooks/useLoadPotValue.ts b/ts/utils/hooks/useLoadPotValue.ts index 2a8cb946ec2..32ab9b54558 100644 --- a/ts/utils/hooks/useLoadPotValue.ts +++ b/ts/utils/hooks/useLoadPotValue.ts @@ -11,6 +11,7 @@ const retryTimeout = 5000 as Millisecond; * @param id - the loadRequestId. Should be always the same for the same pot and different, for different pots. * @param potValue - the value that we would ensure that should be loaded * @param loadAction - the action that trigger the load of the pot + * @deprecated */ export const useLoadPotValue = ( id: string, From bed6138cc1f169feccc1dea9a1d9b2b60d3dd7c8 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 4 Nov 2020 18:49:45 +0100 Subject: [PATCH 31/31] [#175515542] fix ts --- .../bonus/bpd/screens/details/transaction/GoToTransactions.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx index d213f04cdb6..d0cdd4bb6b8 100644 --- a/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx +++ b/ts/features/bonus/bpd/screens/details/transaction/GoToTransactions.tsx @@ -1,4 +1,3 @@ -import { fromNullable } from "fp-ts/lib/Option"; import * as pot from "italia-ts-commons/lib/pot"; import * as React from "react"; import { connect } from "react-redux";