Skip to content

Commit

Permalink
feat: [PE-549] Adopt DS on CGN detail screen (#5651)
Browse files Browse the repository at this point in the history
## Short description
This PR refactors the CGN detail screen to adopt the new DS Components

## List of changes proposed in this pull request
- Changes `CgnDetailScreen`
- Changes every child component for status information rendering

## How to test
Check the CGN detail screen to be properly rendered.


https://github.com/pagopa/io-app/assets/3959405/ccdfff2c-f789-4490-b2a3-00a326af54cc

| CGN Status | Screen |
|--------|--------|
| Active | Check below video 👇 |
| Revoked | <img
src="https://github.com/pagopa/io-app/assets/3959405/33a64029-e6da-4944-a647-13a0ec37a6c0"
height="500" /> |
| Expired | <img
src="https://github.com/pagopa/io-app/assets/3959405/044ac6da-af28-4b6d-883b-8d74f47b9e17"
height="500" /> |

| Eyca Status | Screen |
|--------|--------|
| Active | <img
src="https://github.com/pagopa/io-app/assets/3959405/3bc2dc99-ea1e-4679-abd0-f07047b4bded"
height="500" /> |
| Pending | <img
src="https://github.com/pagopa/io-app/assets/3959405/5e759079-e4c3-4dd5-86c1-52c45147a343"
height="500" /> |
| Error | <img
src="https://github.com/pagopa/io-app/assets/3959405/b02b3a33-f358-48ab-9358-7633d8e66529"
height="500" /> |

---------

Co-authored-by: Fabio Bombardi <[email protected]>
Co-authored-by: Alessandro Izzo <[email protected]>
  • Loading branch information
3 people authored May 8, 2024
1 parent 3ab6f47 commit 33fedf9
Show file tree
Hide file tree
Showing 20 changed files with 645 additions and 892 deletions.
Binary file modified img/bonus/cgn/card_mask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/bonus/cgn/cgn_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/bonus/cgn/eyca_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2600,11 +2600,12 @@ bonus:
allNational: Tutti i punti vendita sul territorio nazionale
cta:
activeBonus: Request your Card
deactivateBonus: Deactivate your Card
deactivateBonus: Deactivate Carta Giovani Nazionale
goToDetail: View your Carta Giovani
detail:
cta:
buyers: Discover the CGN benefits
discover: Discover the benefits
otp: Generate code
eyca:
copy: Copy EYCA's card number
Expand All @@ -2614,8 +2615,8 @@ bonus:
information:
active: "Your card is active and can be used until {{date}}"
warning: "Attention! "
revoked: "This card has been revoked cause {{reason}}"
expired: "This card expired on {{date}}"
revoked: "Attention! This card has been revoked cause {{reason}}"
expired: "Attention! This card expired on {{date}}"
ownership: Who can use this card?
status:
title: Carta Giovani Nazionale (CGN)
Expand All @@ -2631,6 +2632,7 @@ bonus:
revoked: Revoked
expired: Expired
date:
valid_until: "Available until {{date}}"
activated: Activated on
expired: Expired on
revoked: Revoked on
Expand Down
8 changes: 5 additions & 3 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2600,11 +2600,12 @@ bonus:
allNational: Tutti i punti vendita sul territorio nazionale
cta:
activeBonus: Richiedi la Carta
deactivateBonus: Disattiva la Carta
deactivateBonus: Disattiva Carta Giovani Nazionale
goToDetail: Visualizza la Carta
detail:
cta:
buyers: Vedi le opportunità CGN
discover: Scopri le opportunità
otp: Genera codice
eyca:
copy: Copia numero carta EYCA
Expand All @@ -2614,8 +2615,8 @@ bonus:
information:
active: "La carta è attiva e può essere usata fino al {{date}}"
warning: "Attenzione! "
revoked: "Questa carta è stata revocata per {{reason}}"
expired: "Questa carta è scaduta il {{date}}"
revoked: "Attenzione! Questa carta è stata revocata per {{reason}}"
expired: "Attenzione! Questa carta è scaduta il {{date}}"
ownership: Chi può usare la carta?
status:
title: Carta Giovani Nazionale (CGN)
Expand All @@ -2631,6 +2632,7 @@ bonus:
revoked: Revocata
expired: Scaduta
date:
valid_until: "Valida fino al {{date}}"
activated: Attivata il
expired: Scaduta il
revoked: Revocata il
Expand Down
3 changes: 2 additions & 1 deletion ts/features/bonus/cgn/components/detail/CardSvgPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const playSvg = (
translationB: string,
translationC: string
) =>
`<svg width="1000" viewBox = "0 0 300 1000">
`<body style="margin: 0;"><svg width="1000" viewBox = "0 0 300 1000">
<svg>
<g transform="scale(-0.8, 0.8) translate(-200, -100)">
<path d="M210.82,134c.84-37.64-29.89-86.36-56.21-102.85C126.82,16.47,48.61-10.19,16.2,10.36c-33.63,18,1.38,93.26.29,124.61,1.14,31.26-7.74,78.81,25.85,96.73,32.39,20.51,69.63-11.14,97.39-25.92C166.74,188.88,212.81,173,210.82,134Z" fill-opacity="0.6" fill="#AEA5C9">
Expand Down Expand Up @@ -122,4 +122,5 @@ M210.82,134c.84-37.64-29.89-86.36-56.21-102.85C126.82,16.47,48.61-10.19,16.2,10.
</g>
</svg>
</svg>
</body>
`;
174 changes: 76 additions & 98 deletions ts/features/bonus/cgn/components/detail/CgnCardComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,91 +1,72 @@
import { HSpacer } from "@pagopa/io-app-design-system";
import * as React from "react";
import { useEffect } from "react";
import { Image, ImageBackground, StyleSheet, View } from "react-native";
import { widthPercentageToDP } from "react-native-responsive-screen";
import WebView from "react-native-webview";
import { connect } from "react-redux";
import { View, ImageBackground, StyleSheet } from "react-native";
import { widthPercentageToDP } from "react-native-responsive-screen";
import {
Avatar,
H6,
LabelSmall,
Tag,
VSpacer
} from "@pagopa/io-app-design-system";
import { IOStyles } from "../../../../../components/core/variables/IOStyles";
import I18n from "../../../../../i18n";
import { Card } from "../../../../../../definitions/cgn/Card";
import cardBg from "../../../../../../img/bonus/cgn/card_mask.png";
import cgnLogo from "../../../../../../img/bonus/cgn/cgn_logo.png";
import cardBg from "../../../../../../img/bonus/cgn/card_mask.png";
import eycaLogo from "../../../../../../img/bonus/cgn/eyca_logo.png";
import { H3 } from "../../../../../components/core/typography/H3";
import { IOStyles } from "../../../../../components/core/variables/IOStyles";
import I18n from "../../../../../i18n";
import { profileNameSurnameSelector } from "../../../../../store/reducers/profile";
import { GlobalState } from "../../../../../store/reducers/types";
import { eycaDetailSelector } from "../../store/reducers/eyca/details";
import { canEycaCardBeShown } from "../../utils/eyca";
import { useIOSelector } from "../../../../../store/hooks";
import { CardActivated } from "../../../../../../definitions/cgn/CardActivated";
import { formatDateAsShortFormat } from "../../../../../utils/dates";
import { CardRevoked } from "../../../../../../definitions/cgn/CardRevoked";
import { CardExpired } from "../../../../../../definitions/cgn/CardExpired";
import { Point, generateRandomSvgMovement } from "../../utils/svgBackground";
import { playSvg } from "./CardSvgPayload";
import DepartmentLabel from "./DepartmentLabel";

type Props = {
cgnDetails: Card;
onCardLoadEnd: () => void;
} & ReturnType<typeof mapStateToProps>;
};

const styles = StyleSheet.create({
cardContainer: {
height: "100%",
width: widthPercentageToDP(90),
maxWidth: 340
height: 215,
width: widthPercentageToDP(91.5)
},
cgnCard: {
position: "absolute",
alignSelf: "center",
width: widthPercentageToDP(90),
maxWidth: 340,
height: 192,
top: 2
height: 205,
top: 120
},
informationContainer: {
width: widthPercentageToDP(90),
maxWidth: 340,
height: "100%",
top: -190,
zIndex: 9,
top: -205,
zIndex: 2,
elevation: 9
},
spaced: {
justifyContent: "space-between"
},
flex1: {
flex: 1
},
flex2: {
flex: 2
},
paddedContentFull: {
paddingLeft: 16,
paddingTop: 24,
paddingRight: 20,
paddingTop: 8,
paddingBottom: 16
},
column: {
flexDirection: "column"
},
fullLogo: {
resizeMode: "contain",
height: 56,
width: 56,
alignSelf: "flex-end"
},
eycaLogo: {
resizeMode: "contain",
height: 70,
width: 44,
alignSelf: "flex-end",
marginRight: 10
},
imageFull: {
resizeMode: "stretch",
height: 215,
width: widthPercentageToDP(95),
maxWidth: 360,
top: -5,
left: -10,
zIndex: 8
zIndex: 1
},
alignCenter: {
alignItems: "center"
}
});

Expand Down Expand Up @@ -118,7 +99,9 @@ const maxPointC: Point = {

const MOVEMENT_STEPS = 12;

const CgnCardComponent: React.FunctionComponent<Props> = (props: Props) => {
const CgnCardComponent = ({ cgnDetails, onCardLoadEnd }: Props) => {
const eycaDetails = useIOSelector(eycaDetailSelector);

const generatedTranslationA = generateRandomSvgMovement(
MOVEMENT_STEPS,
minPointA,
Expand All @@ -141,10 +124,11 @@ const CgnCardComponent: React.FunctionComponent<Props> = (props: Props) => {
generatedTranslationC
);

const canDisplayEycaLogo = canEycaCardBeShown(props.eycaDetails);
const canCgnLogoBeShown = CardActivated.is(cgnDetails);
const canDisplayEycaLogo =
canCgnLogoBeShown && canEycaCardBeShown(eycaDetails);

// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => () => props.onCardLoadEnd(), []);
useEffect(() => () => onCardLoadEnd(), [onCardLoadEnd]);

return (
<View style={styles.cgnCard} testID={"card-component"}>
Expand All @@ -157,66 +141,60 @@ const CgnCardComponent: React.FunctionComponent<Props> = (props: Props) => {
androidCameraAccessDisabled={true}
androidMicrophoneAccessDisabled={true}
testID={"background-webview"}
onLoadEnd={props.onCardLoadEnd}
onLoadEnd={onCardLoadEnd}
source={{
html: generatedSvg
}}
/>
</ImageBackground>
<View style={[styles.informationContainer, styles.paddedContentFull]}>
<View
style={[
IOStyles.row,
IOStyles.flex,
{ justifyContent: "space-between" }
]}
>
<View style={[styles.column, styles.flex2, styles.spaced]}>
<View>
<H3 weight={"Bold"} color={"black"}>
{I18n.t("bonus.cgn.name")}
</H3>
<DepartmentLabel>
{I18n.t("bonus.cgn.departmentName")}
</DepartmentLabel>
</View>
<View>
{props.currentProfile && (
<H3
weight={"Bold"}
color={"black"}
testID={"profile-name-surname"}
>
{props.currentProfile}
</H3>
)}
</View>
<View style={[IOStyles.flex, styles.spaced]}>
<View style={[IOStyles.rowSpaceBetween, styles.alignCenter]}>
<H6 color={"blueIO-850"}>{I18n.t("bonus.cgn.name")}</H6>
{canCgnLogoBeShown && <Avatar logoUri={cgnLogo} size="small" />}
{CardRevoked.is(cgnDetails) && (
<Tag
testID="card-status-revoked"
variant="error"
text={I18n.t("bonus.cgn.detail.status.badge.revoked")}
/>
)}
{CardExpired.is(cgnDetails) && (
<Tag
testID="card-status-expired"
variant="error"
text={I18n.t("bonus.cgn.detail.status.badge.expired")}
/>
)}
</View>
<View style={[styles.column, styles.flex1, styles.spaced]}>
<View style={[IOStyles.rowSpaceBetween, styles.alignCenter]}>
<LabelSmall style={{ flex: 2 }} color="blueIO-850">
{I18n.t("bonus.cgn.departmentName")}
</LabelSmall>
<View style={{ flex: 1 }} />
</View>
<View style={[IOStyles.rowSpaceBetween, styles.alignCenter]}>
{CardActivated.is(cgnDetails) && (
<LabelSmall
color={"blueIO-850"}
style={IOStyles.flex}
testID={"card-bottom-content"}
>
{I18n.t("bonus.cgn.detail.status.date.valid_until", {
date: formatDateAsShortFormat(cgnDetails.expiration_date)
})}
</LabelSmall>
)}
{canDisplayEycaLogo ? (
<Image
accessibilityIgnoresInvertColors
source={eycaLogo}
style={styles.eycaLogo}
/>
<Avatar logoUri={eycaLogo} size="small" />
) : (
<HSpacer size={16} />
<VSpacer size={40} />
)}
<Image
accessibilityIgnoresInvertColors
source={cgnLogo}
style={styles.fullLogo}
/>
</View>
</View>
</View>
</View>
);
};

const mapStateToProps = (state: GlobalState) => ({
currentProfile: profileNameSurnameSelector(state),
eycaDetails: eycaDetailSelector(state)
});

export default connect(mapStateToProps)(CgnCardComponent);
export default CgnCardComponent;
Loading

0 comments on commit 33fedf9

Please sign in to comment.