Skip to content

Commit

Permalink
feat: first attempt
Browse files Browse the repository at this point in the history
  • Loading branch information
LazyAfternoons committed Dec 16, 2024
1 parent a363468 commit 90e2226
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 27 deletions.
18 changes: 18 additions & 0 deletions locales/en/wallet.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,23 @@
"generic": {
"notAvailable": "Claim not available"
}
},
"credentials": {
"names": {
"pid": "National ID",
"mdl": "Driver's License",
"unknown": "Unknwon credential"
}
},
"home": {
"addCredential": "Add document",
"badges": {
"saved": "Saved"
}
},
"credentialIssuance": {
"list": {
"title": "What would you like to add to the Wallet?"
}
}
}
58 changes: 58 additions & 0 deletions ts/features/wallet/components/OnboardingModuleCredential.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, {useMemo, memo} from 'react';
import {Badge, IOIcons, ModuleCredential} from '@pagopa/io-app-design-system';
import i18next from 'i18next';
import {
wellKnownCredential,
getCredentialNameByType
} from '../utils/credentials';

type Props = {
type: string;
onPress: (type: string) => void;
isSaved: boolean;
isFetching: boolean;
};

const credentialIconByType: Record<string, IOIcons> = {
[wellKnownCredential.DRIVING_LICENSE]: 'car',
[wellKnownCredential.PID]: 'fingerprint'
};

const activeBadge: Badge = {
variant: 'success',
text: i18next.t('home.badges.saved', {ns: 'wallet'})
};

const OnboardingModuleCredential = ({
type,
onPress,
isSaved,
isFetching
}: Props) => {
const badge = useMemo((): Badge | undefined => {
if (isSaved) {
return activeBadge;
}
return undefined;
}, [isSaved]);

const handleOnPress = () => {
onPress(type);
};

const isPressable = !isSaved;

return (
<ModuleCredential
testID={`${type}ModuleTestID`}
icon={credentialIconByType[type]}
label={getCredentialNameByType(type)}
onPress={isPressable ? handleOnPress : undefined}
isFetching={isFetching}
badge={badge}
/>
);
};

const MemoizedComponent = memo(OnboardingModuleCredential);
export {MemoizedComponent as ItwOnboardingModuleCredential};
66 changes: 42 additions & 24 deletions ts/features/wallet/navigation/WalletNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import Failure from '../screens/pidIssuance/Failure';
import WalletInstanceCreation from '../screens/pidIssuance/WalletInstanceCreation';
import Issuance from '../screens/pidIssuance/Issuance';
import Success from '../screens/pidIssuance/Success';
import IssuanceList from '../screens/credentialIssuance/IssuanceList';
import {lifecycleIsValidSelector} from '../store/lifecycle';
import {useAppSelector} from '../../../store';
import WALLET_ROUTES from './routes';

/**
Expand All @@ -15,6 +18,7 @@ export type WalletNavigatorParamsList = {
[WALLET_ROUTES.PID_ISSUANCE.ISSUANCE]: undefined;
[WALLET_ROUTES.PID_ISSUANCE.SUCCESS]: undefined;
[WALLET_ROUTES.PID_ISSUANCE.FAILURE]: undefined;
[WALLET_ROUTES.CREDENTIAL_ISSUANCE.LIST]: undefined;
};

const Stack = createNativeStackNavigator<WalletNavigatorParamsList>();
Expand All @@ -23,29 +27,43 @@ const Stack = createNativeStackNavigator<WalletNavigatorParamsList>();
* The wallted related stack which is used to navigate between wallet related screens.
* It includes the pid issuance flow.
*/
const WalletNavigator = () => (
<Stack.Navigator
initialRouteName={WALLET_ROUTES.PID_ISSUANCE.INSTANCE_CREATION}
screenOptions={{headerShown: false}}>
<Stack.Group>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.INSTANCE_CREATION}
component={WalletInstanceCreation}
/>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.FAILURE}
component={Failure}
/>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.ISSUANCE}
component={Issuance}
/>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.SUCCESS}
component={Success}
/>
</Stack.Group>
</Stack.Navigator>
);
const WalletNavigator = () => {
const isWalletValid = useAppSelector(lifecycleIsValidSelector);

return (
<Stack.Navigator
initialRouteName={WALLET_ROUTES.PID_ISSUANCE.INSTANCE_CREATION}
screenOptions={{headerShown: false}}>
<Stack.Group>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.INSTANCE_CREATION}
component={WalletInstanceCreation}
/>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.FAILURE}
component={Failure}
/>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.ISSUANCE}
component={Issuance}
/>
<Stack.Screen
name={WALLET_ROUTES.PID_ISSUANCE.SUCCESS}
component={Success}
/>
{
/**
* Screen which should be mounted only if the wallet is valid.
*/
isWalletValid && (
<Stack.Screen
name={WALLET_ROUTES.CREDENTIAL_ISSUANCE.LIST}
component={IssuanceList}
/>
)
}
</Stack.Group>
</Stack.Navigator>
);
};
export default WalletNavigator;
5 changes: 4 additions & 1 deletion ts/features/wallet/navigation/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const WALLET_ROUTES = {
ISSUANCE: 'ISSUANCE',
SUCCESS: 'SUCCESS',
FAILURE: 'FAILURE'
} as const
} as const,
CREDENTIAL_ISSUANCE: {
LIST: 'WALLET_CREDENTIAL_ISSUANCE_LIST'
}
} as const;

