diff --git a/locales/en/index.yml b/locales/en/index.yml index 452224e12e2..c0334165410 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1,5 +1,5 @@ --- -date: +date: formats: default: "%d/%m/%Y" short: "%d %B" @@ -377,8 +377,8 @@ profile: preferred_language: title: Favourite language subtitle: In which language do you want to use the application? - alert: - title: Do you want to change the language to + alert: + title: Do you want to change the language to subtitle: You'll need to restart the application to make this happen not_selected: Not selected empty: @@ -754,7 +754,7 @@ wallet: incoming: title: "Upcoming" message: "This payment method will be available in a future release" - featured: Highlighted + featured: Highlighted creditCard: onboardingAttempts: title: Attempts to onboard payment method @@ -1117,7 +1117,7 @@ wallet: shortName: "Card" description: The card issued by your bank that you normally use to pay in stores and online pagoPaCapability: - title: In app payments + title: In app payments description: Make payments to the public administration through pagoPA active: Active arriving: Arriving @@ -1146,7 +1146,7 @@ wallet: bancomatPay: name: BANCOMAT Pay description: Pay with BANCOMAT Pay - postepayApp: + postepayApp: name: Postepay description: your Postepay app postepay: @@ -1162,7 +1162,7 @@ wallet: addCardTitle: Card details dummyCard: labels: - holder: + holder: label: Card holder description: base: "Enter as shown on the card" @@ -1260,21 +1260,21 @@ wallet: fallback: title: "Sorry, an unexpected error has occurred" description: "No charges were made." - code1: + code1: title: "Sorry, an unexpected error has occurred" description: "No charges were made." - code2: + code2: title: "Authorization declined" description: "Your bank did not authorize the transaction. Please make sure you enter all the security codes required by your bank correctly." - code4: + code4: title: "Sorry, the session has expired" description: "No charges were made. For your safety, you have 5 minutes to complete the payment." - code7: + code7: title: "There's a problem with your card" description: "No charges were made. For more information, contact your bank." - code8: + code8: title: "The operation was canceled" - code10: + code10: title: "Authorization declined" description: "You have probably reached your card limit. Check with your bank before trying again." addCreditCard: @@ -1344,19 +1344,19 @@ messages: payment: expired: Payment expired paid: This notice is paid. Show the receipt in your - addMemo: - block1: Add a reminder for the + addMemo: + block1: Add a reminder for the block2: at expiringOrValidAlert: block1: This notice will expire on expiredAlert: block1: This notice expired at block2: on - prescription: + prescription: addMemo: This prescription expires the expiringAlert: This prescription expires today expiredAlert: - block1: The prescription expired at + block1: The prescription expired at block2: "on" pay: Pay € {{amount}} onlyPay: Pay @@ -2107,7 +2107,7 @@ bonus: moneyTransfer: "By {{date}} you will receive the transfer on the IBAN you entered." inactivePeriodBody: "You will be able to start collecting valid transactions starting from {{date}}" label: - one: "1 valid transaction" + one: "1 valid transaction" other: "{{transactions}} valid transactions" ranking: title: "Your position" @@ -2131,7 +2131,7 @@ bonus: text2: "at least one payment method " text3: "at Cashback to start collecting necessary transactions" detail: - empty: + empty: text1: "There are no valid transactions yet." text2: "Check back in the next few days!" summary: @@ -2219,6 +2219,14 @@ bonus: merchantsList: navigationTitle: View merchants screenTitle: Select the merchant where you want to buy something + merchantDetail: + title: + deals: Discounts + description: Description + services: Services + hours: Working Hours + cta: + label: Navigate to merchant website cta: activeBonus: Activate your Carta Giovani goToDetail: View your Carta Giovani diff --git a/locales/it/index.yml b/locales/it/index.yml index 5130eb9fb59..2e09fb87f9b 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1,5 +1,5 @@ --- -date: +date: formats: default: "%d/%m/%Y" short: "%d %B" @@ -937,7 +937,7 @@ wallet: title: "Non riusciamo a contattare il server" body: "Siamo al lavoro per risolvere il problema." alert: - supportedCardPageLinkError: Si è verificato un errore durante l'apertura della pagina di riferimento per le carte supportate. + supportedCardPageLinkError: Si è verificato un errore durante l'apertura della pagina di riferimento per le carte supportate. msgErrorUpdateApp: "Si è verificato un errore durante l'apertura dello store delle app" titlePagoPaUpdateApp: Aggiornamento richiesto messagePagoPaUpdateApp: "IO introduce spesso piccole migliorie e nuove funzioni: per continuare ad usare il portafoglio è necessario aggiornare l'applicazione all'ultima versione." @@ -1170,7 +1170,7 @@ wallet: bancomatPay: name: BANCOMAT Pay description: Abbina il tuo account BANCOMAT Pay - postepayApp: + postepayApp: name: Postepay description: la tua app Postepay postepay: @@ -1285,21 +1285,21 @@ wallet: fallback: title: "Spiacenti, si è verificato un errore imprevisto" description: "Non è stato addebitato alcun importo." - code1: + code1: title: "Spiacenti, si è verificato un errore imprevisto" description: "Non è stato addebitato alcun importo." - code2: + code2: title: "Autorizzazione negata" description: "La tua banca non ha autorizzato l’operazione. Controlla di aver inserito correttamente i vari codici richiesti dalla tua banca." - code4: + code4: title: "Spiacenti, la sessione è scaduta" description: "Non è stato addebitato alcun importo. Per la tua sicurezza, hai a disposizione 5 minuti per completare l’operazione." - code7: + code7: title: "C’è un problema con la tua carta" description: "Non è stato addebitato alcun importo. Per maggiori informazioni, contatta la tua banca." - code8: + code8: title: "L’operazione è stata annullata" - code10: + code10: title: "Autorizzazione negata" description: "Probabilmente hai superato il massimale della tua carta. Verifica con la tua banca prima di riprovare." addCreditCard: @@ -2161,7 +2161,7 @@ bonus: text2: "almeno un metodo di pagamento " text3: "al Cashback per iniziare a collezionare le transazioni necessarie" detail: - empty: + empty: text1: "Non ci sono ancora transazioni valide." text2: "Controlla di nuovo nei prossimi giorni!" summary: @@ -2249,6 +2249,14 @@ bonus: merchantsList: navigationTitle: Visualizza esercenti screenTitle: Seleziona l’esercente presso cui vuoi effettuare il tuo acquisto + merchantDetail: + title: + deals: Offerte + description: Descrizione + services: Servizi + hours: Orari + cta: + label: Vai al sito dell'esercente cta: activeBonus: Attiva la tua Carta Giovani goToDetail: Visualizza la Carta Giovani diff --git a/ts/features/bonus/cgn/__mock__/availableMerchantDetail.ts b/ts/features/bonus/cgn/__mock__/availableMerchantDetail.ts new file mode 100644 index 00000000000..926206e2cba --- /dev/null +++ b/ts/features/bonus/cgn/__mock__/availableMerchantDetail.ts @@ -0,0 +1,55 @@ +export type TmpDiscountType = { + category: string; + title: string; + description: string; + validityDescription: string; + discountCode?: string; + conditions: string; + value: number; +}; + +export type TmpMerchantDetail = { + name: string; + cover: string; + location: string; + url: string; + discounts: ReadonlyArray; + description: string; + availableServices: string; + workingHours?: string; +}; + +export const sampleMerchant: TmpMerchantDetail = { + name: "Nome teatro", + url: "https://google.com", + cover: "https://picsum.photos/343/230", + location: "Via Roma 1, 00000, Roma", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sollicitudin dolor ut lacus faucibus lobortis.", + availableServices: + "Tecnologia, Libri, Casa, Cura della persona, Abbigliamento, Giochi, Auto e Moto", + workingHours: "Lun, Mar, Mer, Gio, Dom 9:00 - 23:00 Ven, Sab 9:00 - 00:00", + discounts: [ + { + category: "test category", + title: "Abbonamento stagione danza", + description: + "Acquista un abbonamento per tutti gli spettacoli di danza previsti per la stagione 2021-22.", + validityDescription: "Dal 15 Marzo al 15 Maggio 2021.", + discountCode: "123 456 789 10", + conditions: + "Lo sconto del 30% si applica sull’acquisto di un solo abbonamento. L’offerta è nominale e non è rimborsabile.", + value: 30 + }, + { + category: "test category 2", + title: "Abbonamento stagione danza", + description: + "Acquista un abbonamento per tutti gli spettacoli di danza previsti per la stagione 2021-22.", + validityDescription: "Dal 15 Marzo al 15 Maggio 2021.", + conditions: + "Lo sconto del 30% si applica sull’acquisto di un solo abbonamento. L’offerta è nominale e non è rimborsabile.", + value: 30 + } + ] +}; diff --git a/ts/features/bonus/cgn/components/merchants/CgnMerchantListItem.tsx b/ts/features/bonus/cgn/components/merchants/CgnMerchantListItem.tsx index 53e38b445b2..c53d8f88d7d 100644 --- a/ts/features/bonus/cgn/components/merchants/CgnMerchantListItem.tsx +++ b/ts/features/bonus/cgn/components/merchants/CgnMerchantListItem.tsx @@ -6,6 +6,7 @@ import { H2 } from "../../../../../components/core/typography/H2"; import { Label } from "../../../../../components/core/typography/Label"; import IconFont from "../../../../../components/ui/IconFont"; import { IOColors } from "../../../../../components/core/variables/IOColors"; +import TouchableDefaultOpacity from "../../../../../components/TouchableDefaultOpacity"; type Props = { // FIXME change the props when merchant definition is available @@ -30,7 +31,10 @@ const styles = StyleSheet.create({ * @constructor */ const CgnMerchantListItem: React.FunctionComponent = (props: Props) => ( - + {/* TODO when available and defined the icon name should be defined through a map of category codes */} @@ -44,7 +48,7 @@ const CgnMerchantListItem: React.FunctionComponent = (props: Props) => ( - + ); export default CgnMerchantListItem; diff --git a/ts/features/bonus/cgn/components/merchants/CgnMerchantsDiscountItem.tsx b/ts/features/bonus/cgn/components/merchants/CgnMerchantsDiscountItem.tsx index 21cb52cc0a3..970e8ce5a7c 100644 --- a/ts/features/bonus/cgn/components/merchants/CgnMerchantsDiscountItem.tsx +++ b/ts/features/bonus/cgn/components/merchants/CgnMerchantsDiscountItem.tsx @@ -13,7 +13,7 @@ import { IOStyles } from "../../../../../components/core/variables/IOStyles"; type Props = { category: string; description: string; - value: string; + value: number; }; const PERCENTAGE_SYMBOL = "%"; @@ -62,7 +62,7 @@ const CgnMerchantDiscountItem: React.FunctionComponent = (

{/* avoid overflow */} {WithinRangeInteger(0, 100) - .decode(parseInt(props.value, 10)) + .decode(props.value) .map(v => v.toString()) .getOrElse("-")}

diff --git a/ts/features/bonus/cgn/navigation/actions.ts b/ts/features/bonus/cgn/navigation/actions.ts index 7d15204d222..ad24da34ec6 100644 --- a/ts/features/bonus/cgn/navigation/actions.ts +++ b/ts/features/bonus/cgn/navigation/actions.ts @@ -52,3 +52,8 @@ export const navigateToCgnMerchantsList = () => NavigationActions.navigate({ routeName: CGN_ROUTES.MERCHANTS.LIST }); + +export const navigateToCgnMerchantDetail = () => + NavigationActions.navigate({ + routeName: CGN_ROUTES.MERCHANTS.DETAIL + }); diff --git a/ts/features/bonus/cgn/navigation/navigator.ts b/ts/features/bonus/cgn/navigation/navigator.ts index dff5e1ef7cd..485b3bc492b 100644 --- a/ts/features/bonus/cgn/navigation/navigator.ts +++ b/ts/features/bonus/cgn/navigation/navigator.ts @@ -8,6 +8,7 @@ import CgnActivationIneligibleScreen from "../screens/activation/CgnActivationIn import CgnAlreadyActiveScreen from "../screens/activation/CgnAlreadyActiveScreen"; import CgnDetailScreen from "../screens/CgnDetailScreen"; import MerchantsListScreen from "../screens/merchants/CgnMerchantsListScreen"; +import CgnMerchantDetailScreen from "../screens/merchants/CgnMerchantDetailScreen"; import CGN_ROUTES from "./routes"; const CgnNavigator = createStackNavigator( @@ -36,6 +37,9 @@ const CgnNavigator = createStackNavigator( [CGN_ROUTES.MERCHANTS.LIST]: { screen: MerchantsListScreen }, + [CGN_ROUTES.MERCHANTS.DETAIL]: { + screen: CgnMerchantDetailScreen + }, [CGN_ROUTES.DETAILS]: { screen: CgnDetailScreen } diff --git a/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx b/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx index b0f0fb4d6c3..54cb30fa7e9 100644 --- a/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx +++ b/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react"; import { connect } from "react-redux"; import { View } from "native-base"; import LinearGradient from "react-native-linear-gradient"; -import { SafeAreaView } from "react-native"; +import { SafeAreaView, ScrollView } from "react-native"; import { constNull } from "fp-ts/lib/function"; import { GlobalState } from "../../../../store/reducers/types"; import { Dispatch } from "../../../../store/actions/types"; @@ -27,7 +27,6 @@ import { availableBonusTypesSelectorFromId } from "../../bonusVacanze/store/redu import { ID_CGN_TYPE } from "../../bonusVacanze/utils/bonus"; import { navigateToCgnMerchantsList } from "../navigation/actions"; - type Props = ReturnType & ReturnType; @@ -48,38 +47,40 @@ const CgnDetailScreen = (props: Props): React.ReactElement => { contextualHelp={emptyContextualHelp} > - - {/* TODO Add Specific CGN Card element when card is available */} - - - - {props.cgnDetails && ( - // Renders the message based on the current status of the card - - )} - - - - {/* Ownership block rendering owner's fiscal code */} - - - - {props.cgnDetails && ( - // Renders status information including activation and expiring date and a badge that represents the CGN status - // ACTIVATED - EXPIRED - REVOKED - - )} - - - + + + {/* TODO Add Specific CGN Card element when card is available */} + + + + {props.cgnDetails && ( + // Renders the message based on the current status of the card + + )} + + + + {/* Ownership block rendering owner's fiscal code */} + + + + {props.cgnDetails && ( + // Renders status information including activation and expiring date and a badge that represents the CGN status + // ACTIVATED - EXPIRED - REVOKED + + )} + + + + & + ReturnType; + +const CgnMerchantDetailScreen: React.FunctionComponent = ({ + merchantDetail +}: Props) => { + const renderDiscountListItem = ({ + item + }: ListRenderItemInfo) => ( + + ); + + return ( + + + + + + + + +

{merchantDetail.name}

+

{merchantDetail.location}

+ +

{I18n.t("bonus.cgn.merchantDetail.title.deals")}

+ + +

{I18n.t("bonus.cgn.merchantDetail.title.description")}

+

{merchantDetail.description}

+ +

{I18n.t("bonus.cgn.merchantDetail.title.services")}

+

{merchantDetail.availableServices}

+ +

{I18n.t("bonus.cgn.merchantDetail.title.hours")}

+

{merchantDetail.workingHours}

+ + +
+ openWebUrl(merchantDetail.url), + I18n.t("bonus.cgn.merchantDetail.cta.label") + )} + /> +
+
+ ); +}; + +const mapStateToProps = (_: GlobalState) => ({ + // FIXME replace with the selector when API and store are linked + merchantDetail: sampleMerchant +}); + +const mapDispatchToProps = (_: Dispatch) => ({}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(CgnMerchantDetailScreen); diff --git a/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListScreen.tsx b/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListScreen.tsx index 9ae1c13e4cd..31d87bbb4cf 100644 --- a/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListScreen.tsx +++ b/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListScreen.tsx @@ -2,7 +2,6 @@ import * as React from "react"; import { connect } from "react-redux"; import { FlatList, ListRenderItemInfo, SafeAreaView } from "react-native"; import { Input, Item, View } from "native-base"; -import { nullType } from "io-ts"; import { debounce } from "lodash"; import { Millisecond } from "italia-ts-commons/lib/units"; import { GlobalState } from "../../../../../store/reducers/types"; @@ -18,6 +17,7 @@ import IconFont from "../../../../../components/ui/IconFont"; import { availableMerchants } from "../../__mock__/availableMerchants"; import ItemSeparatorComponent from "../../../../../components/ItemSeparatorComponent"; import { EdgeBorderComponent } from "../../../../../components/screens/EdgeBorderComponent"; +import { navigateToCgnMerchantDetail } from "../../navigation/actions"; type Props = ReturnType & ReturnType; @@ -62,12 +62,17 @@ const CgnMerchantsListScreen: React.FunctionComponent = ( debounceRef.current(searchValue, props.merchants); }, [searchValue, props.merchants]); + const onItemPress = () => { + // TODO Add the dispatch of merchant selected when the complete workflow is available + props.navigateToMerchantDetail(); + }; + const renderListItem = (listItem: ListRenderItemInfo) => ( ); @@ -114,9 +119,8 @@ const mapStateToProps = (_: GlobalState) => ({ merchants: availableMerchants }); -const mapDispatchToProps = (_: Dispatch) => ({ - // FIXME Replace with correct navigation action when available - navigateToMerchantDetail: () => nullType +const mapDispatchToProps = (dispatch: Dispatch) => ({ + navigateToMerchantDetail: () => dispatch(navigateToCgnMerchantDetail()) }); export default connect(