Skip to content

Commit

Permalink
chore(IT Wallet): [SIW-1536] Add skeumorphic card in MDL details scre…
Browse files Browse the repository at this point in the history
…en (#6144)

## Short description
This PR adds the skeumorphic card in the credential details screen.
The skeumorphic card is rendered only if the credential supports it (at
the time of opening this PR only the Driving License is supported).

## List of changes proposed in this pull request
- Updated `io-app-design-system` to `1.46.0`
- Added background as a fall back while the `ItwSkeumorphicCard`
background is being loaded
- Added the `ItwSkeumorphicCard` component in the details screen for
credentials which sopport it

## How to test
Open the details screen of your MDL credential, check that the card is
rendered correctly and you can flip it.

## Preview


https://github.com/user-attachments/assets/5bbce011-919c-4c90-8701-c736bbce70de

---------

Co-authored-by: LazyAfternoons <[email protected]>
  • Loading branch information
mastro993 and LazyAfternoons authored Sep 10, 2024
1 parent eff0eab commit 5002894
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 51 deletions.
1 change: 1 addition & 0 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3292,6 +3292,7 @@ features:
confirm: Sì, rimuovi
toast:
removed: Fatto! Hai rimosso {{credentialName}}
flipCard: "Show back"
trialSystem:
toast:
subscribed: Done! You will receive a message when the trial period will begin.
Expand Down
1 change: 1 addition & 0 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3292,6 +3292,7 @@ features:
confirm: Sì, rimuovi
toast:
removed: Fatto! Hai rimosso {{credentialName}}
flipCard: "Mostra retro"
trialSystem:
toast:
subscribed: Fatto! Riceverai un messaggio all’avvio della sperimentazione
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"dependencies": {
"@babel/plugin-transform-regenerator": "^7.18.6",
"@gorhom/bottom-sheet": "^4.1.5",
"@pagopa/io-app-design-system": "1.45.0",
"@pagopa/io-app-design-system": "1.46.0",
"@pagopa/io-pagopa-commons": "^3.1.0",
"@pagopa/io-react-native-crypto": "^0.3.0",
"@pagopa/io-react-native-http-client": "1.0.5",
Expand Down
33 changes: 31 additions & 2 deletions ts/features/design-system/core/DSCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ import {
VStack
} from "@pagopa/io-app-design-system";
import * as React from "react";
import { Alert, ScrollView } from "react-native";
import { Alert, Pressable, ScrollView } from "react-native";
import { CgnCard } from "../../bonus/cgn/components/CgnCard";
import { IdPayCard } from "../../idpay/wallet/components/IdPayCard";
import { ItwCredentialCard } from "../../itwallet/common/components/ItwCredentialCard";
import { CredentialType } from "../../itwallet/common/utils/itwMocksUtils";
import {
ItwSkeumorphicCard,
ItwSkeumorphicCardProps
} from "../../itwallet/common/components/ItwSkeumorphicCard";
import {
CredentialType,
ItwStoredCredentialsMocks
} from "../../itwallet/common/utils/itwMocksUtils";
import { PaymentCard } from "../../payments/common/components/PaymentCard";
import { PaymentCardBig } from "../../payments/common/components/PaymentCardBig";
import { PaymentCardSmall } from "../../payments/common/components/PaymentCardSmall";
Expand Down Expand Up @@ -436,6 +443,15 @@ const ItwCards = () => (
</DSComponentViewerBox>
</VStack>
</DesignSystemSection>
<DesignSystemSection title="Skeumorphic Driving License">
<VStack space={componentMargin}>
<DSComponentViewerBox name="Valid">
<ItwSkeumorphicCardPreview
credential={ItwStoredCredentialsMocks.mdl}
/>
</DSComponentViewerBox>
</VStack>
</DesignSystemSection>
<DesignSystemSection title="Disability Card">
<VStack space={componentMargin}>
<DSComponentViewerBox name="Preview">
Expand Down Expand Up @@ -505,6 +521,19 @@ const ItwCards = () => (
</VStack>
);

const ItwSkeumorphicCardPreview = (props: ItwSkeumorphicCardProps) => {
const [isFlipped, setIsFlipped] = React.useState(false);
return (
<Pressable
onPress={() => setIsFlipped(!isFlipped)}
accessibilityRole="button"
accessibilityLabel="Flip card"
>
<ItwSkeumorphicCard {...props} isFlipped={isFlipped} />
</Pressable>
);
};

// for testing reasons, abi codes can be found here:
// https://www.comuniecitta.it/elenco-banche-per-codice-abi
export const DSCards = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IOColors } from "@pagopa/io-app-design-system";
import React from "react";
import { ImageSourcePropType, StyleSheet } from "react-native";
import { ImageSourcePropType, StyleSheet, View } from "react-native";
import { AnimatedImage } from "../../../../../components/AnimatedImage";
import { StoredCredential } from "../../utils/itwTypesUtils";
import { CardSide } from "./types";
Expand All @@ -19,7 +20,11 @@ const CardBackground = ({ credentialType, side }: CardBackgroundProps) => {
return null;
}

return <AnimatedImage source={cardAssets[side]} style={styles.background} />;
return (
<View style={styles.wrapper}>
<AnimatedImage source={cardAssets[side]} style={styles.background} />
</View>
);
};

type CardAssets = Record<CardSide, ImageSourcePropType>;
Expand All @@ -35,6 +40,10 @@ const assetsMap: Record<string, CardAssets> = {
};

const styles = StyleSheet.create({
wrapper: {
backgroundColor: IOColors["grey-100"],
borderRadius: 8
},
background: {
width: "100%",
height: "100%"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
ButtonLink,
IOSpacingScale,
VStack
} from "@pagopa/io-app-design-system";
import React from "react";
import { StyleSheet, View } from "react-native";
import I18n from "../../../../i18n";
import { ItwCredentialCard } from "../../common/components/ItwCredentialCard";
import { ItwSkeumorphicCard } from "../../common/components/ItwSkeumorphicCard";
import { CredentialType } from "../../common/utils/itwMocksUtils";
import { getThemeColorByCredentialType } from "../../common/utils/itwStyleUtils";
import { StoredCredential } from "../../common/utils/itwTypesUtils";
import { getCredentialExpireStatus } from "../../common/utils/itwClaimsUtils";

type Props = {
credential: StoredCredential;
};

/**
* This component renders the credential card in the presentation screen.
* If the credential supports the skeumorphic card, it also renders it with the flip button.
*/
const ItwPresentationCredentialCard = ({ credential }: Props) => {
const [isFlipped, setIsFlipped] = React.useState(false);
const themeColor = getThemeColorByCredentialType(
credential.credentialType as CredentialType
);

const hasSkeumorphicCard =
credential.credentialType === CredentialType.DRIVING_LICENSE;

const credentialStatus = getCredentialExpireStatus(
credential.parsedCredential
);

if (hasSkeumorphicCard) {
return (
<VStack space={8}>
<Wrapper backgroundColor={themeColor}>
<ItwSkeumorphicCard credential={credential} isFlipped={isFlipped} />
</Wrapper>
<View style={styles.flipButton}>
<ButtonLink
label={I18n.t(
"features.itWallet.presentation.credentialDetails.flipCard"
)}
onPress={() => setIsFlipped(_ => !_)}
icon="switchCard"
iconPosition="end"
/>
</View>
</VStack>
);
}

return (
<Wrapper backgroundColor={themeColor}>
<ItwCredentialCard
credentialType={credential.credentialType}
status={credentialStatus}
/>
</Wrapper>
);
};

type WrapperProps = {
children: React.ReactNode;
backgroundColor: string;
};

const Wrapper = ({ children, backgroundColor }: WrapperProps) => (
<View style={styles.cardContainer}>
{children}
<View style={[styles.cardBackdrop, { backgroundColor }]} />
</View>
);

const cardPaddingHorizontal: IOSpacingScale = 16;

const styles = StyleSheet.create({
cardContainer: {
position: "relative",
paddingHorizontal: cardPaddingHorizontal
},
cardBackdrop: {
height: "200%", // Twice the card in order to avoid the white background when the scrollview bounces
position: "absolute",
top: "-130%", // Offset by the card height + a 30%
right: 0,
left: 0,
zIndex: -1
},
flipButton: {
alignSelf: "center"
}
});

export { ItwPresentationCredentialCard };
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import {
ContentWrapper,
IOSpacingScale,
VSpacer
} from "@pagopa/io-app-design-system";
import { ContentWrapper, VSpacer } from "@pagopa/io-app-design-system";
import * as O from "fp-ts/Option";
import { pipe } from "fp-ts/lib/function";
import React from "react";
import { ScrollView, StyleSheet, View } from "react-native";
import { ScrollView } from "react-native";
import FocusAwareStatusBar from "../../../../components/ui/FocusAwareStatusBar";
import { useDebugInfo } from "../../../../hooks/useDebugInfo";
import { useHeaderSecondLevel } from "../../../../hooks/useHeaderSecondLevel";
import { useScreenEndMargin } from "../../../../hooks/useScreenEndMargin";
import I18n from "../../../../i18n";
import { IOStackNavigationRouteProps } from "../../../../navigation/params/AppParamsList";
import { useIOSelector } from "../../../../store/hooks";
import { ItwCredentialCard } from "../../common/components/ItwCredentialCard";
import { ItwGenericErrorContent } from "../../common/components/ItwGenericErrorContent";
import { getHumanReadableParsedCredential } from "../../common/utils/debug";
import { CredentialType } from "../../common/utils/itwMocksUtils";
Expand All @@ -24,8 +19,8 @@ import { itwCredentialByTypeSelector } from "../../credentials/store/selectors";
import { ItwParamsList } from "../../navigation/ItwParamsList";
import { ItwPresentationAlertsSection } from "../components/ItwPresentationAlertsSection";
import { ItwPresentationClaimsSection } from "../components/ItwPresentationClaimsSection";
import { ItwPresentationCredentialCard } from "../components/ItwPresentationCredentialCard";
import { ItwPresentationDetailFooter } from "../components/ItwPresentationDetailFooter";
import { getCredentialStatus } from "../../common/utils/itwClaimsUtils";

export type ItwPresentationCredentialDetailNavigationParams = {
credentialType: string;
Expand Down Expand Up @@ -75,24 +70,14 @@ const ContentView = ({ credential }: ContentProps) => {
)
});

const credentialStatus = getCredentialStatus(credential);

return (
<>
<FocusAwareStatusBar
backgroundColor={themeColor}
barStyle="light-content"
/>
<ScrollView contentContainerStyle={{ paddingBottom: screenEndMargin }}>
<View style={styles.cardContainer}>
<ItwCredentialCard
credentialType={credential.credentialType}
status={credentialStatus}
/>
<View
style={[styles.cardBackdrop, { backgroundColor: themeColor }]}
/>
</View>
<ItwPresentationCredentialCard credential={credential} />
<ContentWrapper>
<VSpacer size={16} />
<ItwPresentationAlertsSection credential={credential} />
Expand All @@ -111,20 +96,3 @@ const ContentView = ({ credential }: ContentProps) => {
</>
);
};

const cardPaddingHorizontal: IOSpacingScale = 16;

const styles = StyleSheet.create({
cardContainer: {
position: "relative",
paddingHorizontal: cardPaddingHorizontal
},
cardBackdrop: {
height: "200%", // Twice the card in order to avoid the white background when the scrollview bounces
position: "absolute",
top: "-130%", // Offset by the card height + a 30%
right: 0,
left: 0,
zIndex: -1
}
});
15 changes: 5 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2046,10 +2046,10 @@
dependencies:
"@types/node" ">= 8"

"@pagopa/io-app-design-system@1.45.0":
version "1.45.0"
resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.45.0.tgz#a04b7d2a192ddf125726e533392fb2b12b007339"
integrity sha512-ALMCET2jktso6F87BzzJVdTN1eoFNsCaVnh5mBObiziOMHMuAhBrXumFDXSzgayNpjvroQ3OSa49ELpwFyO36w==
"@pagopa/io-app-design-system@1.46.0":
version "1.46.0"
resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.46.0.tgz#b8605df8131f487d7325a46653588fac9a186244"
integrity sha512-z7q4/O0iyIXm6L6WrZXktzZ0kc317mRtfWwEEJwHuMaOca9Uj8YtcmRyluLtbE1OXUPcBh57ebsLs+o6JSEwoA==
dependencies:
"@pagopa/ts-commons" "^12.0.0"
"@testing-library/jest-native" "^5.4.2"
Expand Down Expand Up @@ -16547,7 +16547,7 @@ [email protected]:
commander "^2.20.3"
cssfilter "0.0.10"

"xstate5@npm:xstate@5":
"xstate5@npm:xstate@5", xstate@^5.13.0:
version "5.13.0"
resolved "https://registry.yarnpkg.com/xstate/-/xstate-5.13.0.tgz#7f7092d813a89d94024b083fe23a86b6cf4a323a"
integrity sha512-Z0om784N5u8sAzUvQJBa32jiTCIGGF/2ZsmKkerQEqeeUktAeOMK20FIHFUMywC4GcAkNksSvaeX7lwoRNXPEQ==
Expand All @@ -16557,11 +16557,6 @@ xstate@^4.29.0, xstate@^4.33.6:
resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.35.4.tgz#87b2a45b6c7e84d820f56378408c6531ca5c4662"
integrity sha512-mqRBYHhljP1xIItI4xnSQNHEv6CKslSM1cOGmvhmxeoDPAZgNbhSUYAL5N6DZIxRfpYY+M+bSm3mUFHD63iuvg==

xstate@^5.13.0:
version "5.13.0"
resolved "https://registry.yarnpkg.com/xstate/-/xstate-5.13.0.tgz#7f7092d813a89d94024b083fe23a86b6cf4a323a"
integrity sha512-Z0om784N5u8sAzUvQJBa32jiTCIGGF/2ZsmKkerQEqeeUktAeOMK20FIHFUMywC4GcAkNksSvaeX7lwoRNXPEQ==

xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
Expand Down

0 comments on commit 5002894

Please sign in to comment.