export default WALLET_ROUTES;
56 changes: 56 additions & 0 deletions ts/features/wallet/screens/credentialIssuance/IssuanceList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
Badge,
IOVisualCostants,
ListItemHeader,
VStack
} from '@pagopa/io-app-design-system';
import React from 'react';
import {StyleSheet, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useAppSelector} from '../../../../store';
import {lifecycleIsValidSelector} from '../../store/lifecycle';
import {IOScrollViewWithLargeHeader} from '../../../../components/IOScrollViewWithLargeHeader';
import {wellKnownCredential} from '../../utils/credentials';
import {ItwOnboardingModuleCredential} from '../../components/OnboardingModuleCredential';

const IssuanceList = () => {
const isWalletValid = useAppSelector(lifecycleIsValidSelector);
const {t} = useTranslation('wallet');

const activeBadge: Badge = {
variant: 'success',
text: t('home.badges.saved')
};

return (
<IOScrollViewWithLargeHeader
title={{
label: t('credentialIssuance.list.title')
}}>
<View style={styles.wrapper}>
<ListItemHeader label={'TEST'} />
<VStack space={8}>
{Object.entries(wellKnownCredential).map(([_, type]) => (
<ItwOnboardingModuleCredential
key={`itw_credential_${type}`}
type={type}
isSaved={false}
isFetching={false}
onPress={() => void 0}
/>
))}
</VStack>
</View>
</IOScrollViewWithLargeHeader>
);
};

const styles = StyleSheet.create({
wrapper: {
paddingVertical: 16,
paddingHorizontal: IOVisualCostants.appMarginDefault,
gap: 16
}
});

export default IssuanceList;
19 changes: 19 additions & 0 deletions ts/features/wallet/utils/credentials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import i18next from 'i18next';

type CredentialsKeys = 'DRIVING_LICENSE' | 'PID';

export const wellKnownCredential: Record<CredentialsKeys, string> = {
DRIVING_LICENSE: 'MDL',
PID: 'PersonIdentificationData'
};

export const getCredentialNameByType = (type: string): string => {
switch (type) {
case wellKnownCredential.DRIVING_LICENSE:
return i18next.t('credentials.names.mdl', {ns: 'wallet'});
case wellKnownCredential.PID:
return i18next.t('credentials.names.pid', {ns: 'wallet'});
default:
return i18next.t('credentials.names.unknown', {ns: 'wallet'});
}
};
18 changes: 18 additions & 0 deletions ts/i18n/types/resources.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,24 @@ interface Resources {
notAvailable: 'Claim not available';
};
};
credentials: {
names: {
pid: 'National ID';
mdl: "Driver's License";
unknown: 'Unknwon credential';
};
};
home: {
addCredential: 'Add document';
badges: {
saved: 'Saved';
};
};
credentialIssuance: {
list: {
title: 'What would you like to add to the Wallet?';
};
};
};
}

Expand Down
19 changes: 17 additions & 2 deletions ts/screens/WalletHome.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React from 'react';
import {View} from 'react-native';
import {IOStyles, HeaderFirstLevel} from '@pagopa/io-app-design-system';
import {
IOStyles,
HeaderFirstLevel,
ButtonSolid
} from '@pagopa/io-app-design-system';
import {useTranslation} from 'react-i18next';
import {useNavigation} from '@react-navigation/native';
import {useAppSelector} from '../store';
Expand Down Expand Up @@ -39,7 +43,18 @@ const WalletHome = () => {
/>
</View>
) : (
<></> // Needs to
<ButtonSolid
label={t('wallet:home.addCredential')}
accessibilityLabel={t('wallet:home.addCredential')}
onPress={() =>
navigation.navigate('MAIN_WALLET', {
screen: 'WALLET_CREDENTIAL_ISSUANCE_LIST'
})
}
icon="addSmall"
iconPosition="end"
fullWidth={true}
/>
)}
</View>
</>
Expand Down

0 comments on commit 90e2226

Please sign in to comment.