From e66a3bcef611781a48c4d17f6ae28ae0981e3e5f Mon Sep 17 00:00:00 2001 From: CraftyDragon678 Date: Wed, 4 Aug 2021 23:25:38 +0900 Subject: [PATCH] feat: drops detail page (#6) * feat: add drops item page * feat: add drop detail contents * feat: flip countdown * chore: bump version to 0.4.3 * fix: init route name --- android/app/build.gradle | 4 +- package.json | 4 +- .../react-native-flip-countdown-timer.d.ts | 80 +++++++++++ src/App.tsx | 4 + src/components/DropItem.tsx | 6 +- src/pages/DropDetail.tsx | 134 ++++++++++++++++++ src/pages/Drops.tsx | 27 +++- src/router/navigator.ts | 18 ++- yarn.lock | 10 ++ 9 files changed, 274 insertions(+), 13 deletions(-) create mode 100644 src/@types/react-native-flip-countdown-timer.d.ts create mode 100644 src/pages/DropDetail.tsx diff --git a/android/app/build.gradle b/android/app/build.gradle index 960c95f..684b654 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,8 +134,8 @@ android { applicationId "com.ast.mvp" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 16 - versionName "0.4.2" + versionCode 17 + versionName "0.4.3" multiDexEnabled true } splits { diff --git a/package.json b/package.json index a8e150e..671eba9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rn", - "version": "0.4.2", + "version": "0.4.3", "private": true, "scripts": { "android": "react-native run-android", @@ -27,9 +27,11 @@ "@react-navigation/native": "^5.9.2", "@react-navigation/stack": "^5.14.2", "axios": "^0.21.1", + "dayjs": "^1.10.6", "react": "16.13.1", "react-native": "0.63.4", "react-native-collapsible-tab-view": "^4.2.1", + "react-native-flip-countdown-timer": "^0.0.3", "react-native-gesture-handler": "^1.9.0", "react-native-nfc-manager": "^2.2.1", "react-native-pager-view": "^5.1.9", diff --git a/src/@types/react-native-flip-countdown-timer.d.ts b/src/@types/react-native-flip-countdown-timer.d.ts new file mode 100644 index 0000000..db30eca --- /dev/null +++ b/src/@types/react-native-flip-countdown-timer.d.ts @@ -0,0 +1,80 @@ +declare module 'react-native-flip-countdown-timer' { + import React from 'react'; + import { TextStyle, ViewStyle } from 'react-native'; + + interface FlipNumberProps { + /** + * Number Input + */ + number: string | number; + + /** + * Number Input Unit + * @default 'seconds' + */ + unit?: 'hours' | 'minutes' | 'seconds'; + + /** + * size (default is `Dimention.width / 6`) + */ + size?: number; + + /** + * perspective + * @default 250 + */ + perspective?: number; + + /** + * Wrapper Style + * @default {} + */ + numberWrapperStyle?: ViewStyle; + + /** + * Card Style + * @default {} + */ + cardStyle?: ViewStyle; + + /** + * Flip Card Style + * @default {} + */ + flipCardStyle?: ViewStyle; + + /** + * Number style + * @default {} + */ + numberStyle?: TextStyle; + } + + interface CountdownTimerProps { + /** + * Time (in seconds) + */ + time: string | number; + + /** + * Play the timer + * @default true + */ + play?: boolean; + + /** + * Wrapper for the CountdownTimer + * @default {} + */ + wrapperStyle?: ViewStyle; + + /** + * Flip Number Props + */ + flipNumberProps?: FlipNumberProps; + } + + export const CountdownTimer: React.ComponentClass; + + export const FlipNumber: React.FC; +} diff --git a/src/App.tsx b/src/App.tsx index cda87cd..87d5fb3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,8 @@ import React from 'react'; import 'react-native-gesture-handler'; import styled from '@emotion/native'; import { GoogleSignin } from '@react-native-community/google-signin'; +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; import Router from './router'; import { ProvideAuth } from './hooks/user'; @@ -15,6 +17,8 @@ GoogleSignin.configure({ '51227550156-72gpdjmbedgn18n066r6g22a1kjp2k2m.apps.googleusercontent.com', }); +dayjs.extend(duration); + const TopBackground = styled.SafeAreaView` flex: 0; background-color: ${({ backgroundColor, topColor }) => diff --git a/src/components/DropItem.tsx b/src/components/DropItem.tsx index 5d7b63e..7c6cf66 100644 --- a/src/components/DropItem.tsx +++ b/src/components/DropItem.tsx @@ -3,7 +3,7 @@ import styled from '@emotion/native'; import { GestureResponderEvent, ImageSourcePropType, View } from 'react-native'; import Button from './Button'; -const Container = styled.View` +const Container = styled.TouchableOpacity` padding: 20px; flex-direction: row; justify-content: space-between; @@ -56,6 +56,7 @@ interface DropItemProps { price: number; description: string; onClickNotify: (event: GestureResponderEvent) => void; + onClickProduct: (event: GestureResponderEvent) => void; } const DropItem: React.FC = ({ @@ -66,8 +67,9 @@ const DropItem: React.FC = ({ price, description, onClickNotify, + onClickProduct, }) => ( - + diff --git a/src/pages/DropDetail.tsx b/src/pages/DropDetail.tsx new file mode 100644 index 0000000..96e7cfa --- /dev/null +++ b/src/pages/DropDetail.tsx @@ -0,0 +1,134 @@ +import React from 'react'; +import { StyleSheet } from 'react-native'; +import { FlipNumber } from 'react-native-flip-countdown-timer'; +import { useState } from 'react'; +import styled from '@emotion/native'; +import { RouteProp } from '@react-navigation/native'; +import { DropsStackParamList } from '@src/router/navigator'; +import dayjs from 'dayjs'; +import productImage from '../assets/images/productImageTemp.jpg'; +import logoImage from '../assets/images/logoImageTemp.jpg'; +import { useLayoutEffect } from 'react'; +import { useCallback } from 'react'; + +type Props = { + route: RouteProp; +}; + +const styles = StyleSheet.create({ + card: { + backgroundColor: '#fff', + borderColor: '#9a9a9a', + borderWidth: 0.5, + padding: 0, + }, + number: { + color: '#000', + fontFamily: 'Gong Gothic OTF', + }, + numberWrapper: { + shadowOpacity: 0, + elevation: 0, + borderColor: '#9a9a9a', + borderWidth: 1, + borderRadius: 5, + overflow: 'hidden', + }, +}); + +const Container = styled.View` + align-items: center; +`; + +const ProductImage = styled.Image` + width: 100%; + height: 390px; + margin-bottom: 20px; +`; + +const LogoImage = styled.Image` + width: 30px; + height: 30px; + margin-bottom: 15px; +`; + +const SubTitle = styled.Text` + font-family: 'NEXON Lv1 Gothic OTF Bold'; + font-size: 12px; + margin-bottom: 5px; +`; + +const Title = styled.Text` + font-family: 'NEXON Lv1 Gothic OTF Bold'; + font-size: 30px; + margin-bottom: 30px; +`; + +const CountDownContainer = styled.View` + flex-direction: row; + align-items: center; +`; + +const CountDownText = styled.Text` + font-family: 'NEXON Lv1 Gothic OTF Bold'; + font-size: 10px; + margin: 0 10px; +`; + +const DropDetail = ({ + route: { + params: { product }, + }, +}: Props) => { + const [time, setTime] = useState(61773); + const duration = dayjs.duration(time, 's'); + + useLayoutEffect( + useCallback(() => { + const timer = setInterval(() => setTime((t) => t - 1), 1e3); + return () => { + clearInterval(timer); + }; + }, []), + ); + + return ( + + + + {'조던 자이언 1'} + {product.nfcID} + + + H + + M + + 남음 + + + ); +}; + +export default DropDetail; diff --git a/src/pages/Drops.tsx b/src/pages/Drops.tsx index f9dc565..1b9c2a4 100644 --- a/src/pages/Drops.tsx +++ b/src/pages/Drops.tsx @@ -19,6 +19,8 @@ import { Product } from '@src/constants/types'; import logoImage from '../assets/images/logoImageTemp.jpg'; import productImage from '../assets/images/productImageTemp.jpg'; import moveToTopImage from '../assets/images/move-top.png'; +import { DropsStack, navigate } from '@src/router/navigator'; +import DropDetail from './DropDetail'; const styles = StyleSheet.create({ indicator: { @@ -114,6 +116,7 @@ const Ongoing = (props: Partial>) => { description="5월 12일 오전 11시 출시 예정" price={139000} onClickNotify={() => {}} + onClickProduct={() => navigate('DropDetail', { product: item })} /> )} {...props} @@ -121,7 +124,7 @@ const Ongoing = (props: Partial>) => { ); }; -const Drop = () => { +const DropsList = () => { const ref = useRef(); const [showingMoveToTop, setShowingMoveToTop] = useState(false); const moveToTop = useCallback(() => { @@ -139,9 +142,6 @@ const Drop = () => { ); return ( - - AST - { ); }; -export default Drop; + +const Drops = () => { + return ( + <> + + AST + + + + + + + ); +}; +export default Drops; diff --git a/src/router/navigator.ts b/src/router/navigator.ts index 91b3f37..ad1c680 100644 --- a/src/router/navigator.ts +++ b/src/router/navigator.ts @@ -5,6 +5,7 @@ import { import { createStackNavigator } from '@react-navigation/stack'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createRef } from 'react'; +import { Product } from '@src/constants/types'; export type RootStackParamList = { Root: undefined; @@ -29,15 +30,26 @@ export type MainTabParamList = { Profile: undefined; }; +export type DropsStackParamList = { + DropsList: undefined; + DropDetail: { + product: Product; + }; +}; + export const Stack = createStackNavigator(); export const Tab = createBottomTabNavigator(); +export const DropsStack = createStackNavigator(); + export const navigationRef = createRef(); -export const navigate = ( +type ParamList = RootStackParamList & MainTabParamList & DropsStackParamList; + +export const navigate = ( routeName: K, - params?: RootStackParamList[K], + ...[params]: ParamList[K] extends undefined ? [undefined?] : [ParamList[K]] ) => { if (!navigationRef.current) { throw new Error('navigator is not defined'); @@ -50,7 +62,7 @@ export const navigate = ( ); }; -export const reset = (routeName: K) => { +export const reset = (routeName: K) => { if (!navigationRef.current) { throw new Error('navigator is not defined'); } diff --git a/yarn.lock b/yarn.lock index aaad531..ff1b13a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2523,6 +2523,11 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" +dayjs@^1.10.6: + version "1.10.6" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63" + integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw== + dayjs@^1.8.15: version "1.10.4" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" @@ -5945,6 +5950,11 @@ react-native-collapsible-tab-view@^4.2.1: dependencies: use-deep-compare "^1.1.0" +react-native-flip-countdown-timer@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/react-native-flip-countdown-timer/-/react-native-flip-countdown-timer-0.0.3.tgz#a96cb694ea3b0cc720c33f27d92d82b81250c52a" + integrity sha512-TbNaZK0lm7hegnoV2L0bGB/PL/T7oRa6r0LlZ5XD9J3NQHFm9kbbBafksGpzmOBijeLgKM1djcUAysjxWk43JQ== + react-native-gesture-handler@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.9.0.tgz#e441b1c0277c3fd4ca3e5c58fdd681e2f0ceddf0"