From c89685c1c4f5564491b97d998de4106f0f9359b2 Mon Sep 17 00:00:00 2001 From: Gianluca Spada Date: Thu, 13 Feb 2025 09:52:53 +0100 Subject: [PATCH] chore(IT Wallet): [SIW-1964] Add failure screen for missing credentials in presentation (#6702) > [!WARNING] > Depends on #6694 ## Short description This PR adds a failure screen for missing credentials in the remote presentation flow. Note that since the presentation flow is still a work in progress, the screen is not fully implemented. ## List of changes proposed in this pull request - Improved typing of failure reasons - Added a case for missing credentials ## How to test Currently the only way to test the screen is to mock it, forcing the `MISSING_CREDENTIALS` failure. --------- Co-authored-by: RiccardoMolinari95 --- locales/en/index.yml | 9 +++-- locales/it/index.yml | 9 +++-- .../presentation/remote/machine/failure.ts | 26 +++++++++++--- .../presentation/remote/machine/guards.ts | 6 +++- .../presentation/remote/machine/machine.ts | 3 +- .../remote/screens/ItwRemoteFailureScreen.tsx | 36 +++++++++++++++++-- 6 files changed, 76 insertions(+), 13 deletions(-) diff --git a/locales/en/index.yml b/locales/en/index.yml index fee2783fe42..d301332a4a8 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -3554,8 +3554,13 @@ features: walletInactiveScreen: title: Attiva Documenti su IO per continuare subtitle: Per accedere con IT Wallet ai servizi online è necessario prima attivare la funzionalità Documenti su IO. - continue: Inizia - close: Non ora + primaryAction: Inizia + secondaryAction: Non ora + missingCredentialsScreen: + title: Mancano i dati contenuti in {{credentialName}} + subtitle: Aggiungi il documento al Portafoglio prima di continuare e poi riprova. + primaryAction: Aggiungi documento al Portafoglio + secondaryAction: Annulla trustmark: description: Mostra il QR Code per attestare l’autenticità del documento quando ti viene richiesto. qrCode: QR code autenticità credenziale diff --git a/locales/it/index.yml b/locales/it/index.yml index 81f61aa3b45..aed3527e5f0 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -3554,8 +3554,13 @@ features: walletInactiveScreen: title: Attiva Documenti su IO per continuare subtitle: Per accedere con IT Wallet ai servizi online è necessario prima attivare la funzionalità Documenti su IO. - continue: Inizia - close: Non ora + primaryAction: Inizia + secondaryAction: Non ora + missingCredentialsScreen: + title: Mancano i dati contenuti in {{credentialName}} + subtitle: Aggiungi il documento al Portafoglio prima di continuare e poi riprova. + primaryAction: Aggiungi documento al Portafoglio + secondaryAction: Annulla trustmark: description: Mostra il QR Code per attestare l’autenticità del documento quando ti viene richiesto. qrCode: QR code autenticità credenziale diff --git a/ts/features/itwallet/presentation/remote/machine/failure.ts b/ts/features/itwallet/presentation/remote/machine/failure.ts index 61304533072..fc3ba0e2494 100644 --- a/ts/features/itwallet/presentation/remote/machine/failure.ts +++ b/ts/features/itwallet/presentation/remote/machine/failure.ts @@ -1,15 +1,31 @@ import { RemoteEvents } from "./events.ts"; export enum RemoteFailureType { - UNEXPECTED = "UNEXPECTED", - WALLET_INACTIVE = "WALLET_INACTIVE" + WALLET_INACTIVE = "WALLET_INACTIVE", + MISSING_CREDENTIALS = "MISSING_CREDENTIALS", + UNEXPECTED = "UNEXPECTED" } -export type RemoteFailure = { - type: RemoteFailureType; - reason: unknown; +/** + * Type that maps known reasons with the corresponding failure, in order to avoid unknowns as much as possible. + */ +export type ReasonTypeByFailure = { + [RemoteFailureType.WALLET_INACTIVE]: string; + [RemoteFailureType.MISSING_CREDENTIALS]: { + missingCredentials: Array; + }; + [RemoteFailureType.UNEXPECTED]: unknown; }; +type TypedRemoteFailures = { + [K in RemoteFailureType]: { type: K; reason: ReasonTypeByFailure[K] }; +}; + +/* + * Union type of failures with the reason properly typed. + */ +export type RemoteFailure = TypedRemoteFailures[keyof TypedRemoteFailures]; + /** * Maps an event dispatched by the remote presentation machine to a failure object. * If the event contains an error, it is mapped to an unexpected failure. diff --git a/ts/features/itwallet/presentation/remote/machine/guards.ts b/ts/features/itwallet/presentation/remote/machine/guards.ts index eded7f356b7..8cd59a41daa 100644 --- a/ts/features/itwallet/presentation/remote/machine/guards.ts +++ b/ts/features/itwallet/presentation/remote/machine/guards.ts @@ -7,5 +7,9 @@ export const createRemoteGuardsImplementation = ( ) => ({ isWalletActive: () => itwLifecycleIsValidSelector(store.getState()) && - isItwEnabledSelector(store.getState()) + isItwEnabledSelector(store.getState()), + + areRequiredCredentialsAvailable: () => + // TODO: implementation depends on the remote presentation request + true }); diff --git a/ts/features/itwallet/presentation/remote/machine/machine.ts b/ts/features/itwallet/presentation/remote/machine/machine.ts index 6bdc9c06393..fa09a6538f1 100644 --- a/ts/features/itwallet/presentation/remote/machine/machine.ts +++ b/ts/features/itwallet/presentation/remote/machine/machine.ts @@ -22,7 +22,8 @@ export const itwRemoteMachine = setup({ }, actors: {}, guards: { - isWalletActive: notImplemented + isWalletActive: notImplemented, + areRequiredCredentialsAvailable: notImplemented } }).createMachine({ id: "itwRemoteMachine", diff --git a/ts/features/itwallet/presentation/remote/screens/ItwRemoteFailureScreen.tsx b/ts/features/itwallet/presentation/remote/screens/ItwRemoteFailureScreen.tsx index 72b214e30d8..9ebb643bf2b 100644 --- a/ts/features/itwallet/presentation/remote/screens/ItwRemoteFailureScreen.tsx +++ b/ts/features/itwallet/presentation/remote/screens/ItwRemoteFailureScreen.tsx @@ -12,6 +12,9 @@ import { RemoteFailure, RemoteFailureType } from "../machine/failure.ts"; import { useAvoidHardwareBackButton } from "../../../../../utils/useAvoidHardwareBackButton.ts"; import { useDebugInfo } from "../../../../../hooks/useDebugInfo.ts"; import I18n from "../../../../../i18n.ts"; +import { getCredentialNameFromType } from "../../../common/utils/itwCredentialUtils.ts"; +import { useIONavigation } from "../../../../../navigation/params/AppParamsList.ts"; +import { ITW_ROUTES } from "../../../navigation/routes.ts"; export const ItwRemoteFailureScreen = () => { const failureOption = @@ -30,6 +33,7 @@ type ContentViewProps = { failure: RemoteFailure }; const ContentView = ({ failure }: ContentViewProps) => { const machineRef = ItwRemoteMachineContext.useActorRef(); + const navigation = useIONavigation(); useDebugInfo({ failure: serializeFailureReason(failure) @@ -59,18 +63,46 @@ const ContentView = ({ failure }: ContentViewProps) => { pictogram: "itWallet", action: { label: I18n.t( - "features.itWallet.presentation.remote.walletInactiveScreen.continue" + "features.itWallet.presentation.remote.walletInactiveScreen.primaryAction" ), onPress: () => machineRef.send({ type: "go-to-wallet-activation" }) }, secondaryAction: { label: I18n.t( - "features.itWallet.presentation.remote.walletInactiveScreen.close" + "features.itWallet.presentation.remote.walletInactiveScreen.secondaryAction" ), onPress: () => machineRef.send({ type: "go-to-wallet" }) } }; + case RemoteFailureType.MISSING_CREDENTIALS: { + const [missingCredential] = failure.reason.missingCredentials; // Only consider one credential for now + return { + title: I18n.t( + "features.itWallet.presentation.remote.missingCredentialsScreen.title", + { credentialName: getCredentialNameFromType(missingCredential) } + ), + subtitle: I18n.t( + "features.itWallet.presentation.remote.missingCredentialsScreen.subtitle" + ), + pictogram: "emptyWallet", + action: { + label: I18n.t( + "features.itWallet.presentation.remote.missingCredentialsScreen.primaryAction" + ), + onPress: () => + navigation.navigate(ITW_ROUTES.MAIN, { + screen: ITW_ROUTES.ONBOARDING + }) + }, + secondaryAction: { + label: I18n.t( + "features.itWallet.presentation.remote.missingCredentialsScreen.secondaryAction" + ), + onPress: () => machineRef.send({ type: "go-to-wallet" }) + } + }; + } } };