Skip to content

Commit

Permalink
feat(Carta Giovani Nazionale): [#176961686] Introduces CGN Card Compo…
Browse files Browse the repository at this point in the history
…nent (#2877)

* [#176961686] Adds Card component for animation POC

* [#176961686] cgn card absolute position

* [#176961686] fix

* [#176961686] Temp card component

* [#176961686] Implements CgnCard information container

* [#176961686] Working on card shape

* [#176961686] Adds an alternate card bg and implements the svg random translate functionality

* [#176961686] minor

* [#176961686] Minor fix on border

* Update ts/features/bonus/cgn/components/detail/CgnCardComponent.tsx

Co-authored-by: Matteo Boschi <[email protected]>

* [#176961686] Fixes from review

Co-authored-by: Matteo Boschi <[email protected]>
  • Loading branch information
CrisTofani and Undermaken authored Mar 12, 2021
1 parent 3c08d46 commit d82b6ef
Show file tree
Hide file tree
Showing 7 changed files with 372 additions and 6 deletions.
Binary file added 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 added img/bonus/cgn/card_mask_1.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 added 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.
145 changes: 145 additions & 0 deletions ts/features/bonus/cgn/components/detail/CardSvgPayload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
export const playSvg = (
translationA: string,
translationB: string,
translationC: string
) =>
`<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.8">
<animate
dur='5s'
attributeType="XML"
attributeName='d'
repeatCount='indefinite'
values="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;
M194.63,135c.84-37.64-44.79-53.72-71.1-70.22-27.79-14.71-65-46.45-97.39-25.91C-7.48,56.9,1.38,104.62.3,136c1.14,31.26-7.74,78.81,25.85,96.73,32.38,20.51,69.62-11.14,97.38-25.92C150.54,189.88,196.62,174,194.63,135Z;
M207.46,135c.84-37.64-32.62-72.11-58.93-88.61C120.74,31.72,71.39,18.37,39,38.91,5.35,56.9,1.08,144.11,0,175.46c1.14,31.26,5.39,39.32,39,57.24,32.38,20.51,112.37,25.8,140.12,11C206.12,226.82,209.45,174,207.46,135Z;
M194.63,117.79c.57-21.28-44.79-53.72-71.1-70.21-27.79-14.72-65-46.46-97.39-25.92C-7.48,39.65,1.38,87.37.3,118.72,1.44,150-7.44,197.53,26.15,215.46,58.53,236,139.9,248,167.66,233.24,194.67,216.34,196.62,156.78,194.63,117.79Z;
M215.35,127.15C216.19,89.5,230,21.54,203.71,5.05,175.92-9.67,79.28,10.47,46.87,31,13.24,49,4.75,108.21,3.67,139.56c1.14,31.25,9.61,67.33,43.2,85.25,32.38,20.5,69.62-11.14,97.38-25.92C171.26,182,217.34,166.14,215.35,127.15Z;
M194.63,102.85c.84-37.64-44.79-53.72-71.1-70.21-27.79-14.72-65-46.46-97.39-25.92C-7.48,24.71,1.38,72.43.3,103.79c1.14,31.25-7.74,78.8,25.85,96.73C58.53,221,77.75,130,105.51,115.26,132.52,98.36,196.62,141.84,194.63,102.85Z;
M203.64,125c.84-37.64-57.34-35.13-83.66-51.63C92.19,58.68,49.32-17,16.9,3.51c-33.63,18-6.5,91.1-7.59,122.45,1.14,31.26-7.74,78.81,25.85,96.73,32.39,20.5,69.63-11.14,97.39-25.92C159.56,179.87,205.63,164,203.64,125Z;
M230.27,124c.84-37.64-70.65-97.93-97-114.43C105.52-5.14,44.82,2,12.4,22.58c-33.63,18,11.93,65.54,10.84,96.9,1.14,31.25-44.43,79-10.84,96.9,32.39,20.5,69.63-11.14,97.38-25.92C136.8,173.56,232.26,163,230.27,124Z;
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;"
/>
<animate
attributeName="fill"
dur="10s"
repeatCount="indefinite"
values="#D91120;#7CB3D9;#D91120"
/>
<animateTransform
type="translate"
attributeName="transform"
dur="12s"
begin="0s"
repeatCount="indefinite"
values="${translationA}"
/>
</path>
</g>
</svg>
<svg>
<g transform="scale(0.8) translate(250, 80)">
<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.5">
<animate
dur='6s'
attributeType="XML"
attributeName='d'
repeatCount='indefinite'
values="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;
M194.63,135c.84-37.64-44.79-53.72-71.1-70.22-27.79-14.71-65-46.45-97.39-25.91C-7.48,56.9,1.38,104.62.3,136c1.14,31.26-7.74,78.81,25.85,96.73,32.38,20.51,69.62-11.14,97.38-25.92C150.54,189.88,196.62,174,194.63,135Z;
M207.46,135c.84-37.64-32.62-72.11-58.93-88.61C120.74,31.72,71.39,18.37,39,38.91,5.35,56.9,1.08,144.11,0,175.46c1.14,31.26,5.39,39.32,39,57.24,32.38,20.51,112.37,25.8,140.12,11C206.12,226.82,209.45,174,207.46,135Z;
M194.63,117.79c.57-21.28-44.79-53.72-71.1-70.21-27.79-14.72-65-46.46-97.39-25.92C-7.48,39.65,1.38,87.37.3,118.72,1.44,150-7.44,197.53,26.15,215.46,58.53,236,139.9,248,167.66,233.24,194.67,216.34,196.62,156.78,194.63,117.79Z;
M215.35,127.15C216.19,89.5,230,21.54,203.71,5.05,175.92-9.67,79.28,10.47,46.87,31,13.24,49,4.75,108.21,3.67,139.56c1.14,31.25,9.61,67.33,43.2,85.25,32.38,20.5,69.62-11.14,97.38-25.92C171.26,182,217.34,166.14,215.35,127.15Z;
M194.63,102.85c.84-37.64-44.79-53.72-71.1-70.21-27.79-14.72-65-46.46-97.39-25.92C-7.48,24.71,1.38,72.43.3,103.79c1.14,31.25-7.74,78.8,25.85,96.73C58.53,221,77.75,130,105.51,115.26,132.52,98.36,196.62,141.84,194.63,102.85Z;
M203.64,125c.84-37.64-57.34-35.13-83.66-51.63C92.19,58.68,49.32-17,16.9,3.51c-33.63,18-6.5,91.1-7.59,122.45,1.14,31.26-7.74,78.81,25.85,96.73,32.39,20.5,69.63-11.14,97.39-25.92C159.56,179.87,205.63,164,203.64,125Z;
M230.27,124c.84-37.64-70.65-97.93-97-114.43C105.52-5.14,44.82,2,12.4,22.58c-33.63,18,11.93,65.54,10.84,96.9,1.14,31.25-44.43,79-10.84,96.9,32.39,20.5,69.63-11.14,97.38-25.92C136.8,173.56,232.26,163,230.27,124Z;
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;"
/>
<animate
attributeName="fill"
dur="10s"
repeatCount="indefinite"
values="#008736;#7CB3D9;#008736"
/>
<animateTransform
type="translate"
attributeName="transform"
dur="12s"
begin="0s"
repeatCount="indefinite"
values="${translationB}"
/>
</path>
</g>
<g transform="scale(0.7) translate(-50, 50)">
<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.5">
<animate
dur='10s'
attributeType="XML"
attributeName='d'
repeatCount='indefinite'
values="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;
M194.63,135c.84-37.64-44.79-53.72-71.1-70.22-27.79-14.71-65-46.45-97.39-25.91C-7.48,56.9,1.38,104.62.3,136c1.14,31.26-7.74,78.81,25.85,96.73,32.38,20.51,69.62-11.14,97.38-25.92C150.54,189.88,196.62,174,194.63,135Z;
M207.46,135c.84-37.64-32.62-72.11-58.93-88.61C120.74,31.72,71.39,18.37,39,38.91,5.35,56.9,1.08,144.11,0,175.46c1.14,31.26,5.39,39.32,39,57.24,32.38,20.51,112.37,25.8,140.12,11C206.12,226.82,209.45,174,207.46,135Z;
M194.63,117.79c.57-21.28-44.79-53.72-71.1-70.21-27.79-14.72-65-46.46-97.39-25.92C-7.48,39.65,1.38,87.37.3,118.72,1.44,150-7.44,197.53,26.15,215.46,58.53,236,139.9,248,167.66,233.24,194.67,216.34,196.62,156.78,194.63,117.79Z;
M215.35,127.15C216.19,89.5,230,21.54,203.71,5.05,175.92-9.67,79.28,10.47,46.87,31,13.24,49,4.75,108.21,3.67,139.56c1.14,31.25,9.61,67.33,43.2,85.25,32.38,20.5,69.62-11.14,97.38-25.92C171.26,182,217.34,166.14,215.35,127.15Z;
M194.63,102.85c.84-37.64-44.79-53.72-71.1-70.21-27.79-14.72-65-46.46-97.39-25.92C-7.48,24.71,1.38,72.43.3,103.79c1.14,31.25-7.74,78.8,25.85,96.73C58.53,221,77.75,130,105.51,115.26,132.52,98.36,196.62,141.84,194.63,102.85Z;
M203.64,125c.84-37.64-57.34-35.13-83.66-51.63C92.19,58.68,49.32-17,16.9,3.51c-33.63,18-6.5,91.1-7.59,122.45,1.14,31.26-7.74,78.81,25.85,96.73,32.39,20.5,69.63-11.14,97.39-25.92C159.56,179.87,205.63,164,203.64,125Z;
M230.27,124c.84-37.64-70.65-97.93-97-114.43C105.52-5.14,44.82,2,12.4,22.58c-33.63,18,11.93,65.54,10.84,96.9,1.14,31.25-44.43,79-10.84,96.9,32.39,20.5,69.63-11.14,97.38-25.92C136.8,173.56,232.26,163,230.27,124Z;
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;"
/>
<animate
attributeName="fill"
dur="10s"
repeatCount="indefinite"
values="#7CB3D9;#D91120;#7CB3D9"
/>
<animateTransform
type="translate"
attributeName="transform"
dur="12s"
begin="0s"
repeatCount="indefinite"
values="${translationC}"
/>
</path>
</g>
</svg>
</svg>
`;
188 changes: 188 additions & 0 deletions ts/features/bonus/cgn/components/detail/CgnCardComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import * as React from "react";
import { View } from "native-base";
import WebView from "react-native-webview";
import { Image, ImageBackground, StyleSheet } from "react-native";
import { connect } from "react-redux";
import { IOStyles } from "../../../../../components/core/variables/IOStyles";
import { H5 } from "../../../../../components/core/typography/H5";
import { H3 } from "../../../../../components/core/typography/H3";
import I18n from "../../../../../i18n";
import { Card } from "../../../../../../definitions/cgn/Card";
import { GlobalState } from "../../../../../store/reducers/types";
import { profileNameSurnameSelector } from "../../../../../store/reducers/profile";
import { localeDateFormat } from "../../../../../utils/locale";
import cgnLogo from "../../../../../../img/bonus/cgn/cgn_logo.png";
import cardBg from "../../../../../../img/bonus/cgn/card_mask_1.png";
import { generateRandomSvgMovement, Point } from "../../utils/svgBackground";
import { playSvg } from "./CardSvgPayload";

type Props = {
cgnDetails: Card;
} & ReturnType<typeof mapStateToProps>;

const styles = StyleSheet.create({
cardContainer: {
height: "100%"
},
cgnCard: {
position: "absolute",
width: "100%",
height: 192,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 7
},
shadowOpacity: 0.29,
shadowRadius: 4.65,
zIndex: 7,
elevation: 7,
top: 2
},
informationContainer: {
height: "100%",
top: -190,
zIndex: 9,
elevation: 9
},
spaced: {
justifyContent: "space-between"
},
flex1: {
flex: 1
},
flex2: {
flex: 2
},
paddedContentFull: {
paddingLeft: 16,
paddingTop: 24,
paddingRight: 20,
paddingBottom: 16
},
column: {
flexDirection: "column"
},
fullLogo: {
resizeMode: "contain",
height: 56,
width: 56,
alignSelf: "flex-end"
},
imageFull: {
resizeMode: "stretch",
height: "100%",
zIndex: 8,
elevation: 8
}
});

const minPointA: Point = {
x: 80,
y: -100
};
const maxPointA: Point = {
x: 100,
y: 50
};

const minPointB: Point = {
x: -80,
y: 0
};
const maxPointB: Point = {
x: 100,
y: 10
};

const minPointC: Point = {
x: -50,
y: 50
};
const maxPointC: Point = {
x: 50,
y: 10
};

const MOVEMENT_STEPS = 12;

const CgnCardComponent: React.FunctionComponent<Props> = (props: Props) => {
const generatedTranslationA = generateRandomSvgMovement(
MOVEMENT_STEPS,
minPointA,
maxPointA
);
const generatedTranslationB = generateRandomSvgMovement(
MOVEMENT_STEPS,
minPointB,
maxPointB
);
const generatedTranslationC = generateRandomSvgMovement(
MOVEMENT_STEPS,
minPointC,
maxPointC
);

const generatedSvg = playSvg(
generatedTranslationA,
generatedTranslationB,
generatedTranslationC
);

return (
<View style={[IOStyles.horizontalContentPadding, styles.cgnCard]}>
<ImageBackground
source={cardBg}
imageStyle={[styles.imageFull, { borderRadius: 10 }]}
style={styles.cardContainer}
>
<WebView
style={{ borderRadius: 15, top: -1, left: -1 }}
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]}>
<H3 weight={"Bold"} color={"black"}>
{I18n.t("bonus.cgn.name")}
</H3>
<View>
{props.cgnDetails.status !== "PENDING" && (
<H5>
{`${I18n.t("cardComponent.validUntil")} ${localeDateFormat(
props.cgnDetails.expiration_date,
I18n.t("global.dateFormats.shortFormat")
)}`}
</H5>
)}
{props.currentProfile && (
<H3 weight={"Bold"} color={"black"}>
{props.currentProfile}
</H3>
)}
</View>
</View>
<View style={[styles.column, styles.flex1, styles.spaced]}>
<View hspacer />
<Image source={cgnLogo} style={styles.fullLogo} />
</View>
</View>
</View>
</View>
);
};

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

export default connect(mapStateToProps)(CgnCardComponent);
16 changes: 10 additions & 6 deletions ts/features/bonus/cgn/screens/CgnDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ import CgnStatusDetail from "../components/detail/CgnStatusDetail";
import { availableBonusTypesSelectorFromId } from "../../bonusVacanze/store/reducers/availableBonusesTypes";
import { ID_CGN_TYPE } from "../../bonusVacanze/utils/bonus";
import { navigateToCgnMerchantsList } from "../navigation/actions";
import CgnCardComponent from "../components/detail/CgnCardComponent";

type Props = ReturnType<typeof mapStateToProps> &
ReturnType<typeof mapDispatchToProps>;

const HEADER_BACKGROUND_COLOR = "#7CB3D9";
/**
* Screen to display all the information about the active CGN
*/
Expand All @@ -40,20 +42,22 @@ const CgnDetailScreen = (props: Props): React.ReactElement => {

return (
<BaseScreenComponent
headerBackgroundColor={IOColors.yellowGradientTop}
headerBackgroundColor={HEADER_BACKGROUND_COLOR}
goBack
headerTitle={I18n.t("bonus.cgn.name")}
titleColor={"black"}
contextualHelp={emptyContextualHelp}
>
<SafeAreaView style={IOStyles.flex}>
<ScrollView style={[IOStyles.flex]} bounces={false}>
<LinearGradient
colors={[IOColors.yellowGradientTop, IOColors.yellowGradientBottom]}
>
{/* TODO Add Specific CGN Card element when card is available */}
<View style={{ height: 164 }} />
<LinearGradient colors={[HEADER_BACKGROUND_COLOR, IOColors.bluegrey]}>
<View
style={[IOStyles.horizontalContentPadding, { height: 180 }]}
/>
</LinearGradient>
{props.cgnDetails && (
<CgnCardComponent cgnDetails={props.cgnDetails} />
)}
<View
style={[
IOStyles.flex,
Expand Down
Loading

0 comments on commit d82b6ef

Please sign in to comment.