Skip to content

Instantly share code, notes, and snippets.

@ericlewis
Last active April 5, 2020 19:04
Show Gist options
  • Save ericlewis/15eef6a650470f0e21913774666eb100 to your computer and use it in GitHub Desktop.
Save ericlewis/15eef6a650470f0e21913774666eb100 to your computer and use it in GitHub Desktop.
import React, { useEffect, useRef } from "react";
import {
Animated,
Dimensions,
Image,
StyleSheet,
Text,
TouchableOpacity,
} from "react-native";
import Config from "react-native-config";
import {
accelerometer,
SensorTypes,
setUpdateIntervalForType,
} from "react-native-sensors";
import { FetchDetailedUserInfoVirtualCard } from "../screens/__generated__/components";
import { generateRandomTitle } from "../utils";
import { useClipboard, useDialogReducer } from "../utils/hooks";
import { DialogView } from "./dialog";
import { Flex } from "./flex";
import { Row } from "./row";
setUpdateIntervalForType(SensorTypes.accelerometer, 50);
const { width } = Dimensions.get("window");
const WIDTH = width / 3;
const HEIGHT = WIDTH * 1.5;
const MAX_X_VAL = WIDTH / 2;
const MAX_Y_VAL = HEIGHT / 2;
interface Props {
virtualCard: FetchDetailedUserInfoVirtualCard;
name: string;
cardShowing: boolean;
pressedCard?: any;
}
export const Card: React.FunctionComponent<Props> = ({
virtualCard,
name,
pressedCard,
cardShowing,
}) => {
const dialog = useDialogReducer();
const Clipboard = useClipboard();
const xVal = useRef(new Animated.Value(0)).current;
const yVal = useRef(new Animated.Value(0)).current;
useEffect(() => {
if (!Config.SIMULATOR) {
const subscription = accelerometer.subscribe(
({ x, y }: { x: number; y: number }) => {
Animated.timing(xVal, {
toValue: x,
duration: 100,
useNativeDriver: true,
}).start();
Animated.timing(yVal, {
toValue: y,
duration: 100,
useNativeDriver: true,
}).start();
},
);
return () => subscription.unsubscribe();
}
}, []);
return (
<TouchableOpacity activeOpacity={1} onPress={pressedCard}>
<Animated.View style={styles.container}>
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
backgroundColor: "#6E62EE",
opacity: xVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [0, 1, 0],
extrapolate: "clamp",
}),
borderRadius: 10,
shadowColor: "#000000",
shadowRadius: 4,
shadowOpacity: 1,
shadowOffset: { height: 0, width: 0 },
}}
/>
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
backgroundColor: "#6E62EE",
opacity: xVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [0, 0, 1],
extrapolate: "clamp",
}),
borderRadius: 10,
shadowColor: "#000000",
shadowRadius: 4,
shadowOpacity: 1,
shadowOffset: { height: 0, width: 4 },
}}
/>
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
backgroundColor: "#6E62EE",
opacity: xVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [1, 0, 0],
extrapolate: "clamp",
}),
borderRadius: 10,
shadowColor: "#000000",
shadowRadius: 4,
shadowOpacity: 1,
shadowOffset: { height: 0, width: -4 },
}}
/>
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
backgroundColor: "#6E62EE",
opacity: yVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [0, 0, 1],
extrapolate: "clamp",
}),
borderRadius: 10,
shadowColor: "#000000",
shadowRadius: 4,
shadowOpacity: 1,
shadowOffset: { height: -4, width: 0 },
}}
/>
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
overflow: "hidden",
alignItems: "center",
}}
>
<Animated.Image
source={require("../assets/images/specular.png")}
style={{
opacity: xVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [0.5, 0.25, 0.5],
extrapolate: "clamp",
}),
transform: [
{ scale: 2 },
{
translateX: xVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [MAX_X_VAL, 0, -MAX_X_VAL],
extrapolate: "clamp",
}),
},
{
translateY: yVal.interpolate({
inputRange: [-1, 0, 1],
outputRange: [-MAX_Y_VAL, 0, MAX_Y_VAL],
extrapolate: "clamp",
}),
},
],
}}
/>
</Animated.View>
<Row>
<Image source={require("../assets/images/card/logo.png")} />
<Flex />
<Image source={require("../assets/images/card/amex.png")} />
</Row>
<Flex flex={2} />
<Text
style={[
styles.text,
{
alignSelf: "flex-end",
fontSize: 18,
},
]}
onPress={() => {
Clipboard.setString(virtualCard.cvv);
dialog.show({
message: "CVV copied to clipboard",
title: generateRandomTitle(),
});
}}
>
{cardShowing && virtualCard.cvv}
</Text>
<Flex flex={4} />
<Text
style={[
styles.text,
{
fontSize: 22,
},
]}
onPress={() => {
Clipboard.setString(virtualCard.fullNumber);
dialog.show({
message: "Card number copied to clipboard",
title: generateRandomTitle(),
});
}}
>
{[
virtualCard.fullNumber.slice(0, 4),
virtualCard.fullNumber.slice(4, 10),
virtualCard.fullNumber.slice(10, 15),
].join(" ")}
</Text>
<Flex flex={4} />
<Row
style={{
alignItems: "center",
}}
>
<Text
style={[
styles.text,
{
fontSize: 18,
},
]}
onPress={() => {
Clipboard.setString(name);
dialog.show({
message: "Name copied to clipboard",
title: generateRandomTitle(),
});
}}
>
{name.toUpperCase()}
</Text>
<Flex />
<Image
source={require("../assets/images/card/validThru.png")}
style={{ marginRight: 5, marginBottom: 3 }}
/>
<Text
onPress={() => {
Clipboard.setString(virtualCard.expMonth);
dialog.show({
message: "Month copied to clipboard",
title: generateRandomTitle(),
});
}}
style={styles.text}
>
{Number(virtualCard.expMonth)}/
</Text>
<Text
onPress={() => {
Clipboard.setString(virtualCard.expYear.slice(0, 2));
dialog.show({
message: "Year copied to clipboard",
title: generateRandomTitle(),
});
}}
style={styles.text}
>
{Number(virtualCard.expYear.slice(0, 2))}
</Text>
</Row>
<Flex />
</Animated.View>
<DialogView {...dialog} />
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
container: {
width: "100%",
maxWidth: 600,
backgroundColor: "#6E62EE",
borderRadius: 10,
padding: 20,
aspectRatio: 1.5,
alignSelf: "center",
alignItems: "center",
},
text: {
color: "white",
fontFamily: "OCRAStd",
shadowColor: "black",
shadowRadius: 1,
shadowOpacity: 0.5,
shadowOffset: { height: 1, width: 1 },
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment