From 565ca296dba371da191e588682dc6119655c665a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 17:09:32 +0900 Subject: [PATCH 001/111] =?UTF-8?q?feat:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=B9=B4=EB=93=9C=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.tsx | 281 +++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 client/src/constants/Rush/rushCard.tsx diff --git a/client/src/constants/Rush/rushCard.tsx b/client/src/constants/Rush/rushCard.tsx new file mode 100644 index 00000000..1d246a21 --- /dev/null +++ b/client/src/constants/Rush/rushCard.tsx @@ -0,0 +1,281 @@ +import { ReactNode } from "react"; + +export const CARD_COLOR = { + BLUE: "blue", + RED: "red", + YELLOW: "yellow", + GREEN: "green", +} as const; + +export const CARD_SELECTED_STATUS = { + TRUE: "true", + FALSE: "false", +} as const; + +export const CARD_DAYS = { + DAY1: 1, + DAY2: 2, + DAY3: 3, + DAY4: 4, + DAY5: 5, + DAY6: 6, +} as const; + +// TODO: API 연동 +export const CARD_COLORS: { [key: number]: { FIRST_CARD: string; SECOND_CARD: string } } = { + [CARD_DAYS.DAY1]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.BLUE }, + [CARD_DAYS.DAY2]: { FIRST_CARD: CARD_COLOR.YELLOW, SECOND_CARD: CARD_COLOR.RED }, + [CARD_DAYS.DAY3]: { FIRST_CARD: CARD_COLOR.BLUE, SECOND_CARD: CARD_COLOR.RED }, + [CARD_DAYS.DAY4]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.YELLOW }, + [CARD_DAYS.DAY5]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.RED }, + [CARD_DAYS.DAY6]: { FIRST_CARD: CARD_COLOR.BLUE, SECOND_CARD: CARD_COLOR.YELLOW }, +}; + +export const CARD_TITLES: { [key: number]: { FIRST_CARD: string; SECOND_CARD: string } } = { + [CARD_DAYS.DAY1]: { FIRST_CARD: "첫 차는 저렴해야 한다", SECOND_CARD: "첫 차는 안전해야 한다" }, + [CARD_DAYS.DAY2]: { + FIRST_CARD: "온라인 쇼핑이 편해서 좋다", + SECOND_CARD: "오프라인 쇼핑이 확실해서 좋다", + }, + [CARD_DAYS.DAY3]: { FIRST_CARD: "텐트 치고 캠핑하기", SECOND_CARD: "차 안에서 차박하기" }, + [CARD_DAYS.DAY4]: { FIRST_CARD: "평생 주차 무료로 하기", SECOND_CARD: "평생 주유 무료로 하기" }, + [CARD_DAYS.DAY5]: { FIRST_CARD: "무채색 차가 좋다", SECOND_CARD: "컬러풀한 차가 좋다" }, + [CARD_DAYS.DAY6]: { + FIRST_CARD: "주말에는 바다보러 가기", + SECOND_CARD: "주말에는 도심 드라이브", + }, +}; + +export const CARD_DESCRIPTION: { + [key: number]: { + FIRST_CARD: { + [status in (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS]]: ReactNode[]; + }; + SECOND_CARD: { + [status in (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS]]: ReactNode[]; + }; + }; +} = { + [CARD_DAYS.DAY1]: { + FIRST_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <> + 가성비 좋은 +
+ 도심형 전기차 + , + <> + 캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 +
첫 차로 캐스퍼 일렉트릭 어떤가요? + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 가성비 좋게 저렴한 차로 시작해서 +
+ 차근히 업그레이드하고 싶어 + , + ], + }, + SECOND_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <> + 가성비 좋은 +
+ 도심형 전기차 + , + <> + 캐스퍼는 작고 귀엽기만 하다고 생각했나요? +
+ 이젠 현대 스마트센스 안전옵션까지 지원해요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 처음 사는 차인 만큼 +
+ 안전한 차를 사서 오래 타고 싶어 + , + ], + }, + }, + [CARD_DAYS.DAY2]: { + FIRST_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>현대 유일 온라인 예약, + <> + 차 살때도 온라인 쇼핑을! +
+ 오직 온라인에서만 구매할 수 있는 캐스퍼 일렉트릭 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 편한 게 최고야! +
+ 집에서 인터넷으로 쇼핑할래 + , + ], + }, + SECOND_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>캐스퍼 스튜디오 송파, + <> + 캐스퍼 일렉트릭을 원하는 시간에 +
+ 직접 만나볼 수 있는 무인 전시 스튜디오 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 살 거면 제대로 보고 사야지! +
+ 직접 보고 나서 판단할래 + , + ], + }, + }, + [CARD_DAYS.DAY3]: { + FIRST_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>V2L로 캠핑 준비 끝, + <> + 캠핑장 전기 눈치싸움은 이제 그만! +
+ 차에서 직접 220V 전원을 연결할 수 있어요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [<>캠핑은 텐트가 근본이지!], + }, + SECOND_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>폴 폴딩으로 공간 활용, + <> + 모든 시트가 완전히 접혀서 +
+ 나만의 작은 방으로 만들 수 있어요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 가벼운 짐으로 +
+ 차에서 잠드는 낭만이 좋아 + , + ], + }, + }, + [CARD_DAYS.DAY4]: { + FIRST_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <> + 전기차는 +
+ 주차비 혜택 받아요 + , + <> + 공영주차장 50% 할인 정책으로 +
+ 주차비 부담을 덜 수 있어요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 요즘 주차장은 너무 비싸 +
+ 주차비 걱정은 그만 하고 싶어 + , + ], + }, + SECOND_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <> + 전기차는 +
+ 기름값 걱정 없어요 + , + <> + 모든 시트가 완전히 접혀서 +
+ 나만의 작은 방으로 만들 수 있어요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 기름값이 너무 많이 올랐어 +
+ 주유비가 많이 들어 고민이야 + , + ], + }, + }, + [CARD_DAYS.DAY5]: { + FIRST_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>기본 색감도 다채롭게, + <> + 무채색 컬러도 매트부터 메탈릭까지 +
+ 다양한 질감으로 구성했어요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 검은색, 흰색, 회색! +
+ 오래 타려면 무난한 게 최고야 + , + ], + }, + SECOND_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>신규 색상 5종 출시, + <> + 기존 캐스퍼 색상 라인업에 새로운 5종을 추가! +
내 차의 개성을 뽐내봐요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 무채색은 지루해! +
+ 내가 좋아하는 색으로 고를래 + , + ], + }, + }, + [CARD_DAYS.DAY6]: { + FIRST_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>충전 한 번에 315km, + <> + 엔트리급 전기차의 주행거리 혁신 +
한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 아까운 주말엔 +
+ 국내여행이라도 다녀오고 싶어 + , + ], + }, + SECOND_CARD: { + [CARD_SELECTED_STATUS.TRUE]: [ + <>충전 한 번에 315km, + <> + 엔트리급 전기차의 주행거리 혁신 +
한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요 + , + ], + [CARD_SELECTED_STATUS.FALSE]: [ + <> + 평일에 너무 피곤했으니 +
+ 오랜만에 동네 드라이브나 할래 + , + ], + }, + }, +}; From 40d385b68f673254cf01914ec6778f27cb10f77c Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 17:14:08 +0900 Subject: [PATCH 002/111] =?UTF-8?q?feat:=20=EC=84=A0=EC=B9=99=EC=88=9C=20?= =?UTF-8?q?=EB=B0=B8=EB=9F=B0=EC=8A=A4=20=EA=B2=8C=EC=9E=84=20RushCardDesc?= =?UTF-8?q?ription=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20UI=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/Rush/RushCardDescription.tsx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 client/src/features/Rush/RushCardDescription.tsx diff --git a/client/src/features/Rush/RushCardDescription.tsx b/client/src/features/Rush/RushCardDescription.tsx new file mode 100644 index 00000000..55c34b0b --- /dev/null +++ b/client/src/features/Rush/RushCardDescription.tsx @@ -0,0 +1,55 @@ +import { cva } from "class-variance-authority"; +import Category from "@/components/Category"; +import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; + +type CardColor = keyof typeof CARD_COLOR; + +interface RushCardDescriptionProps { + color: CardColor; +} + +const backgroundGradients = cva( + `flex gap-[35px] w-[834px] h-[400px] bg-gradient-green rounded-800 py-6 px-[37px] justify-between`, + { + variants: { + color: { + [CARD_COLOR.BLUE]: "bg-gradient-blue", + [CARD_COLOR.RED]: "bg-gradient-red", + [CARD_COLOR.YELLOW]: "bg-gradient-yellow", + [CARD_COLOR.GREEN]: "bg-gradient-green", + }, + }, + } +); + +export default function RushCardDescription({ color }: RushCardDescriptionProps) { + return ( +
+
+ 당신의 선택 +

+ 첫 차는 +
+ 저렴해야 한다 +

+ +

지금

+

63%

+

가 선택했어요

+
+
+ +

CASPER Electric

+

+ 가성비 좋은 +
+ 도심형 전기차 +

+

+ 캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 +
첫 차로 캐스퍼 일렉트릭 어떤가요? +

+
+
+ ); +} From f25b85c1968ab9f3a03926ef0d42c87ec2aae47b Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 17:14:29 +0900 Subject: [PATCH 003/111] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?= =?UTF-8?q?=EB=B0=B8=EB=9F=B0=EC=8A=A4=20=EA=B2=8C=EC=9E=84=20RushCard=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCard.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 client/src/features/Rush/RushCard.tsx diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/features/Rush/RushCard.tsx new file mode 100644 index 00000000..29d1ade2 --- /dev/null +++ b/client/src/features/Rush/RushCard.tsx @@ -0,0 +1,16 @@ +export default function RushCard() { + return ( +
+

+ 첫 차는 +
+ 저렴해야 한다 +

+

+ 가성비 좋게 저렴한 차로 시작해서 +
+ 차근히 업그레이드하고 싶어 +

+
+ ); +} From e60991d98cb7410bbdad09da774991d1b909c04d Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 17:15:56 +0900 Subject: [PATCH 004/111] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?= =?UTF-8?q?=EB=B0=B8=EB=9F=B0=EC=8A=A4=20=EA=B2=8C=EC=9E=84=20RushCardComp?= =?UTF-8?q?arison=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20UI=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCardComparison.tsx | 13 +++++++++++++ client/src/pages/Rush/index.tsx | 13 ++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 client/src/features/Rush/RushCardComparison.tsx diff --git a/client/src/features/Rush/RushCardComparison.tsx b/client/src/features/Rush/RushCardComparison.tsx new file mode 100644 index 00000000..7ca624af --- /dev/null +++ b/client/src/features/Rush/RushCardComparison.tsx @@ -0,0 +1,13 @@ +import RushCard from "@/features/Rush/RushCard.tsx"; + +export default function RushCardComparison() { + return ( +
+ +

+ VS +

+ +
+ ); +} diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index ab7eeedf..964cd5cd 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -1,3 +1,14 @@ +import RushCard from "@/features/Rush/RushCard.tsx"; +import RushCardComparison from "@/features/Rush/RushCardComparison.tsx"; +import RushCardDescription from "@/features/Rush/RushCardDescription.tsx"; + export default function Rush() { - return
rush
; + // 컴포넌트 테스트용 (storybook X) + return ( +
+ + + +
+ ); } From 6787f396d952c4e1bd6a2b9d6fc5f899f9c2265c Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 17:24:39 +0900 Subject: [PATCH 005/111] =?UTF-8?q?fix:=20CARD=5FCOLOR=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCardDescription.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/features/Rush/RushCardDescription.tsx b/client/src/features/Rush/RushCardDescription.tsx index 55c34b0b..e135ceb5 100644 --- a/client/src/features/Rush/RushCardDescription.tsx +++ b/client/src/features/Rush/RushCardDescription.tsx @@ -2,10 +2,8 @@ import { cva } from "class-variance-authority"; import Category from "@/components/Category"; import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; -type CardColor = keyof typeof CARD_COLOR; - interface RushCardDescriptionProps { - color: CardColor; + color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; } const backgroundGradients = cva( From e75434908b90b2ce3da8adf23b5720cdaa52a51c Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 18:11:48 +0900 Subject: [PATCH 006/111] =?UTF-8?q?feat:=20CARD=5FTYPE=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/src/constants/Rush/rushCard.tsx b/client/src/constants/Rush/rushCard.tsx index 1d246a21..c584d944 100644 --- a/client/src/constants/Rush/rushCard.tsx +++ b/client/src/constants/Rush/rushCard.tsx @@ -1,5 +1,10 @@ import { ReactNode } from "react"; +export const CARD_TYPE = { + FIRST_CARD: "FIRST_CARD", + SECOND_CARD: "SECOND_CARD", +} as const; + export const CARD_COLOR = { BLUE: "blue", RED: "red", @@ -22,7 +27,12 @@ export const CARD_DAYS = { } as const; // TODO: API 연동 -export const CARD_COLORS: { [key: number]: { FIRST_CARD: string; SECOND_CARD: string } } = { +export const CARD_COLORS: { + [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { + FIRST_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + SECOND_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + }; +} = { [CARD_DAYS.DAY1]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.BLUE }, [CARD_DAYS.DAY2]: { FIRST_CARD: CARD_COLOR.YELLOW, SECOND_CARD: CARD_COLOR.RED }, [CARD_DAYS.DAY3]: { FIRST_CARD: CARD_COLOR.BLUE, SECOND_CARD: CARD_COLOR.RED }, From 1f05f0ca5ae089ebe9fbb69bf92580b87dd45a69 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 18:13:16 +0900 Subject: [PATCH 007/111] =?UTF-8?q?feat:=20RushCard=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=8F=99?= =?UTF-8?q?=EC=A0=81=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCard.tsx | 57 +++++++++++++++---- .../src/features/Rush/RushCardComparison.tsx | 5 +- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/features/Rush/RushCard.tsx index 29d1ade2..c5534ee7 100644 --- a/client/src/features/Rush/RushCard.tsx +++ b/client/src/features/Rush/RushCard.tsx @@ -1,16 +1,49 @@ -export default function RushCard() { +import React from "react"; +import { cva } from "class-variance-authority"; +import { + CARD_COLOR, + CARD_DAYS, + CARD_DESCRIPTION, + CARD_SELECTED_STATUS, + CARD_TITLES, + CARD_TYPE, +} from "@/constants/Rush/rushCard.tsx"; + +interface RushCardProps { + color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; +} + +const backgroundGradients = cva( + `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800`, + { + variants: { + color: { + [CARD_COLOR.BLUE]: "bg-gradient-blue", + [CARD_COLOR.RED]: "bg-gradient-red", + [CARD_COLOR.YELLOW]: "bg-gradient-yellow", + [CARD_COLOR.GREEN]: "bg-gradient-green", + }, + }, + defaultVariants: { + color: CARD_COLOR.GREEN, + }, + } +); + +type CardType = (typeof CARD_TYPE)[keyof typeof CARD_TYPE]; + +const currentDay = CARD_DAYS.DAY2; +const cardType: CardType = CARD_TYPE.FIRST_CARD; +const cardStatus = CARD_SELECTED_STATUS.FALSE; + +const cardTitle = CARD_TITLES[currentDay][cardType]; +const cardDescription = CARD_DESCRIPTION[currentDay][cardType][cardStatus]; + +export default function RushCard({ color }: RushCardProps) { return ( -
-

- 첫 차는 -
- 저렴해야 한다 -

-

- 가성비 좋게 저렴한 차로 시작해서 -
- 차근히 업그레이드하고 싶어 -

+
+

{cardTitle}

+

{cardDescription}

); } diff --git a/client/src/features/Rush/RushCardComparison.tsx b/client/src/features/Rush/RushCardComparison.tsx index 7ca624af..48815e0a 100644 --- a/client/src/features/Rush/RushCardComparison.tsx +++ b/client/src/features/Rush/RushCardComparison.tsx @@ -1,13 +1,14 @@ +import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; import RushCard from "@/features/Rush/RushCard.tsx"; export default function RushCardComparison() { return (
- +

VS

- +
); } From f2add85f7e55e1f861ff50787d75a0c46b15fe77 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 18:19:57 +0900 Subject: [PATCH 008/111] =?UTF-8?q?refactor:=20RushCard=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=82=B4=EB=B6=80=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=ED=83=80=EC=9E=85=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCard.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/features/Rush/RushCard.tsx index c5534ee7..182ef967 100644 --- a/client/src/features/Rush/RushCard.tsx +++ b/client/src/features/Rush/RushCard.tsx @@ -30,11 +30,10 @@ const backgroundGradients = cva( } ); -type CardType = (typeof CARD_TYPE)[keyof typeof CARD_TYPE]; - -const currentDay = CARD_DAYS.DAY2; -const cardType: CardType = CARD_TYPE.FIRST_CARD; -const cardStatus = CARD_SELECTED_STATUS.FALSE; +const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY5; +const cardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.FIRST_CARD; +const cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS] = + CARD_SELECTED_STATUS.FALSE; const cardTitle = CARD_TITLES[currentDay][cardType]; const cardDescription = CARD_DESCRIPTION[currentDay][cardType][cardStatus]; From b48ba8cda0a7f18917308652e4f2d8302433817f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 18:34:08 +0900 Subject: [PATCH 009/111] =?UTF-8?q?feat:=20RushCardComparison=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B0=8F=20RushCard=EB=A1=9C=20Props=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.tsx | 2 +- client/src/features/Rush/RushCard.tsx | 27 ++++---------- .../src/features/Rush/RushCardComparison.tsx | 37 +++++++++++++++++-- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/client/src/constants/Rush/rushCard.tsx b/client/src/constants/Rush/rushCard.tsx index c584d944..0fb95889 100644 --- a/client/src/constants/Rush/rushCard.tsx +++ b/client/src/constants/Rush/rushCard.tsx @@ -26,7 +26,7 @@ export const CARD_DAYS = { DAY6: 6, } as const; -// TODO: API 연동 +// TODO: 추후 API 연동 export const CARD_COLORS: { [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { FIRST_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/features/Rush/RushCard.tsx index 182ef967..80b999fc 100644 --- a/client/src/features/Rush/RushCard.tsx +++ b/client/src/features/Rush/RushCard.tsx @@ -1,16 +1,11 @@ -import React from "react"; +import React, { ReactNode } from "react"; import { cva } from "class-variance-authority"; -import { - CARD_COLOR, - CARD_DAYS, - CARD_DESCRIPTION, - CARD_SELECTED_STATUS, - CARD_TITLES, - CARD_TYPE, -} from "@/constants/Rush/rushCard.tsx"; +import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; interface RushCardProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + title: string; + description: ReactNode[]; } const backgroundGradients = cva( @@ -30,19 +25,11 @@ const backgroundGradients = cva( } ); -const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY5; -const cardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.FIRST_CARD; -const cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS] = - CARD_SELECTED_STATUS.FALSE; - -const cardTitle = CARD_TITLES[currentDay][cardType]; -const cardDescription = CARD_DESCRIPTION[currentDay][cardType][cardStatus]; - -export default function RushCard({ color }: RushCardProps) { +export default function RushCard({ color, title, description }: RushCardProps) { return (
-

{cardTitle}

-

{cardDescription}

+

{title}

+

{description}

); } diff --git a/client/src/features/Rush/RushCardComparison.tsx b/client/src/features/Rush/RushCardComparison.tsx index 48815e0a..538b6c01 100644 --- a/client/src/features/Rush/RushCardComparison.tsx +++ b/client/src/features/Rush/RushCardComparison.tsx @@ -1,14 +1,45 @@ -import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; +import { + CARD_COLORS, + CARD_DAYS, + CARD_DESCRIPTION, + CARD_SELECTED_STATUS, + CARD_TITLES, + CARD_TYPE, +} from "@/constants/Rush/rushCard.tsx"; import RushCard from "@/features/Rush/RushCard.tsx"; export default function RushCardComparison() { + // TODO: 추후 API 연동 + const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; + const firstCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.FIRST_CARD; + const secondCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.SECOND_CARD; + const cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS] = + CARD_SELECTED_STATUS.FALSE; + + const firstCardColor = CARD_COLORS[currentDay][firstCardType]; + const secondCardColor = CARD_COLORS[currentDay][secondCardType]; + + const firstCardTitle = CARD_TITLES[currentDay][firstCardType]; + const secondCardTitle = CARD_TITLES[currentDay][secondCardType]; + + const firstCardDescription = CARD_DESCRIPTION[currentDay][firstCardType][cardStatus]; + const secondCardDescription = CARD_DESCRIPTION[currentDay][secondCardType][cardStatus]; + return (
- +

VS

- +
); } From 481123e5dd113de52c0e0a51797eeccfb31da015 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 18:35:26 +0900 Subject: [PATCH 010/111] =?UTF-8?q?chore:=20=ED=95=84=EC=9A=94=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=98=B8=EC=B6=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/Rush/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index 964cd5cd..03816200 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -1,12 +1,9 @@ -import RushCard from "@/features/Rush/RushCard.tsx"; import RushCardComparison from "@/features/Rush/RushCardComparison.tsx"; import RushCardDescription from "@/features/Rush/RushCardDescription.tsx"; export default function Rush() { - // 컴포넌트 테스트용 (storybook X) return (
-
From 2b609f932ef61452ae0b5a8e12e3e4d0ce32eff0 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 19:09:17 +0900 Subject: [PATCH 011/111] =?UTF-8?q?fix:=20RushCard=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EB=82=B4=EB=B6=80=20ReactNodes[]=20?= =?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=8B=9C=20key=20Props=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCard.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/features/Rush/RushCard.tsx index 80b999fc..988de9ae 100644 --- a/client/src/features/Rush/RushCard.tsx +++ b/client/src/features/Rush/RushCard.tsx @@ -27,9 +27,13 @@ const backgroundGradients = cva( export default function RushCard({ color, title, description }: RushCardProps) { return ( -
+

{title}

-

{description}

+ {description.map((text, index) => ( +

+ {text} +

+ ))}
); } From 1230052e9b7584de5bf88a751616ff4851306ac4 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 19:13:05 +0900 Subject: [PATCH 012/111] =?UTF-8?q?feat:=20RushCardDescription=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20mock=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=9E=84=EC=8B=9C=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/Rush/RushCardComparison.tsx | 2 +- .../src/features/Rush/RushCardDescription.tsx | 39 +++++++++++-------- client/src/pages/Rush/index.tsx | 2 +- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/client/src/features/Rush/RushCardComparison.tsx b/client/src/features/Rush/RushCardComparison.tsx index 538b6c01..06db87a4 100644 --- a/client/src/features/Rush/RushCardComparison.tsx +++ b/client/src/features/Rush/RushCardComparison.tsx @@ -10,7 +10,7 @@ import RushCard from "@/features/Rush/RushCard.tsx"; export default function RushCardComparison() { // TODO: 추후 API 연동 - const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; + const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; const firstCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.FIRST_CARD; const secondCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.SECOND_CARD; const cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS] = diff --git a/client/src/features/Rush/RushCardDescription.tsx b/client/src/features/Rush/RushCardDescription.tsx index e135ceb5..b5fb8eb1 100644 --- a/client/src/features/Rush/RushCardDescription.tsx +++ b/client/src/features/Rush/RushCardDescription.tsx @@ -1,9 +1,19 @@ import { cva } from "class-variance-authority"; import Category from "@/components/Category"; -import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; +import { + CARD_COLOR, + CARD_DAYS, + CARD_DESCRIPTION, + CARD_SELECTED_STATUS, + CARD_TITLES, + CARD_TYPE, +} from "@/constants/Rush/rushCard.tsx"; interface RushCardDescriptionProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + day: (typeof CARD_DAYS)[keyof typeof CARD_DAYS]; + cardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE]; + cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS]; } const backgroundGradients = cva( @@ -20,16 +30,20 @@ const backgroundGradients = cva( } ); -export default function RushCardDescription({ color }: RushCardDescriptionProps) { +export default function RushCardDescription({ + color, + day, + cardType, + cardStatus, +}: RushCardDescriptionProps) { + const title = CARD_TITLES[day][cardType]; + const [descriptionTitle, descriptionText] = CARD_DESCRIPTION[day][cardType][cardStatus]; + return (
당신의 선택 -

- 첫 차는 -
- 저렴해야 한다 -

+

{title}

지금

63%

@@ -38,15 +52,8 @@ export default function RushCardDescription({ color }: RushCardDescriptionProps)

CASPER Electric

-

- 가성비 좋은 -
- 도심형 전기차 -

-

- 캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 -
첫 차로 캐스퍼 일렉트릭 어떤가요? -

+

{descriptionTitle}

+

{descriptionText}

); diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index 03816200..da49bbab 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -5,7 +5,7 @@ export default function Rush() { return (
- +
); } From fd9e8fdcb3805833623df2ae7e2ac5988532211f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 4 Aug 2024 19:13:52 +0900 Subject: [PATCH 013/111] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/RushCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/features/Rush/RushCard.tsx index 988de9ae..5452bb09 100644 --- a/client/src/features/Rush/RushCard.tsx +++ b/client/src/features/Rush/RushCard.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from "react"; +import { ReactNode } from "react"; import { cva } from "class-variance-authority"; import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; From e225a98f21e3d150aa424b73ea660adbfbd160ec Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 8 Aug 2024 18:08:23 +0900 Subject: [PATCH 014/111] =?UTF-8?q?feat:=20Rush=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8=20=EB=B0=8F=20Fetch=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 123 ++++++++++++++++++++++++++++++++++++ client/src/types/rushApi.ts | 57 +++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 client/src/apis/rushAPI.ts create mode 100644 client/src/types/rushApi.ts diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts new file mode 100644 index 00000000..81d8b691 --- /dev/null +++ b/client/src/apis/rushAPI.ts @@ -0,0 +1,123 @@ +import { + GetRushBalanceResponse, + GetRushOptionResultResponse, + GetRushParticipationStatusResponse, + GetRushResultResponse, + GetTodayRushEventResponse, + GetTotalRushEventsResponse, + PostSelectedRushCardOptionResponse, +} from "@/types/rushApi"; + +const baseURL = `${import.meta.env.VITE_API_URL}/event/rush`; +const headers = { + "Content-Type": "application/json", +}; + +export const RushAPI = { + // 밸런스 게임 전체 조회 : 서버 시간 연동 (GET) /event/rush + // (서버 시간) - (이벤트 시작 시간) => 카운트 다운 진행 + async getRush(): Promise { + try { + const response = await fetch(`${baseURL}`, { + method: "GET", + headers: headers, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, + // 밸런스 게임 참여 여부 조회 (GET) /event/rush/applied + async getRushParticipationStatus(token: string): Promise { + try { + const response = await fetch(`${baseURL}/applied`, { + method: "GET", + headers: { ...headers, Authorization: `Bearer ${token}` }, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, + // 밸런스 게임 옵션 선택지 정보 조회 (GET) /event/rush/today + async getTodayRushEvent(token: string): Promise { + try { + const response = await fetch(`${baseURL}/today`, { + method: "GET", + headers: { ...headers, Authorization: `Bearer ${token}` }, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, + // 밸런스 게임 옵션 선택 (응모) (POST) /event/rush/options/{optionId}/apply + async postSelectedRushOptionApply( + token: string, + optionId: number + ): Promise { + try { + const response = await fetch(`${baseURL}/options/${optionId}/apply`, { + method: "POST", + headers: { ...headers, Authorization: `Bearer ${token}` }, + body: JSON.stringify({}), + }); + switch (response.status) { + case 204: + return 204; + case 404: + return 404; + default: + throw new Error(`Unexpected response status: ${response.status}`); + } + } catch (error) { + console.error("Error:", error); + throw error; + } + }, + // 밸런스 게임 카드 선택 결과 (GET) /event/rush/options/{optionId}/result + async getRushOptionResult( + token: string, + optionId: number + ): Promise { + try { + const response = await fetch(`${baseURL}/options/${optionId}/result`, { + method: "GET", + headers: { ...headers, Authorization: `Bearer ${token}` }, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, + // 밸런스 게임 선택 비율 조회 (GET) /event/rush/balance + async getRushBalance(token: string): Promise { + try { + const response = await fetch(`${baseURL}/balance`, { + method: "GET", + headers: { ...headers, Authorization: `Bearer ${token}` }, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, + // 밸런스 게임 결과 조회 (GET) /event/rush/result + async getRushResult(token: string): Promise { + try { + const response = await fetch(`${baseURL}/result`, { + method: "GET", + headers: { ...headers, Authorization: `Bearer ${token}` }, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, +}; diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts new file mode 100644 index 00000000..53afbe2d --- /dev/null +++ b/client/src/types/rushApi.ts @@ -0,0 +1,57 @@ +interface RushEventType { + rushEventId: number; + startDateTime: string; + endDateTime: string; +} + +interface RushCardType { + title: string; + description: string; +} + +// 밸런스 게임 전체 조회 : 서버 시간 연동 (GET) /event/rush +// (서버 시간) - (이벤트 시작 시간) => 카운트 다운 진행 +export interface GetTotalRushEventsResponse { + serverDateTime: string; + todayEventId: number; + eventsStartDate: string; + eventsEndDate: string; + activePeriod: number; + events: RushEventType[]; +} + +// 밸런스 게임 참여 여부 조회 (GET) /event/rush/applied +export interface GetRushParticipationStatusResponse { + result: boolean; +} + +// 밸런스 게임 옵션 선택지 정보 조회 (GET) /event/rush/today +export interface GetTodayRushEventResponse { + leftOption: RushCardType; + rightOption: RushCardType; +} + +// 밸런스 게임 옵션 선택 (응모) (POST) /event/rush/options/{optionId}/apply +export type PostSelectedRushCardOptionResponse = 204 | 404; + +// 밸런스 게임 카드 선택 결과 (GET) /event/rush/options/{optionId}/result +export interface GetRushOptionResultResponse { + resultTitle: string; + resultDescription: string; +} + +// 밸런스 게임 선택 비율 조회 (GET) /event/rush/balance +export interface GetRushBalanceResponse { + optionId: number; + leftOption: number; + rightOption: number; +} + +// 밸런스 게임 결과 조회 (GET) /event/rush/result +export interface GetRushResultResponse { + leftSelection: number; + rightSelection: number; + rank: number; + totalParticipants: number; + winnerCount: number; +} From d259f5e2551087b87b4b00cd19749e332d10a59a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 8 Aug 2024 18:09:41 +0900 Subject: [PATCH 015/111] =?UTF-8?q?chore:=20Rush=20API=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=A3=BC=EC=84=9D=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 8 -------- client/src/types/rushApi.ts | 8 -------- 2 files changed, 16 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index 81d8b691..0a6f40c1 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -14,8 +14,6 @@ const headers = { }; export const RushAPI = { - // 밸런스 게임 전체 조회 : 서버 시간 연동 (GET) /event/rush - // (서버 시간) - (이벤트 시작 시간) => 카운트 다운 진행 async getRush(): Promise { try { const response = await fetch(`${baseURL}`, { @@ -28,7 +26,6 @@ export const RushAPI = { throw error; } }, - // 밸런스 게임 참여 여부 조회 (GET) /event/rush/applied async getRushParticipationStatus(token: string): Promise { try { const response = await fetch(`${baseURL}/applied`, { @@ -41,7 +38,6 @@ export const RushAPI = { throw error; } }, - // 밸런스 게임 옵션 선택지 정보 조회 (GET) /event/rush/today async getTodayRushEvent(token: string): Promise { try { const response = await fetch(`${baseURL}/today`, { @@ -54,7 +50,6 @@ export const RushAPI = { throw error; } }, - // 밸런스 게임 옵션 선택 (응모) (POST) /event/rush/options/{optionId}/apply async postSelectedRushOptionApply( token: string, optionId: number @@ -78,7 +73,6 @@ export const RushAPI = { throw error; } }, - // 밸런스 게임 카드 선택 결과 (GET) /event/rush/options/{optionId}/result async getRushOptionResult( token: string, optionId: number @@ -94,7 +88,6 @@ export const RushAPI = { throw error; } }, - // 밸런스 게임 선택 비율 조회 (GET) /event/rush/balance async getRushBalance(token: string): Promise { try { const response = await fetch(`${baseURL}/balance`, { @@ -107,7 +100,6 @@ export const RushAPI = { throw error; } }, - // 밸런스 게임 결과 조회 (GET) /event/rush/result async getRushResult(token: string): Promise { try { const response = await fetch(`${baseURL}/result`, { diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts index 53afbe2d..cf1d776a 100644 --- a/client/src/types/rushApi.ts +++ b/client/src/types/rushApi.ts @@ -9,8 +9,6 @@ interface RushCardType { description: string; } -// 밸런스 게임 전체 조회 : 서버 시간 연동 (GET) /event/rush -// (서버 시간) - (이벤트 시작 시간) => 카운트 다운 진행 export interface GetTotalRushEventsResponse { serverDateTime: string; todayEventId: number; @@ -20,34 +18,28 @@ export interface GetTotalRushEventsResponse { events: RushEventType[]; } -// 밸런스 게임 참여 여부 조회 (GET) /event/rush/applied export interface GetRushParticipationStatusResponse { result: boolean; } -// 밸런스 게임 옵션 선택지 정보 조회 (GET) /event/rush/today export interface GetTodayRushEventResponse { leftOption: RushCardType; rightOption: RushCardType; } -// 밸런스 게임 옵션 선택 (응모) (POST) /event/rush/options/{optionId}/apply export type PostSelectedRushCardOptionResponse = 204 | 404; -// 밸런스 게임 카드 선택 결과 (GET) /event/rush/options/{optionId}/result export interface GetRushOptionResultResponse { resultTitle: string; resultDescription: string; } -// 밸런스 게임 선택 비율 조회 (GET) /event/rush/balance export interface GetRushBalanceResponse { optionId: number; leftOption: number; rightOption: number; } -// 밸런스 게임 결과 조회 (GET) /event/rush/result export interface GetRushResultResponse { leftSelection: number; rightSelection: number; From bdcdecc8969fb27b2ae8a85fe88a2e01d25bfad1 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 8 Aug 2024 18:53:02 +0900 Subject: [PATCH 016/111] =?UTF-8?q?fix:=20Rush=20API=20POST=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EC=83=81=ED=83=9C=20=EC=B2=98=EB=A6=AC=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index 0a6f40c1..93a2fcd1 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -60,14 +60,7 @@ export const RushAPI = { headers: { ...headers, Authorization: `Bearer ${token}` }, body: JSON.stringify({}), }); - switch (response.status) { - case 204: - return 204; - case 404: - return 404; - default: - throw new Error(`Unexpected response status: ${response.status}`); - } + return response.json(); } catch (error) { console.error("Error:", error); throw error; From f3d99217dad83a68415e228329993c99f48e5f61 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 8 Aug 2024 20:20:22 +0900 Subject: [PATCH 017/111] =?UTF-8?q?feat:=20Main=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20Rush=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EA=B2=BD?= =?UTF-8?q?=ED=92=88=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushEvent/index.tsx | 30 ++++----- client/src/constants/Main/rushEventData.ts | 38 +++++++++++ client/src/features/Main/Rush.tsx | 73 +++++++++------------- 3 files changed, 79 insertions(+), 62 deletions(-) create mode 100644 client/src/constants/Main/rushEventData.ts diff --git a/client/src/components/RushEvent/index.tsx b/client/src/components/RushEvent/index.tsx index dd5ee836..fc10cef5 100644 --- a/client/src/components/RushEvent/index.tsx +++ b/client/src/components/RushEvent/index.tsx @@ -1,27 +1,19 @@ -import { useMemo } from "react"; +import { RushEventProps } from "@/constants/Main/rushEventData.ts"; import { formatDate } from "@/utils/formatDate.ts"; -export interface RushEventProps { - id: number; +export interface TotalRushEventsProps extends RushEventProps { date: string; - image: string; - prizeName: string; + isPastEvent: boolean; + isTodayEvent: boolean; } -export default function RushEvent({ date, image, prizeName }: RushEventProps) { - // TODO: 백엔드와 상의 후 게임 진행 상태 값 받는 걸로 변경 - const { isPastEvent, isTodayEvent } = useMemo(() => { - const eventDate = new Date(date.split(" ")[0]); - const today = new Date(); - today.setHours(0, 0, 0, 0); - eventDate.setHours(0, 0, 0, 0); - - return { - isPastEvent: eventDate.getTime() < today.getTime(), - isTodayEvent: eventDate.getTime() === today.getTime(), - }; - }, [date]); - +export default function RushEvent({ + date, + image, + prizeName, + isPastEvent, + isTodayEvent, +}: Omit) { const borderClass = isTodayEvent ? "border-s-red" : "border-n-neutral-300"; const opacityClass = isPastEvent && "opacity-50"; const textClass = isTodayEvent ? "text-s-red" : "text-n-neutral-950"; diff --git a/client/src/constants/Main/rushEventData.ts b/client/src/constants/Main/rushEventData.ts new file mode 100644 index 00000000..8c3c4e84 --- /dev/null +++ b/client/src/constants/Main/rushEventData.ts @@ -0,0 +1,38 @@ +export interface RushEventProps { + id: number; + image: string; + prizeName: string; +} + +export const rushEventData: RushEventProps[] = [ + { + id: 1, + image: "/assets/main/rush/prize-1.png", + prizeName: "영화 예매권", + }, + { + id: 2, + image: "/assets/main/rush/prize-2.png", + prizeName: "야구 관람권", + }, + { + id: 3, + image: "/assets/main/rush/prize-3.jpg", + prizeName: "올리브영 상품권", + }, + { + id: 4, + image: "/assets/main/rush/prize-4.jpeg", + prizeName: "쿠팡 기프트카드", + }, + { + id: 5, + image: "/assets/main/rush/prize-5.jpg", + prizeName: "배달의민족 기프트카드", + }, + { + id: 6, + image: "/assets/main/rush/prize-6.jpg", + prizeName: "BBQ 기프트카드", + }, +]; diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 982c5d7c..2232ab91 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -1,48 +1,34 @@ -import RushEvent, { RushEventProps } from "@/components/RushEvent"; +import { useEffect, useState } from "react"; +import { RushAPI } from "@/apis/rushAPI.ts"; +import RushEvent, { TotalRushEventsProps } from "@/components/RushEvent"; +import { rushEventData } from "@/constants/Main/rushEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; -// TODO: API로 대체될 데이터 -export const rushEventData: RushEventProps[] = [ - { - id: 1, - date: "2024-07-28 09:00:00.000000", - image: "/assets/main/rush/prize-1.png", - prizeName: "영화 예매권", - }, - { - id: 2, - date: "2024-07-29 09:00:00.000000", - image: "/assets/main/rush/prize-2.png", - prizeName: "야구 관람권", - }, - { - id: 3, - date: "2024-07-30 09:00:00.000000", - image: "/assets/main/rush/prize-3.jpg", - prizeName: "올리브영 상품권", - }, - { - id: 4, - date: "2024-07-31 09:00:00.000000", - image: "/assets/main/rush/prize-4.jpeg", - prizeName: "쿠팡 기프트카드", - }, - { - id: 5, - date: "2024-08-01 09:00:00.000000", - image: "/assets/main/rush/prize-5.jpg", - prizeName: "배달의민족 기프트카드", - }, - { - id: 6, - date: "2024-08-02 09:00:00.000000", - image: "/assets/main/rush/prize-6.jpg", - prizeName: "BBQ 기프트카드", - }, -]; - export function Rush({ id }: SectionKeyProps) { + const [rushEvents, setRushEvents] = useState([]); + + useEffect(() => { + async function loadRushData() { + const data = await RushAPI.getRush(); + + const events = data.events.map((event) => { + const rushEvent = rushEventData.find((re) => re.id === event.rushEventId); + return { + id: event.rushEventId, + date: event.startDateTime, + image: rushEvent.image, + prizeName: rushEvent.prizeName, + isPastEvent: new Date(event.endDateTime) < new Date(data.serverDateTime), + isTodayEvent: event.rushEventId === data.todayEventId, + }; + }); + + setRushEvents(events); + } + loadRushData(); + }, []); + return (

이벤트 경품

- {rushEventData.map((event) => ( + {rushEvents.map((event) => ( ))}
From 8e5954ff3f8ad98217664ad0a0f396ea9ef37fe5 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 8 Aug 2024 20:27:24 +0900 Subject: [PATCH 018/111] =?UTF-8?q?feat:=20Rush=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EA=B2=BD=ED=92=88=20isPastEvent,=20isTodayEvent=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Rush.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 2232ab91..af53f3ef 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -11,16 +11,19 @@ export function Rush({ id }: SectionKeyProps) { useEffect(() => { async function loadRushData() { const data = await RushAPI.getRush(); + const serverDateTime = new Date(data.serverDateTime); const events = data.events.map((event) => { const rushEvent = rushEventData.find((re) => re.id === event.rushEventId); + const eventEndTime = new Date(event.endDateTime); return { id: event.rushEventId, date: event.startDateTime, image: rushEvent.image, prizeName: rushEvent.prizeName, - isPastEvent: new Date(event.endDateTime) < new Date(data.serverDateTime), - isTodayEvent: event.rushEventId === data.todayEventId, + isPastEvent: serverDateTime > eventEndTime, + isTodayEvent: + event.rushEventId === data.todayEventId && serverDateTime <= eventEndTime, }; }); From 3c78a9bef52b9234848a9936e4c8ad5c28921963 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 10:12:28 +0900 Subject: [PATCH 019/111] =?UTF-8?q?feat:=20date=20util=20=ED=8F=AC?= =?UTF-8?q?=EB=A7=B7=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B3=B5=ED=86=B5=20=ED=8C=8C=EC=8B=B1=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/utils/formatDate.ts | 54 +++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index 241e42eb..2dc79eb1 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -1,14 +1,52 @@ -export const formatDate = (dateString: string): string => { +export const parseDate = (dateString: string): Date | null => { const date = new Date(dateString); + return isNaN(date.getTime()) ? null : date; +}; - if (isNaN(date.getTime())) { - console.error(`Invalid date string: ${dateString}`); - return ""; - } - +export const getFormattedDateComponents = (date: Date) => { const month = date.getMonth() + 1; const day = date.getDate(); const DAY_OF_WEEK = ["일", "월", "화", "수", "목", "금", "토"]; - const today = DAY_OF_WEEK[date.getDay()]; - return `${month}/${day} (${today})`; + const dayOfWeek = DAY_OF_WEEK[date.getDay()]; + + return { month, day, dayOfWeek }; +}; + +export const formatDateWithSlash = (date: Date): string => { + const { month, day, dayOfWeek } = getFormattedDateComponents(date); + return `${month}/${day} (${dayOfWeek})`; +}; + +export const formatDateWithDot = (date: Date): string => { + const { month, day, dayOfWeek } = getFormattedDateComponents(date); + return `${month}. ${day}. (${dayOfWeek})`; +}; + +export const formatSingleDateWithSlash = (dateString: string): string => { + const date = parseDate(dateString); + if (!date) return ""; + + return formatDateWithSlash(date); +}; + +export const formatSingleDateWithDot = (dateString: string): string => { + const date = parseDate(dateString); + if (!date) return ""; + + return formatDateWithDot(date); +}; + +export const formatEventDateRangeWithDot = ( + startDateString: string, + endDateString: string +): string => { + const startDate = parseDate(startDateString); + const endDate = parseDate(endDateString); + + if (!startDate || !endDate) return ""; + + const startFormatted = formatDateWithDot(startDate); + const endFormatted = formatDateWithDot(endDate); + + return `${startFormatted} ~ ${endFormatted}`; }; From ebbc15c30fbec39569656393915eee6268a3da55 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 10:14:46 +0900 Subject: [PATCH 020/111] =?UTF-8?q?feat:=20Main=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20Rush=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushEvent/index.tsx | 4 ++-- client/src/features/Main/Rush.tsx | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/client/src/components/RushEvent/index.tsx b/client/src/components/RushEvent/index.tsx index fc10cef5..cd0bea57 100644 --- a/client/src/components/RushEvent/index.tsx +++ b/client/src/components/RushEvent/index.tsx @@ -1,5 +1,5 @@ import { RushEventProps } from "@/constants/Main/rushEventData.ts"; -import { formatDate } from "@/utils/formatDate.ts"; +import { formatSingleDateWithSlash } from "@/utils/formatDate.ts"; export interface TotalRushEventsProps extends RushEventProps { date: string; @@ -23,7 +23,7 @@ export default function RushEvent({ className={`relative w-[160px] h-[200px] py-7 px-5 rounded-500 bg-n-white flex flex-col gap-4 justify-between items-center border ${borderClass} ${opacityClass}`} >

- {isTodayEvent ? "Today" : formatDate(date)} + {isTodayEvent ? "Today" : formatSingleDateWithSlash(date)}

event prize

{prizeName}

diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index af53f3ef..b88a40dc 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -4,14 +4,19 @@ import RushEvent, { TotalRushEventsProps } from "@/components/RushEvent"; import { rushEventData } from "@/constants/Main/rushEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; +import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; export function Rush({ id }: SectionKeyProps) { const [rushEvents, setRushEvents] = useState([]); + const [startDateTime, setStartDateTime] = useState(null); + const [endDateTime, setEndDateTime] = useState(null); useEffect(() => { async function loadRushData() { const data = await RushAPI.getRush(); const serverDateTime = new Date(data.serverDateTime); + setStartDateTime(data.eventsStartDate); + setEndDateTime(data.eventsEndDate); const events = data.events.map((event) => { const rushEvent = rushEventData.find((re) => re.id === event.rushEventId); @@ -49,7 +54,9 @@ export function Rush({ id }: SectionKeyProps) {

이벤트 기간

- 2024. 08. 25. (목) ~ 2024. 09. 01. (일) + {startDateTime && endDateTime + ? formatEventDateRangeWithDot(startDateTime, endDateTime) + : ""}

매일 오후 10시!

From 1554c64ad2aefb5de8ede97eaf6255cdc25fbc09 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 10:24:38 +0900 Subject: [PATCH 021/111] =?UTF-8?q?feat:=20RushEvent=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20storybook=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/RushEvent/index.stories.tsx | 95 +++++++++++++++---- 1 file changed, 79 insertions(+), 16 deletions(-) diff --git a/client/src/components/RushEvent/index.stories.tsx b/client/src/components/RushEvent/index.stories.tsx index a89c811f..10c6be5d 100644 --- a/client/src/components/RushEvent/index.stories.tsx +++ b/client/src/components/RushEvent/index.stories.tsx @@ -1,6 +1,4 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { rushEventData } from "@/features/Main/Rush.tsx"; -import { formatDate } from "@/utils/formatDate.ts"; import RushEvent from "./index"; const meta: Meta = { @@ -11,24 +9,89 @@ const meta: Meta = { }, tags: ["autodocs"], argTypes: { - date: { control: "text", description: "선착순 이벤트 날짜" }, + date: { control: "text", description: "선착순 이벤트 시작 날짜" }, image: { control: "text", description: "선착순 이벤트 경품 이미지" }, prizeName: { control: "text", description: "선착순 이벤트 경품 이름" }, + isPastEvent: { control: "boolean", description: "이벤트가 종료되었는지 여부" }, + isTodayEvent: { control: "boolean", description: "오늘 이벤트 여부" }, }, }; export default meta; -export const AllPrizes: StoryFn = () => ( - <> - {rushEventData.map((event) => ( - - ))} - -); +export const AllPrizes: StoryFn = () => { + interface RushEventProps { + id: number; + date: string; + image: string; + prizeName: string; + isPastEvent: boolean; + isTodayEvent: boolean; + } + + const rushEventDataDummy: RushEventProps[] = [ + { + id: 1, + date: "2024-08-01T02:35:57.397Z", + image: "/assets/main/rush/prize-1.png", + prizeName: "영화 예매권", + isPastEvent: true, + isTodayEvent: false, + }, + { + id: 2, + date: "2024-08-02T02:35:57.397Z", + image: "/assets/main/rush/prize-2.png", + prizeName: "야구 관람권", + isPastEvent: true, + isTodayEvent: false, + }, + { + id: 3, + date: "2024-08-03T02:35:57.397Z", + image: "/assets/main/rush/prize-3.jpg", + prizeName: "올리브영 상품권", + isPastEvent: true, + isTodayEvent: false, + }, + { + id: 4, + date: "2024-08-04T02:35:57.397Z", + image: "/assets/main/rush/prize-4.jpeg", + prizeName: "쿠팡 기프트카드", + isPastEvent: true, + isTodayEvent: true, + }, + { + id: 5, + date: "2024-08-05T02:35:57.397Z", + image: "/assets/main/rush/prize-5.jpg", + prizeName: "배달의민족 기프트카드", + isPastEvent: false, + isTodayEvent: false, + }, + { + id: 6, + date: "2024-08-06T02:35:57.397Z", + image: "/assets/main/rush/prize-6.jpg", + prizeName: "BBQ 기프트카드", + isPastEvent: false, + isTodayEvent: false, + }, + ]; + + return ( + <> + {rushEventDataDummy.map((event) => ( + + ))} + + ); +}; From edea461f40589d808554f9c42417123ea469469f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 10:35:44 +0900 Subject: [PATCH 022/111] =?UTF-8?q?feat:=20Lottery=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?API=20=EB=AA=85=EC=84=B8=20=EB=B0=98=EC=98=81=20=EB=B0=8F=20API?= =?UTF-8?q?=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Lottery.tsx | 18 +++++++++++++++++- client/src/features/Main/Rush.tsx | 5 ++--- client/src/types/lotteryApi.ts | 8 ++++---- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/client/src/features/Main/Lottery.tsx b/client/src/features/Main/Lottery.tsx index 3d4526da..c4c009e7 100644 --- a/client/src/features/Main/Lottery.tsx +++ b/client/src/features/Main/Lottery.tsx @@ -1,11 +1,25 @@ +import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; +import { LotteryAPI } from "@/apis/lotteryAPI.ts"; import LotteryEvent from "@/components/LotteryEvent"; import { LOTTERY_EVENT_DATA } from "@/constants/Main/lotteryEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; +import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; import ArrowIcon from "/public/assets/icons/arrow.svg?react"; export function Lottery({ id }: SectionKeyProps) { + const [startDateTime, setStartDateTime] = useState(null); + const [endDateTime, setEndDateTime] = useState(null); + + useEffect(() => { + (async () => { + const data = await LotteryAPI.getLottery(); + setStartDateTime(data.eventStartDate); + setEndDateTime(data.eventEndDate); + })(); + }, []); + return (

이벤트 기간

- 2024. 08. 23. (금) ~ 2024. 09. 05 (목) + {startDateTime && endDateTime + ? formatEventDateRangeWithDot(startDateTime, endDateTime) + : ""}

diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index b88a40dc..302cc2d7 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -12,7 +12,7 @@ export function Rush({ id }: SectionKeyProps) { const [endDateTime, setEndDateTime] = useState(null); useEffect(() => { - async function loadRushData() { + (async () => { const data = await RushAPI.getRush(); const serverDateTime = new Date(data.serverDateTime); setStartDateTime(data.eventsStartDate); @@ -33,8 +33,7 @@ export function Rush({ id }: SectionKeyProps) { }); setRushEvents(events); - } - loadRushData(); + })(); }, []); return ( diff --git a/client/src/types/lotteryApi.ts b/client/src/types/lotteryApi.ts index 1e4f2782..b70c9929 100644 --- a/client/src/types/lotteryApi.ts +++ b/client/src/types/lotteryApi.ts @@ -24,8 +24,8 @@ export interface GetApplyCountResponse { } export interface GetLotteryResponse { - lotteryEventId: number; - startDate: string; - endDate: string; - winnerCount: number; + serverDateTime: string; + eventStartDate: string; + eventEndDate: string; + activePeriod: number; } From 252c1e395522b3a03fbf04c0cd01cd4ed6ee08ba Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 10:55:01 +0900 Subject: [PATCH 023/111] =?UTF-8?q?feat:=20date=20util=20=EC=97=B0?= =?UTF-8?q?=EB=8F=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/utils/formatDate.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index 2dc79eb1..d4daa148 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -4,12 +4,13 @@ export const parseDate = (dateString: string): Date | null => { }; export const getFormattedDateComponents = (date: Date) => { + const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const DAY_OF_WEEK = ["일", "월", "화", "수", "목", "금", "토"]; const dayOfWeek = DAY_OF_WEEK[date.getDay()]; - return { month, day, dayOfWeek }; + return { year, month, day, dayOfWeek }; }; export const formatDateWithSlash = (date: Date): string => { @@ -18,8 +19,8 @@ export const formatDateWithSlash = (date: Date): string => { }; export const formatDateWithDot = (date: Date): string => { - const { month, day, dayOfWeek } = getFormattedDateComponents(date); - return `${month}. ${day}. (${dayOfWeek})`; + const { year, month, day, dayOfWeek } = getFormattedDateComponents(date); + return `${year}. ${month}. ${day}. (${dayOfWeek})`; }; export const formatSingleDateWithSlash = (dateString: string): string => { From cc81296a9e2ec85975e3702a862c129294b5b42f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 11:25:15 +0900 Subject: [PATCH 024/111] =?UTF-8?q?fix:=20=EB=B9=8C=EB=93=9C=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Notice/index.tsx | 58 ++++++++++++++++++-------- client/src/features/Main/Rush.tsx | 6 ++- client/src/pages/Lottery/index.tsx | 4 +- client/src/utils/formatDate.ts | 20 +++++++++ 4 files changed, 67 insertions(+), 21 deletions(-) diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index 99dd762a..0c09eb8e 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -1,9 +1,12 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; +import { LotteryAPI } from "@/apis/lotteryAPI.ts"; +import { RushAPI } from "@/apis/rushAPI.ts"; +import { formatEventDateRangeWithDotNoDayOfWeek } from "@/utils/formatDate.ts"; interface EventDetails { startDate: string; endDate: string; - days: number; + activePeriod: number; } interface EventData { @@ -28,23 +31,42 @@ const Section: React.FC = ({ title, items, indentedIndices = [] }) ); export default function Notice() { - const eventDetails: EventData = { - // TODO: 임시 데이터 -> API로 변경 필요 - badgeDraw: { - startDate: "2024.08.23.", - endDate: "2024.09.05.", - days: 14, - }, - balanceGame: { - startDate: "2024.08.31.", - endDate: "2024.09.05.", - days: 6, - }, - }; + const [eventDetails, setEventDetails] = useState({}); + + useEffect(() => { + (async () => { + try { + const [rushData, lotteryData] = await Promise.all([ + RushAPI.getRush(), + LotteryAPI.getLottery(), + ]); + + const rushEventDetails: EventDetails = { + startDate: rushData.eventsStartDate, + endDate: rushData.eventsEndDate, + activePeriod: rushData.activePeriod, + }; + + const lotteryEventDetails: EventDetails = { + startDate: lotteryData.eventStartDate, + endDate: lotteryData.eventEndDate, + activePeriod: lotteryData.activePeriod, + }; + + setEventDetails({ + rush: lotteryEventDetails, + lottery: rushEventDetails, + }); + } catch (error) { + console.error("Error: ", error); + } + })(); + }, []); + const formatEventItem = (eventName: string, eventKey: keyof EventData) => { const event = eventDetails[eventKey]; if (event) { - return `${eventName} : ${event.startDate} ~ ${event.endDate} (${event.days}일)`; + return `${eventName} : ${formatEventDateRangeWithDotNoDayOfWeek(event.startDate, event.endDate)} (${event.activePeriod}일)`; } return `${eventName} : 날짜를 불러오는 중입니다...`; }; @@ -56,8 +78,8 @@ export default function Notice() { title="이벤트 참여" items={[ "이벤트 기간", - formatEventItem("캐스퍼봇 뱃지 추첨 이벤트", "badgeDraw"), - formatEventItem("선착순 밸런스 게임 이벤트", "balanceGame"), + formatEventItem("캐스퍼봇 뱃지 추첨 이벤트", "rush"), + formatEventItem("선착순 밸런스 게임 이벤트", "lottery"), "선착순 밸런스 게임 이벤트는 이벤트 기간 내 매일 하루에 한 번씩, 기간 내 최대 6번 참여 가능합니다.", "이벤트 참여 시 당첨자 연락을 위해 전화번호 기재와 개인정보 수집 동의, 마케팅 정보 수신 동의가 필수로 요구됩니다.", "본 이벤트에서 제작해주신 캐스퍼봇 이미지는 추후 마케팅에 이용될 수 있습니다.", diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 302cc2d7..3855c5db 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -19,7 +19,11 @@ export function Rush({ id }: SectionKeyProps) { setEndDateTime(data.eventsEndDate); const events = data.events.map((event) => { - const rushEvent = rushEventData.find((re) => re.id === event.rushEventId); + const rushEvent = rushEventData.find((re) => re.id === event.rushEventId) || { + image: "", + prizeName: "", + }; + const eventEndTime = new Date(event.endDateTime); return { id: event.rushEventId, diff --git a/client/src/pages/Lottery/index.tsx b/client/src/pages/Lottery/index.tsx index 59d76b2f..b1dd1a91 100644 --- a/client/src/pages/Lottery/index.tsx +++ b/client/src/pages/Lottery/index.tsx @@ -62,8 +62,8 @@ export default function Lottery() { const { showToast, ToastComponent } = useToast("이벤트 기간이 아닙니다"); const handleClickShortCut = () => { - const startDate = getMsTime(data.startDate); - const endDate = getMsTime(data.endDate); + const startDate = getMsTime(data.eventStartDate); + const endDate = getMsTime(data.eventEndDate); const currentDate = new Date().getTime(); const isEventPeriod = currentDate >= startDate && currentDate <= endDate; diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index d4daa148..8b440a73 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -23,6 +23,11 @@ export const formatDateWithDot = (date: Date): string => { return `${year}. ${month}. ${day}. (${dayOfWeek})`; }; +export const formatDateWithDotNoDayOfWeek = (date: Date): string => { + const { year, month, day } = getFormattedDateComponents(date); + return `${year}. ${month}. ${day}.`; +}; + export const formatSingleDateWithSlash = (dateString: string): string => { const date = parseDate(dateString); if (!date) return ""; @@ -51,3 +56,18 @@ export const formatEventDateRangeWithDot = ( return `${startFormatted} ~ ${endFormatted}`; }; + +export const formatEventDateRangeWithDotNoDayOfWeek = ( + startDateString: string, + endDateString: string +): string => { + const startDate = parseDate(startDateString); + const endDate = parseDate(endDateString); + + if (!startDate || !endDate) return ""; + + const startFormatted = formatDateWithDotNoDayOfWeek(startDate); + const endFormatted = formatDateWithDotNoDayOfWeek(endDate); + + return `${startFormatted} ~ ${endFormatted}`; +}; From 5d8e753a93da87d7921c3e6867c4b97ef7a2db44 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 11:43:13 +0900 Subject: [PATCH 025/111] =?UTF-8?q?refactor:=20formatEventDate=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=B9=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Notice/index.tsx | 26 +++++++++----------------- client/src/utils/formatDate.ts | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index 0c09eb8e..009a9189 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -1,16 +1,16 @@ import React, { useEffect, useState } from "react"; import { LotteryAPI } from "@/apis/lotteryAPI.ts"; import { RushAPI } from "@/apis/rushAPI.ts"; -import { formatEventDateRangeWithDotNoDayOfWeek } from "@/utils/formatDate.ts"; +import { formatEventDate } from "@/utils/formatDate.ts"; -interface EventDetails { +interface EventDateDetails { startDate: string; endDate: string; activePeriod: number; } -interface EventData { - [key: string]: EventDetails; +export interface EventDateData { + [key: string]: EventDateDetails; } interface SectionProps { @@ -31,7 +31,7 @@ const Section: React.FC = ({ title, items, indentedIndices = [] }) ); export default function Notice() { - const [eventDetails, setEventDetails] = useState({}); + const [eventDetails, setEventDetails] = useState({}); useEffect(() => { (async () => { @@ -41,13 +41,13 @@ export default function Notice() { LotteryAPI.getLottery(), ]); - const rushEventDetails: EventDetails = { + const rushEventDetails: EventDateDetails = { startDate: rushData.eventsStartDate, endDate: rushData.eventsEndDate, activePeriod: rushData.activePeriod, }; - const lotteryEventDetails: EventDetails = { + const lotteryEventDetails: EventDateDetails = { startDate: lotteryData.eventStartDate, endDate: lotteryData.eventEndDate, activePeriod: lotteryData.activePeriod, @@ -63,14 +63,6 @@ export default function Notice() { })(); }, []); - const formatEventItem = (eventName: string, eventKey: keyof EventData) => { - const event = eventDetails[eventKey]; - if (event) { - return `${eventName} : ${formatEventDateRangeWithDotNoDayOfWeek(event.startDate, event.endDate)} (${event.activePeriod}일)`; - } - return `${eventName} : 날짜를 불러오는 중입니다...`; - }; - return (

유의사항

@@ -78,8 +70,8 @@ export default function Notice() { title="이벤트 참여" items={[ "이벤트 기간", - formatEventItem("캐스퍼봇 뱃지 추첨 이벤트", "rush"), - formatEventItem("선착순 밸런스 게임 이벤트", "lottery"), + formatEventDate("캐스퍼봇 뱃지 추첨 이벤트", "rush", eventDetails), + formatEventDate("선착순 밸런스 게임 이벤트", "lottery", eventDetails), "선착순 밸런스 게임 이벤트는 이벤트 기간 내 매일 하루에 한 번씩, 기간 내 최대 6번 참여 가능합니다.", "이벤트 참여 시 당첨자 연락을 위해 전화번호 기재와 개인정보 수집 동의, 마케팅 정보 수신 동의가 필수로 요구됩니다.", "본 이벤트에서 제작해주신 캐스퍼봇 이미지는 추후 마케팅에 이용될 수 있습니다.", diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index 8b440a73..802abfa0 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -1,3 +1,5 @@ +import { EventDateData } from "@/components/Notice"; + export const parseDate = (dateString: string): Date | null => { const date = new Date(dateString); return isNaN(date.getTime()) ? null : date; @@ -71,3 +73,15 @@ export const formatEventDateRangeWithDotNoDayOfWeek = ( return `${startFormatted} ~ ${endFormatted}`; }; + +export const formatEventDate = ( + eventName: string, + eventKey: keyof EventDateData, + eventDetails: EventDateData +) => { + const event = eventDetails[eventKey]; + if (event) { + return `${eventName} : ${formatEventDateRangeWithDotNoDayOfWeek(event.startDate, event.endDate)} (${event.activePeriod}일)`; + } + return `${eventName} : 날짜를 불러오는 중입니다...`; +}; From 585d85214f1766fb71f5656ed39822d31ed96a2c Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 12:01:29 +0900 Subject: [PATCH 026/111] =?UTF-8?q?refactor:=20Notice=20fetch=20API=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Notice/index.tsx | 68 +++++++++++++++----------- client/src/utils/formatDate.ts | 6 +-- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index 009a9189..a1bd51af 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -30,36 +30,48 @@ const Section: React.FC = ({ title, items, indentedIndices = [] })
); -export default function Notice() { - const [eventDetails, setEventDetails] = useState({}); +const getEventsDateDetails = async (): Promise<{ + rush: EventDateDetails; + lottery: EventDateDetails; +}> => { + try { + const [rushData, lotteryData] = await Promise.all([ + RushAPI.getRush(), + LotteryAPI.getLottery(), + ]); - useEffect(() => { - (async () => { - try { - const [rushData, lotteryData] = await Promise.all([ - RushAPI.getRush(), - LotteryAPI.getLottery(), - ]); + const rushEventDetails: EventDateDetails = { + startDate: rushData.eventsStartDate, + endDate: rushData.eventsEndDate, + activePeriod: rushData.activePeriod, + }; - const rushEventDetails: EventDateDetails = { - startDate: rushData.eventsStartDate, - endDate: rushData.eventsEndDate, - activePeriod: rushData.activePeriod, - }; + const lotteryEventDetails: EventDateDetails = { + startDate: lotteryData.eventStartDate, + endDate: lotteryData.eventEndDate, + activePeriod: lotteryData.activePeriod, + }; - const lotteryEventDetails: EventDateDetails = { - startDate: lotteryData.eventStartDate, - endDate: lotteryData.eventEndDate, - activePeriod: lotteryData.activePeriod, - }; + return { + rush: lotteryEventDetails, + lottery: rushEventDetails, + }; + } catch (error) { + console.error("Error: ", error); + return { + rush: { startDate: "", endDate: "", activePeriod: 0 }, + lottery: { startDate: "", endDate: "", activePeriod: 0 }, + }; + } +}; - setEventDetails({ - rush: lotteryEventDetails, - lottery: rushEventDetails, - }); - } catch (error) { - console.error("Error: ", error); - } +export default function Notice() { + const [eventDateDetails, setEventDateDetails] = useState({}); + + useEffect(() => { + (async () => { + const details = await getEventsDateDetails(); + setEventDateDetails(details); })(); }, []); @@ -70,8 +82,8 @@ export default function Notice() { title="이벤트 참여" items={[ "이벤트 기간", - formatEventDate("캐스퍼봇 뱃지 추첨 이벤트", "rush", eventDetails), - formatEventDate("선착순 밸런스 게임 이벤트", "lottery", eventDetails), + formatEventDate("캐스퍼봇 뱃지 추첨 이벤트", "rush", eventDateDetails), + formatEventDate("선착순 밸런스 게임 이벤트", "lottery", eventDateDetails), "선착순 밸런스 게임 이벤트는 이벤트 기간 내 매일 하루에 한 번씩, 기간 내 최대 6번 참여 가능합니다.", "이벤트 참여 시 당첨자 연락을 위해 전화번호 기재와 개인정보 수집 동의, 마케팅 정보 수신 동의가 필수로 요구됩니다.", "본 이벤트에서 제작해주신 캐스퍼봇 이미지는 추후 마케팅에 이용될 수 있습니다.", diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index 802abfa0..24d5f94f 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -77,10 +77,10 @@ export const formatEventDateRangeWithDotNoDayOfWeek = ( export const formatEventDate = ( eventName: string, eventKey: keyof EventDateData, - eventDetails: EventDateData + eventDateDetails: EventDateData ) => { - const event = eventDetails[eventKey]; - if (event) { + const event = eventDateDetails[eventKey]; + if (event && event.startDate && event.endDate) { return `${eventName} : ${formatEventDateRangeWithDotNoDayOfWeek(event.startDate, event.endDate)} (${event.activePeriod}일)`; } return `${eventName} : 날짜를 불러오는 중입니다...`; From 3ef0416eec15500b8bdc58e7c5a5c9d731a88a5d Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 12:05:04 +0900 Subject: [PATCH 027/111] =?UTF-8?q?rename:=20rushEventData=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Main/rushEventData.ts | 2 +- client/src/features/Main/Rush.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/constants/Main/rushEventData.ts b/client/src/constants/Main/rushEventData.ts index 8c3c4e84..edb7eb23 100644 --- a/client/src/constants/Main/rushEventData.ts +++ b/client/src/constants/Main/rushEventData.ts @@ -4,7 +4,7 @@ export interface RushEventProps { prizeName: string; } -export const rushEventData: RushEventProps[] = [ +export const RUSH_EVENT_DATA: RushEventProps[] = [ { id: 1, image: "/assets/main/rush/prize-1.png", diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 3855c5db..823dd12f 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { RushAPI } from "@/apis/rushAPI.ts"; import RushEvent, { TotalRushEventsProps } from "@/components/RushEvent"; -import { rushEventData } from "@/constants/Main/rushEventData.ts"; +import { RUSH_EVENT_DATA } from "@/constants/Main/rushEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; @@ -19,7 +19,7 @@ export function Rush({ id }: SectionKeyProps) { setEndDateTime(data.eventsEndDate); const events = data.events.map((event) => { - const rushEvent = rushEventData.find((re) => re.id === event.rushEventId) || { + const rushEvent = RUSH_EVENT_DATA.find((re) => re.id === event.rushEventId) || { image: "", prizeName: "", }; From 0c8322ae3e88c2910b45e6a81077693141cb5b2f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 12:06:58 +0900 Subject: [PATCH 028/111] =?UTF-8?q?feat:=20Main=20Headline=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=20API=20=EC=97=B0=EB=8F=99=20(=EC=B6=94=ED=9B=84=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EA=B8=B0=EA=B0=84=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20API=EB=A1=9C=20=EC=97=B0=EB=8F=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Headline.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index 1267dca8..850bdc61 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -1,10 +1,23 @@ +import { useEffect, useState } from "react"; import { motion } from "framer-motion"; +import { LotteryAPI } from "@/apis/lotteryAPI.ts"; import Keyword from "@/components/Keyword"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import { SectionKeyProps } from "@/types/sections.ts"; +import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; export function Headline({ id }: SectionKeyProps) { + const [startDateTime, setStartDateTime] = useState(null); + const [endDateTime, setEndDateTime] = useState(null); + + useEffect(() => { + (async () => { + const data = await LotteryAPI.getLottery(); + setStartDateTime(data.eventStartDate); + setEndDateTime(data.eventEndDate); + })(); + }, []); return (

- 2024. 08. 21. (수) ~ 2024. 09. 03. (화) + {startDateTime && endDateTime + ? formatEventDateRangeWithDot(startDateTime, endDateTime) + : ""}

From 537d75a95f345d34e0f83e491c0287f5ee42b535 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 12:12:30 +0900 Subject: [PATCH 029/111] =?UTF-8?q?refactor:=20=EB=A1=9C=EB=94=A9=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/utils/formatDate.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index 24d5f94f..6c5da89f 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -1,5 +1,7 @@ import { EventDateData } from "@/components/Notice"; +const LOADING_DATE_MESSAGE = "날짜를 불러오는 중입니다..."; + export const parseDate = (dateString: string): Date | null => { const date = new Date(dateString); return isNaN(date.getTime()) ? null : date; @@ -32,14 +34,14 @@ export const formatDateWithDotNoDayOfWeek = (date: Date): string => { export const formatSingleDateWithSlash = (dateString: string): string => { const date = parseDate(dateString); - if (!date) return ""; + if (!date) return LOADING_DATE_MESSAGE; return formatDateWithSlash(date); }; export const formatSingleDateWithDot = (dateString: string): string => { const date = parseDate(dateString); - if (!date) return ""; + if (!date) return LOADING_DATE_MESSAGE; return formatDateWithDot(date); }; @@ -51,7 +53,7 @@ export const formatEventDateRangeWithDot = ( const startDate = parseDate(startDateString); const endDate = parseDate(endDateString); - if (!startDate || !endDate) return ""; + if (!startDate || !endDate) return LOADING_DATE_MESSAGE; const startFormatted = formatDateWithDot(startDate); const endFormatted = formatDateWithDot(endDate); @@ -66,7 +68,7 @@ export const formatEventDateRangeWithDotNoDayOfWeek = ( const startDate = parseDate(startDateString); const endDate = parseDate(endDateString); - if (!startDate || !endDate) return ""; + if (!startDate || !endDate) return LOADING_DATE_MESSAGE; const startFormatted = formatDateWithDotNoDayOfWeek(startDate); const endFormatted = formatDateWithDotNoDayOfWeek(endDate); @@ -83,5 +85,5 @@ export const formatEventDate = ( if (event && event.startDate && event.endDate) { return `${eventName} : ${formatEventDateRangeWithDotNoDayOfWeek(event.startDate, event.endDate)} (${event.activePeriod}일)`; } - return `${eventName} : 날짜를 불러오는 중입니다...`; + return `${eventName} : ${LOADING_DATE_MESSAGE}`; }; From 9a3134c55424d724a9e984553e3e3b163614b493 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 14:16:58 +0900 Subject: [PATCH 030/111] =?UTF-8?q?rename:=20data=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.tsx | 1 + client/src/features/Main/Headline.tsx | 7 ++++--- client/src/features/Main/Rush.tsx | 13 +++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/client/src/constants/Rush/rushCard.tsx b/client/src/constants/Rush/rushCard.tsx index 0fb95889..62256ad0 100644 --- a/client/src/constants/Rush/rushCard.tsx +++ b/client/src/constants/Rush/rushCard.tsx @@ -27,6 +27,7 @@ export const CARD_DAYS = { } as const; // TODO: 추후 API 연동 +// 색상은 클라이언트측에서 픽스 export const CARD_COLORS: { [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { FIRST_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index 850bdc61..8b8fcdcc 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -13,11 +13,12 @@ export function Headline({ id }: SectionKeyProps) { useEffect(() => { (async () => { - const data = await LotteryAPI.getLottery(); - setStartDateTime(data.eventStartDate); - setEndDateTime(data.eventEndDate); + const lotteryData = await LotteryAPI.getLottery(); + setStartDateTime(lotteryData.eventStartDate); + setEndDateTime(lotteryData.eventEndDate); })(); }, []); + return (
{ (async () => { - const data = await RushAPI.getRush(); - const serverDateTime = new Date(data.serverDateTime); - setStartDateTime(data.eventsStartDate); - setEndDateTime(data.eventsEndDate); + const rushData = await RushAPI.getRush(); + const serverDateTime = new Date(rushData.serverDateTime); + setStartDateTime(rushData.eventsStartDate); + setEndDateTime(rushData.eventsEndDate); - const events = data.events.map((event) => { + const events = rushData.events.map((event) => { const rushEvent = RUSH_EVENT_DATA.find((re) => re.id === event.rushEventId) || { image: "", prizeName: "", @@ -32,7 +32,8 @@ export function Rush({ id }: SectionKeyProps) { prizeName: rushEvent.prizeName, isPastEvent: serverDateTime > eventEndTime, isTodayEvent: - event.rushEventId === data.todayEventId && serverDateTime <= eventEndTime, + event.rushEventId === rushData.todayEventId && + serverDateTime <= eventEndTime, }; }); From 87c0e36d906c7c19a88c8607f38422df613b1e16 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 9 Aug 2024 15:00:23 +0900 Subject: [PATCH 031/111] =?UTF-8?q?chore:=20RushCard=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=9E=84=EC=8B=9C=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=ED=8F=B4=EB=8D=94=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/RushCard/index.stories.tsx | 65 +++++++++++++ .../RushCard/index.tsx} | 0 .../RushCardComparison/index.stories.tsx | 91 +++++++++++++++++++ .../RushCardComparison/index.tsx} | 3 +- .../RushCardDescription/index.stories.tsx | 56 ++++++++++++ .../RushCardDescription/index.tsx} | 0 client/src/constants/Rush/rushCard.tsx | 3 +- 7 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 client/src/components/RushCard/index.stories.tsx rename client/src/{features/Rush/RushCard.tsx => components/RushCard/index.tsx} (100%) create mode 100644 client/src/components/RushCardComparison/index.stories.tsx rename client/src/{features/Rush/RushCardComparison.tsx => components/RushCardComparison/index.tsx} (95%) create mode 100644 client/src/components/RushCardDescription/index.stories.tsx rename client/src/{features/Rush/RushCardDescription.tsx => components/RushCardDescription/index.tsx} (100%) diff --git a/client/src/components/RushCard/index.stories.tsx b/client/src/components/RushCard/index.stories.tsx new file mode 100644 index 00000000..b8049954 --- /dev/null +++ b/client/src/components/RushCard/index.stories.tsx @@ -0,0 +1,65 @@ +import { Meta, StoryFn } from "@storybook/react"; +import RushCard from "@/components/RushCard"; +import { CARD_COLOR } from "@/constants/Rush/rushCard"; + +export default { + title: "Components/RushCard", + component: RushCard, + argTypes: { + color: { + control: { type: "select" }, + options: Object.values(CARD_COLOR), + description: "The background gradient color of the card", + table: { + type: { summary: "CARD_COLOR" }, + defaultValue: { summary: CARD_COLOR.GREEN }, + }, + }, + title: { + control: { type: "text" }, + description: "The title displayed on the card", + table: { + type: { summary: "string" }, + defaultValue: { summary: "Card Title" }, + }, + }, + description: { + control: { type: "array" }, + description: "An array of descriptions displayed on the card", + table: { + type: { summary: "ReactNode[]" }, + defaultValue: { summary: [] }, + }, + }, + }, +} as Meta; + +const Template: StoryFn = (args) => ; + +export const BlueCard = Template.bind({}); +BlueCard.args = { + color: CARD_COLOR.BLUE, + title: "Blue Card", + description: ["This is a blue card", "It has a gradient background"], +}; + +export const RedCard = Template.bind({}); +RedCard.args = { + color: CARD_COLOR.RED, + title: "Red Card", + description: ["This is a red card", "It has a gradient background"], +}; + +export const YellowCard = Template.bind({}); +YellowCard.args = { + color: CARD_COLOR.YELLOW, + title: "Yellow Card", + description: ["This is a yellow card", "It has a gradient background"], +}; + +export const GreenCard = Template.bind({}); +GreenCard.args = { + color: CARD_COLOR.GREEN, + title: "Green Card", + description: ["This is a green card", "It has a gradient background"], +}; diff --git a/client/src/features/Rush/RushCard.tsx b/client/src/components/RushCard/index.tsx similarity index 100% rename from client/src/features/Rush/RushCard.tsx rename to client/src/components/RushCard/index.tsx diff --git a/client/src/components/RushCardComparison/index.stories.tsx b/client/src/components/RushCardComparison/index.stories.tsx new file mode 100644 index 00000000..c9682dbf --- /dev/null +++ b/client/src/components/RushCardComparison/index.stories.tsx @@ -0,0 +1,91 @@ +import { Meta, StoryFn } from "@storybook/react"; +import RushCardComparison from "@/components/RushCardComparison"; +import { CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; + +export default { + title: "Components/RushCardComparison", + component: RushCardComparison, + argTypes: { + currentDay: { + control: { type: "select" }, + options: Object.values(CARD_DAYS), + description: "The current day for selecting the card colors and titles", + table: { + type: { summary: "CARD_DAYS" }, + defaultValue: { summary: CARD_DAYS.DAY1 }, + }, + }, + firstCardType: { + control: { type: "select" }, + options: Object.values(CARD_TYPE), + description: "The type of the first card", + table: { + type: { summary: "CARD_TYPE" }, + defaultValue: { summary: CARD_TYPE.FIRST_CARD }, + }, + }, + secondCardType: { + control: { type: "select" }, + options: Object.values(CARD_TYPE), + description: "The type of the second card", + table: { + type: { summary: "CARD_TYPE" }, + defaultValue: { summary: CARD_TYPE.SECOND_CARD }, + }, + }, + cardStatus: { + control: { type: "select" }, + options: Object.values(CARD_SELECTED_STATUS), + description: "The selection status of the card", + table: { + type: { summary: "CARD_SELECTED_STATUS" }, + defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, + }, + }, + }, +} as Meta; + +const Template: StoryFn = (args) => ; + +export const FirstDay = Template.bind({}); +FirstDay.args = { + currentDay: CARD_DAYS.DAY1, + firstCardType: CARD_TYPE.FIRST_CARD, + secondCardType: CARD_TYPE.SECOND_CARD, + cardStatus: CARD_SELECTED_STATUS.FALSE, +}; +export const SecondDay = Template.bind({}); +SecondDay.args = { + currentDay: CARD_DAYS.DAY2, + firstCardType: CARD_TYPE.FIRST_CARD, + secondCardType: CARD_TYPE.SECOND_CARD, + cardStatus: CARD_SELECTED_STATUS.FALSE, +}; +export const ThirdDay = Template.bind({}); +ThirdDay.args = { + currentDay: CARD_DAYS.DAY3, + firstCardType: CARD_TYPE.FIRST_CARD, + secondCardType: CARD_TYPE.SECOND_CARD, + cardStatus: CARD_SELECTED_STATUS.FALSE, +}; +export const FourthDay = Template.bind({}); +FourthDay.args = { + currentDay: CARD_DAYS.DAY4, + firstCardType: CARD_TYPE.FIRST_CARD, + secondCardType: CARD_TYPE.SECOND_CARD, + cardStatus: CARD_SELECTED_STATUS.FALSE, +}; +export const FifthDay = Template.bind({}); +FifthDay.args = { + currentDay: CARD_DAYS.DAY5, + firstCardType: CARD_TYPE.FIRST_CARD, + secondCardType: CARD_TYPE.SECOND_CARD, + cardStatus: CARD_SELECTED_STATUS.FALSE, +}; +export const SixthDay = Template.bind({}); +SixthDay.args = { + currentDay: CARD_DAYS.DAY6, + firstCardType: CARD_TYPE.FIRST_CARD, + secondCardType: CARD_TYPE.SECOND_CARD, + cardStatus: CARD_SELECTED_STATUS.FALSE, +}; diff --git a/client/src/features/Rush/RushCardComparison.tsx b/client/src/components/RushCardComparison/index.tsx similarity index 95% rename from client/src/features/Rush/RushCardComparison.tsx rename to client/src/components/RushCardComparison/index.tsx index 06db87a4..3d98dec9 100644 --- a/client/src/features/Rush/RushCardComparison.tsx +++ b/client/src/components/RushCardComparison/index.tsx @@ -1,3 +1,4 @@ +import RushCard from "@/components/RushCard/index.tsx"; import { CARD_COLORS, CARD_DAYS, @@ -6,10 +7,8 @@ import { CARD_TITLES, CARD_TYPE, } from "@/constants/Rush/rushCard.tsx"; -import RushCard from "@/features/Rush/RushCard.tsx"; export default function RushCardComparison() { - // TODO: 추후 API 연동 const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; const firstCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.FIRST_CARD; const secondCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.SECOND_CARD; diff --git a/client/src/components/RushCardDescription/index.stories.tsx b/client/src/components/RushCardDescription/index.stories.tsx new file mode 100644 index 00000000..7f5c11d1 --- /dev/null +++ b/client/src/components/RushCardDescription/index.stories.tsx @@ -0,0 +1,56 @@ +import { Meta, StoryFn } from "@storybook/react"; +import RushCardDescription from "@/components/RushCardDescription"; +import { CARD_COLOR, CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; + +export default { + title: "Components/RushCardDescription", + component: RushCardDescription, + argTypes: { + color: { + control: { type: "select" }, + options: Object.values(CARD_COLOR), + description: "The background color of the card", + table: { + type: { summary: "CARD_COLOR" }, + defaultValue: { summary: CARD_COLOR.GREEN }, + }, + }, + day: { + control: { type: "select" }, + options: Object.values(CARD_DAYS), + description: "The current day for selecting the card details", + table: { + type: { summary: "CARD_DAYS" }, + defaultValue: { summary: CARD_DAYS.DAY1 }, + }, + }, + cardType: { + control: { type: "select" }, + options: Object.values(CARD_TYPE), + description: "두 개의 카드 중 하나", + table: { + type: { summary: "CARD_TYPE" }, + defaultValue: { summary: CARD_TYPE.FIRST_CARD }, + }, + }, + cardStatus: { + control: { type: "select" }, + options: Object.values(CARD_SELECTED_STATUS), + description: "The selection status of the card", + table: { + type: { summary: "CARD_SELECTED_STATUS" }, + defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, + }, + }, + }, +} as Meta; + +const Template: StoryFn = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + color: CARD_COLOR.GREEN, + day: CARD_DAYS.DAY5, + cardType: CARD_TYPE.FIRST_CARD, + cardStatus: CARD_SELECTED_STATUS.TRUE, +}; diff --git a/client/src/features/Rush/RushCardDescription.tsx b/client/src/components/RushCardDescription/index.tsx similarity index 100% rename from client/src/features/Rush/RushCardDescription.tsx rename to client/src/components/RushCardDescription/index.tsx diff --git a/client/src/constants/Rush/rushCard.tsx b/client/src/constants/Rush/rushCard.tsx index 62256ad0..b68490ce 100644 --- a/client/src/constants/Rush/rushCard.tsx +++ b/client/src/constants/Rush/rushCard.tsx @@ -26,8 +26,7 @@ export const CARD_DAYS = { DAY6: 6, } as const; -// TODO: 추후 API 연동 -// 색상은 클라이언트측에서 픽스 +// TODO: 추후 API 연동 / 색상은 클라이언트 측에서 픽스 export const CARD_COLORS: { [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { FIRST_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; From 48acdaa914dd0b93186daf4e2a2b0962c5e1d176 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 16:11:47 +0900 Subject: [PATCH 032/111] =?UTF-8?q?feat:=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=ED=9B=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useCountDown.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 client/src/hooks/useCountDown.ts diff --git a/client/src/hooks/useCountDown.ts b/client/src/hooks/useCountDown.ts new file mode 100644 index 00000000..c1e6981a --- /dev/null +++ b/client/src/hooks/useCountDown.ts @@ -0,0 +1,17 @@ +import { useEffect, useState } from "react"; + +export default function useCountDown(initialTime: number) { + const [time, setTime] = useState(initialTime); + + useEffect(() => { + if (time <= 0) return; + + const timer = setInterval(() => { + setTime((prevTime) => prevTime - 1); + }, 1000); + + return () => clearInterval(timer); + }, [time]); + + return time; +} From 13bb2544ff931f9b234a7de21cf17debb09ca2a2 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 16:17:27 +0900 Subject: [PATCH 033/111] =?UTF-8?q?feat:=20BalanceGame=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=A7=84=ED=96=89=20=EB=B0=8F=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EC=B0=B8=EC=97=AC=20=EC=83=81=ED=83=9C=20Context?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/balanceGameContext.tsx | 17 +++++++++++++++++ client/src/hooks/useBalanceGameContext.ts | 10 ++++++++++ client/src/pages/Rush/index.tsx | 6 +++++- client/src/types/balanceGame.ts | 9 +++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 client/src/contexts/balanceGameContext.tsx create mode 100644 client/src/hooks/useBalanceGameContext.ts create mode 100644 client/src/types/balanceGame.ts diff --git a/client/src/contexts/balanceGameContext.tsx b/client/src/contexts/balanceGameContext.tsx new file mode 100644 index 00000000..3ae934d0 --- /dev/null +++ b/client/src/contexts/balanceGameContext.tsx @@ -0,0 +1,17 @@ +import React, { ReactNode, createContext, useState } from "react"; +import { BalanceGameContextType } from "@/types/balanceGame"; + +export const BalanceGameContext = createContext(undefined); + +export const BalanceGameProvider = ({ children }: { children: ReactNode }) => { + const [gameState, setGameState] = useState({ + phase: "PRE_EVENT", + userParticipationStatus: "NOT_PARTICIPATED", + }); + + return ( + + {children} + + ); +}; diff --git a/client/src/hooks/useBalanceGameContext.ts b/client/src/hooks/useBalanceGameContext.ts new file mode 100644 index 00000000..22f1c50f --- /dev/null +++ b/client/src/hooks/useBalanceGameContext.ts @@ -0,0 +1,10 @@ +import { useContext } from "react"; +import { BalanceGameContext } from "@/contexts/balanceGameContext.tsx"; + +export const useBalanceGameContext = () => { + const context = useContext(BalanceGameContext); + if (context === undefined) { + throw new Error("useBalanceGameContext must be used within a BalanceGameProvider"); + } + return context; +}; diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index eb72ec89..26b42302 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -1,6 +1,7 @@ import Footer from "@/components/Footer"; import Notice from "@/components/Notice"; import { RUSH_SECTIONS } from "@/constants/PageSections/sections.ts"; +import { BalanceGameProvider } from "@/contexts/balanceGameContext.tsx"; import { BalanceGame, CasperCharge, @@ -24,9 +25,12 @@ export default function Rush() { const containerRef = useHeaderStyleObserver({ darkSections: [RUSH_SECTIONS.INTRO], }); + return (
- + + + diff --git a/client/src/types/balanceGame.ts b/client/src/types/balanceGame.ts new file mode 100644 index 00000000..0018ea3d --- /dev/null +++ b/client/src/types/balanceGame.ts @@ -0,0 +1,9 @@ +import React from "react"; + +export interface BalanceGameContextType { + gameState: { + phase: "PRE_EVENT" | "EVENT_RUNNING" | "EVENT_ENDED"; + userParticipationStatus: "NOT_PARTICIPATED" | "SELECTED" | "VIEWED_RESULT"; + }; + setGameState: React.Dispatch>; +} From da6e206ffe8a590d3990ed20fdfccad7916540c0 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 16:18:04 +0900 Subject: [PATCH 034/111] =?UTF-8?q?feat:=20RushCard=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20description=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCard/index.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/client/src/components/RushCard/index.tsx b/client/src/components/RushCard/index.tsx index 5452bb09..93b4b445 100644 --- a/client/src/components/RushCard/index.tsx +++ b/client/src/components/RushCard/index.tsx @@ -1,11 +1,10 @@ -import { ReactNode } from "react"; import { cva } from "class-variance-authority"; import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; interface RushCardProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; title: string; - description: ReactNode[]; + description: string; } const backgroundGradients = cva( @@ -29,11 +28,7 @@ export default function RushCard({ color, title, description }: RushCardProps) { return (

{title}

- {description.map((text, index) => ( -

- {text} -

- ))} +

{description}

); } From 5ec52496f4b4580d143f3d521ea5b490ec0de449 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 16:45:15 +0900 Subject: [PATCH 035/111] =?UTF-8?q?fix:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=20=EC=83=81=ED=83=9C=20=ED=83=80=EC=9E=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 6 ++++-- client/src/contexts/balanceGameContext.tsx | 14 ++++++++++++-- client/src/types/balanceGame.ts | 4 +++- client/src/types/rushApi.ts | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index 93a2fcd1..b9f1ccd4 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -1,8 +1,8 @@ import { GetRushBalanceResponse, GetRushOptionResultResponse, - GetRushParticipationStatusResponse, GetRushResultResponse, + GetRushUserParticipationStatusResponse, GetTodayRushEventResponse, GetTotalRushEventsResponse, PostSelectedRushCardOptionResponse, @@ -26,7 +26,9 @@ export const RushAPI = { throw error; } }, - async getRushParticipationStatus(token: string): Promise { + async getRushUserParticipationStatus( + token: string + ): Promise { try { const response = await fetch(`${baseURL}/applied`, { method: "GET", diff --git a/client/src/contexts/balanceGameContext.tsx b/client/src/contexts/balanceGameContext.tsx index 3ae934d0..e3b7acc5 100644 --- a/client/src/contexts/balanceGameContext.tsx +++ b/client/src/contexts/balanceGameContext.tsx @@ -1,16 +1,26 @@ import React, { ReactNode, createContext, useState } from "react"; import { BalanceGameContextType } from "@/types/balanceGame"; +import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; export const BalanceGameContext = createContext(undefined); export const BalanceGameProvider = ({ children }: { children: ReactNode }) => { const [gameState, setGameState] = useState({ phase: "PRE_EVENT", - userParticipationStatus: "NOT_PARTICIPATED", + userParticipated: false, }); + const updateUserParticipationStatus = (response: GetRushUserParticipationStatusResponse) => { + setGameState((prevState) => ({ + ...prevState, + userParticipated: response.result, + })); + }; + return ( - + {children} ); diff --git a/client/src/types/balanceGame.ts b/client/src/types/balanceGame.ts index 0018ea3d..50d68d7e 100644 --- a/client/src/types/balanceGame.ts +++ b/client/src/types/balanceGame.ts @@ -1,9 +1,11 @@ import React from "react"; +import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; export interface BalanceGameContextType { gameState: { phase: "PRE_EVENT" | "EVENT_RUNNING" | "EVENT_ENDED"; - userParticipationStatus: "NOT_PARTICIPATED" | "SELECTED" | "VIEWED_RESULT"; + userParticipated: boolean; }; setGameState: React.Dispatch>; + updateUserParticipationStatus: (response: GetRushUserParticipationStatusResponse) => void; } diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts index cf1d776a..112ca155 100644 --- a/client/src/types/rushApi.ts +++ b/client/src/types/rushApi.ts @@ -18,7 +18,7 @@ export interface GetTotalRushEventsResponse { events: RushEventType[]; } -export interface GetRushParticipationStatusResponse { +export interface GetRushUserParticipationStatusResponse { result: boolean; } From 1d1f9049a190769b47c2e80e3f1d432fd4c7d83e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 17:10:31 +0900 Subject: [PATCH 036/111] =?UTF-8?q?feat:=20countdown=20timer=200=EC=B4=88?= =?UTF-8?q?=EC=9D=BC=20=EB=95=8C=20=EC=A2=85=EB=A3=8C=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useCountDown.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/hooks/useCountDown.ts b/client/src/hooks/useCountDown.ts index c1e6981a..50985cb2 100644 --- a/client/src/hooks/useCountDown.ts +++ b/client/src/hooks/useCountDown.ts @@ -7,7 +7,13 @@ export default function useCountDown(initialTime: number) { if (time <= 0) return; const timer = setInterval(() => { - setTime((prevTime) => prevTime - 1); + setTime((prevTime) => { + if (prevTime <= 0) { + clearInterval(timer); + return 0; + } + return prevTime - 1; + }); }, 1000); return () => clearInterval(timer); From f7caf8fb5f921394e770b063992b7bcad4e3afbb Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 17:12:09 +0900 Subject: [PATCH 037/111] =?UTF-8?q?feat:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=20=EA=B4=80=EB=A0=A8=20API=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B0=81=20=EC=84=B9=EC=85=98=20=EB=B6=84=EA=B8=B0?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/balanceGameContext.tsx | 2 +- client/src/features/Rush/BalanceGame.tsx | 92 +++++++++++++------ .../features/Rush/BalanceGame/CardOptions.tsx | 3 + .../features/Rush/BalanceGame/CountDown.tsx | 46 ++++++++++ .../Rush/BalanceGame/CurrentRatio.tsx | 3 + .../features/Rush/BalanceGame/FinalResult.tsx | 3 + .../Rush/BalanceGame/SelectedCard.tsx | 3 + 7 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 client/src/features/Rush/BalanceGame/CardOptions.tsx create mode 100644 client/src/features/Rush/BalanceGame/CountDown.tsx create mode 100644 client/src/features/Rush/BalanceGame/CurrentRatio.tsx create mode 100644 client/src/features/Rush/BalanceGame/FinalResult.tsx create mode 100644 client/src/features/Rush/BalanceGame/SelectedCard.tsx diff --git a/client/src/contexts/balanceGameContext.tsx b/client/src/contexts/balanceGameContext.tsx index e3b7acc5..d9aa83f0 100644 --- a/client/src/contexts/balanceGameContext.tsx +++ b/client/src/contexts/balanceGameContext.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, createContext, useState } from "react"; +import { ReactNode, createContext, useState } from "react"; import { BalanceGameContextType } from "@/types/balanceGame"; import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index adebe696..daddca6c 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -1,42 +1,80 @@ +import { useEffect, useState } from "react"; import { motion } from "framer-motion"; +import { useCookies } from "react-cookie"; +import { RushAPI } from "@/apis/rushAPI.ts"; import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; +import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { Background } from "@/features/Rush/Background.tsx"; +import CardOptions from "@/features/Rush/BalanceGame/CardOptions.tsx"; +import CountDown from "@/features/Rush/BalanceGame/CountDown.tsx"; +import FinalResult from "@/features/Rush/BalanceGame/FinalResult.tsx"; +import SelectedCard from "@/features/Rush/BalanceGame/SelectedCard.tsx"; +import { useBalanceGameContext } from "@/hooks/useBalanceGameContext.ts"; +import useCountDown from "@/hooks/useCountDown.ts"; import { SectionKeyProps } from "@/types/sections.ts"; export function BalanceGame({ id }: SectionKeyProps) { + const [cookies] = useCookies([COOKIE_TOKEN_KEY]); + const { gameState, setGameState, updateUserParticipationStatus } = useBalanceGameContext(); + const [initialCountdown, setInitialCountdown] = useState(null); + + useEffect(() => { + (async () => { + try { + const rushData = await RushAPI.getRush(); + const currentEvent = rushData.events.find( + (event) => event.rushEventId === rushData.todayEventId + ); + + if (rushData.serverDateTime && currentEvent?.startDateTime) { + const serverTime = new Date(rushData.serverDateTime).getTime(); + const startTime = new Date(currentEvent.startDateTime).getTime(); + const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); + setInitialCountdown(countdown); + } + + const userParticipated = await RushAPI.getRushUserParticipationStatus( + cookies[COOKIE_TOKEN_KEY] + ); + updateUserParticipationStatus(userParticipated); + } catch (error) { + console.error("Error:", error); + } + })(); + }, []); + + const countdown = useCountDown(initialCountdown || 0); + + useEffect(() => { + if (countdown === 0 && gameState.phase === "PRE_EVENT") { + setGameState((prev) => ({ ...prev, phase: "EVENT_RUNNING" })); + } + }, [countdown, gameState.phase, setGameState]); + + const renderBalanceGameContent = () => { + switch (gameState.phase) { + case "PRE_EVENT": + return ; + case "EVENT_RUNNING": + if (!gameState.userParticipated) { + return ; + } else { + return ; + } + case "EVENT_ENDED": + return ; + default: + return null; + } + }; + return (
- - 이제 곧 하단에 밸런스 게임 주제가 공개돼요! - - -
-

- 밸런스 게임 주제 공개까지 남은 시간 -

-
- -

Hours

-

04

-
-

:

- -

Minutes

-

21

-
-

:

- -

Seconds

-

32

-
-
-
-
+ {renderBalanceGameContent()} ; +} diff --git a/client/src/features/Rush/BalanceGame/CountDown.tsx b/client/src/features/Rush/BalanceGame/CountDown.tsx new file mode 100644 index 00000000..c26de210 --- /dev/null +++ b/client/src/features/Rush/BalanceGame/CountDown.tsx @@ -0,0 +1,46 @@ +import { motion } from "framer-motion"; +import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import { Background } from "@/features/Rush/Background.tsx"; + +interface CountDownProps { + countdown: number; +} + +export default function CountDown({ countdown }: CountDownProps) { + const hours = Math.floor(countdown / 3600); + const minutes = Math.floor((countdown % 3600) / 60); + const seconds = countdown % 60; + + const formatTime = (time: number) => time.toString().padStart(2, "0"); + + return ( + <> + + 이제 곧 하단에 밸런스 게임 주제가 공개돼요! + + +
+

+ 밸런스 게임 주제 공개까지 남은 시간 +

+
+ +

Hours

+

{formatTime(hours)}

+
+

:

+ +

Minutes

+

{formatTime(minutes)}

+
+

:

+ +

Seconds

+

{formatTime(seconds)}

+
+
+
+
+ + ); +} diff --git a/client/src/features/Rush/BalanceGame/CurrentRatio.tsx b/client/src/features/Rush/BalanceGame/CurrentRatio.tsx new file mode 100644 index 00000000..f3a06b3b --- /dev/null +++ b/client/src/features/Rush/BalanceGame/CurrentRatio.tsx @@ -0,0 +1,3 @@ +export default function CurrentRatio() { + return <>; +} diff --git a/client/src/features/Rush/BalanceGame/FinalResult.tsx b/client/src/features/Rush/BalanceGame/FinalResult.tsx new file mode 100644 index 00000000..cf395fe8 --- /dev/null +++ b/client/src/features/Rush/BalanceGame/FinalResult.tsx @@ -0,0 +1,3 @@ +export default function FinalResult() { + return <>; +} diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/SelectedCard.tsx new file mode 100644 index 00000000..e90314a4 --- /dev/null +++ b/client/src/features/Rush/BalanceGame/SelectedCard.tsx @@ -0,0 +1,3 @@ +export default function SelectedCard() { + return <>; +} From f9d50222ccd7ed85ed63039fbee35bdaa4212b04 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 17:21:13 +0900 Subject: [PATCH 038/111] =?UTF-8?q?chore:=20RushCard=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20?= =?UTF-8?q?=EC=9E=84=EC=8B=9C=20=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/RushCard/index.stories.tsx | 131 ++++++------- .../RushCardComparison/index.stories.tsx | 183 +++++++++--------- .../RushCardDescription/index.stories.tsx | 113 +++++------ 3 files changed, 215 insertions(+), 212 deletions(-) diff --git a/client/src/components/RushCard/index.stories.tsx b/client/src/components/RushCard/index.stories.tsx index b8049954..44b0d36a 100644 --- a/client/src/components/RushCard/index.stories.tsx +++ b/client/src/components/RushCard/index.stories.tsx @@ -1,65 +1,66 @@ -import { Meta, StoryFn } from "@storybook/react"; -import RushCard from "@/components/RushCard"; -import { CARD_COLOR } from "@/constants/Rush/rushCard"; - -export default { - title: "Components/RushCard", - component: RushCard, - argTypes: { - color: { - control: { type: "select" }, - options: Object.values(CARD_COLOR), - description: "The background gradient color of the card", - table: { - type: { summary: "CARD_COLOR" }, - defaultValue: { summary: CARD_COLOR.GREEN }, - }, - }, - title: { - control: { type: "text" }, - description: "The title displayed on the card", - table: { - type: { summary: "string" }, - defaultValue: { summary: "Card Title" }, - }, - }, - description: { - control: { type: "array" }, - description: "An array of descriptions displayed on the card", - table: { - type: { summary: "ReactNode[]" }, - defaultValue: { summary: [] }, - }, - }, - }, -} as Meta; - -const Template: StoryFn = (args) => ; - -export const BlueCard = Template.bind({}); -BlueCard.args = { - color: CARD_COLOR.BLUE, - title: "Blue Card", - description: ["This is a blue card", "It has a gradient background"], -}; - -export const RedCard = Template.bind({}); -RedCard.args = { - color: CARD_COLOR.RED, - title: "Red Card", - description: ["This is a red card", "It has a gradient background"], -}; - -export const YellowCard = Template.bind({}); -YellowCard.args = { - color: CARD_COLOR.YELLOW, - title: "Yellow Card", - description: ["This is a yellow card", "It has a gradient background"], -}; - -export const GreenCard = Template.bind({}); -GreenCard.args = { - color: CARD_COLOR.GREEN, - title: "Green Card", - description: ["This is a green card", "It has a gradient background"], -}; +// import { Meta, StoryFn } from "@storybook/react"; +// import RushCard from "@/components/RushCard"; +// import { CARD_COLOR } from "@/constants/Rush/rushCard"; +// +// export default { +// title: "Components/RushCard", +// component: RushCard, +// argTypes: { +// color: { +// control: { type: "select" }, +// options: Object.values(CARD_COLOR), +// description: "The background gradient color of the card", +// table: { +// type: { summary: "CARD_COLOR" }, +// defaultValue: { summary: CARD_COLOR.GREEN }, +// }, +// }, +// title: { +// control: { type: "text" }, +// description: "The title displayed on the card", +// table: { +// type: { summary: "string" }, +// defaultValue: { summary: "Card Title" }, +// }, +// }, +// description: { +// control: { type: "array" }, +// description: "An array of descriptions displayed on the card", +// table: { +// type: { summary: "ReactNode[]" }, +// defaultValue: { summary: [] }, +// }, +// }, +// }, +// } as Meta; +// +// const Template: StoryFn = (args) => ; +// +// export const BlueCard = Template.bind({}); +// BlueCard.args = { +// color: CARD_COLOR.BLUE, +// title: "Blue Card", +// description: ["This is a blue card", "It has a gradient background"], +// }; +// +// export const RedCard = Template.bind({}); +// RedCard.args = { +// color: CARD_COLOR.RED, +// title: "Red Card", +// description: ["This is a red card", "It has a gradient background"], +// }; +// +// export const YellowCard = Template.bind({}); +// YellowCard.args = { +// color: CARD_COLOR.YELLOW, +// title: "Yellow Card", +// description: ["This is a yellow card", "It has a gradient background"], +// }; +// +// export const GreenCard = Template.bind({}); +// GreenCard.args = { +// color: CARD_COLOR.GREEN, +// title: "Green Card", +// description: ["This is a green card", "It has a gradient background"], +// }; +export default {}; diff --git a/client/src/components/RushCardComparison/index.stories.tsx b/client/src/components/RushCardComparison/index.stories.tsx index c9682dbf..abf4be74 100644 --- a/client/src/components/RushCardComparison/index.stories.tsx +++ b/client/src/components/RushCardComparison/index.stories.tsx @@ -1,91 +1,92 @@ -import { Meta, StoryFn } from "@storybook/react"; -import RushCardComparison from "@/components/RushCardComparison"; -import { CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; - -export default { - title: "Components/RushCardComparison", - component: RushCardComparison, - argTypes: { - currentDay: { - control: { type: "select" }, - options: Object.values(CARD_DAYS), - description: "The current day for selecting the card colors and titles", - table: { - type: { summary: "CARD_DAYS" }, - defaultValue: { summary: CARD_DAYS.DAY1 }, - }, - }, - firstCardType: { - control: { type: "select" }, - options: Object.values(CARD_TYPE), - description: "The type of the first card", - table: { - type: { summary: "CARD_TYPE" }, - defaultValue: { summary: CARD_TYPE.FIRST_CARD }, - }, - }, - secondCardType: { - control: { type: "select" }, - options: Object.values(CARD_TYPE), - description: "The type of the second card", - table: { - type: { summary: "CARD_TYPE" }, - defaultValue: { summary: CARD_TYPE.SECOND_CARD }, - }, - }, - cardStatus: { - control: { type: "select" }, - options: Object.values(CARD_SELECTED_STATUS), - description: "The selection status of the card", - table: { - type: { summary: "CARD_SELECTED_STATUS" }, - defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, - }, - }, - }, -} as Meta; - -const Template: StoryFn = (args) => ; - -export const FirstDay = Template.bind({}); -FirstDay.args = { - currentDay: CARD_DAYS.DAY1, - firstCardType: CARD_TYPE.FIRST_CARD, - secondCardType: CARD_TYPE.SECOND_CARD, - cardStatus: CARD_SELECTED_STATUS.FALSE, -}; -export const SecondDay = Template.bind({}); -SecondDay.args = { - currentDay: CARD_DAYS.DAY2, - firstCardType: CARD_TYPE.FIRST_CARD, - secondCardType: CARD_TYPE.SECOND_CARD, - cardStatus: CARD_SELECTED_STATUS.FALSE, -}; -export const ThirdDay = Template.bind({}); -ThirdDay.args = { - currentDay: CARD_DAYS.DAY3, - firstCardType: CARD_TYPE.FIRST_CARD, - secondCardType: CARD_TYPE.SECOND_CARD, - cardStatus: CARD_SELECTED_STATUS.FALSE, -}; -export const FourthDay = Template.bind({}); -FourthDay.args = { - currentDay: CARD_DAYS.DAY4, - firstCardType: CARD_TYPE.FIRST_CARD, - secondCardType: CARD_TYPE.SECOND_CARD, - cardStatus: CARD_SELECTED_STATUS.FALSE, -}; -export const FifthDay = Template.bind({}); -FifthDay.args = { - currentDay: CARD_DAYS.DAY5, - firstCardType: CARD_TYPE.FIRST_CARD, - secondCardType: CARD_TYPE.SECOND_CARD, - cardStatus: CARD_SELECTED_STATUS.FALSE, -}; -export const SixthDay = Template.bind({}); -SixthDay.args = { - currentDay: CARD_DAYS.DAY6, - firstCardType: CARD_TYPE.FIRST_CARD, - secondCardType: CARD_TYPE.SECOND_CARD, - cardStatus: CARD_SELECTED_STATUS.FALSE, -}; +// import { Meta, StoryFn } from "@storybook/react"; +// import RushCardComparison from "@/components/RushCardComparison"; +// import { CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; +// +// export default { +// title: "Components/RushCardComparison", +// component: RushCardComparison, +// argTypes: { +// currentDay: { +// control: { type: "select" }, +// options: Object.values(CARD_DAYS), +// description: "The current day for selecting the card colors and titles", +// table: { +// type: { summary: "CARD_DAYS" }, +// defaultValue: { summary: CARD_DAYS.DAY1 }, +// }, +// }, +// firstCardType: { +// control: { type: "select" }, +// options: Object.values(CARD_TYPE), +// description: "The type of the first card", +// table: { +// type: { summary: "CARD_TYPE" }, +// defaultValue: { summary: CARD_TYPE.FIRST_CARD }, +// }, +// }, +// secondCardType: { +// control: { type: "select" }, +// options: Object.values(CARD_TYPE), +// description: "The type of the second card", +// table: { +// type: { summary: "CARD_TYPE" }, +// defaultValue: { summary: CARD_TYPE.SECOND_CARD }, +// }, +// }, +// cardStatus: { +// control: { type: "select" }, +// options: Object.values(CARD_SELECTED_STATUS), +// description: "The selection status of the card", +// table: { +// type: { summary: "CARD_SELECTED_STATUS" }, +// defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, +// }, +// }, +// }, +// } as Meta; +// +// const Template: StoryFn = (args) => ; +// +// export const FirstDay = Template.bind({}); +// FirstDay.args = { +// currentDay: CARD_DAYS.DAY1, +// firstCardType: CARD_TYPE.FIRST_CARD, +// secondCardType: CARD_TYPE.SECOND_CARD, +// cardStatus: CARD_SELECTED_STATUS.FALSE, +// }; +// export const SecondDay = Template.bind({}); +// SecondDay.args = { +// currentDay: CARD_DAYS.DAY2, +// firstCardType: CARD_TYPE.FIRST_CARD, +// secondCardType: CARD_TYPE.SECOND_CARD, +// cardStatus: CARD_SELECTED_STATUS.FALSE, +// }; +// export const ThirdDay = Template.bind({}); +// ThirdDay.args = { +// currentDay: CARD_DAYS.DAY3, +// firstCardType: CARD_TYPE.FIRST_CARD, +// secondCardType: CARD_TYPE.SECOND_CARD, +// cardStatus: CARD_SELECTED_STATUS.FALSE, +// }; +// export const FourthDay = Template.bind({}); +// FourthDay.args = { +// currentDay: CARD_DAYS.DAY4, +// firstCardType: CARD_TYPE.FIRST_CARD, +// secondCardType: CARD_TYPE.SECOND_CARD, +// cardStatus: CARD_SELECTED_STATUS.FALSE, +// }; +// export const FifthDay = Template.bind({}); +// FifthDay.args = { +// currentDay: CARD_DAYS.DAY5, +// firstCardType: CARD_TYPE.FIRST_CARD, +// secondCardType: CARD_TYPE.SECOND_CARD, +// cardStatus: CARD_SELECTED_STATUS.FALSE, +// }; +// export const SixthDay = Template.bind({}); +// SixthDay.args = { +// currentDay: CARD_DAYS.DAY6, +// firstCardType: CARD_TYPE.FIRST_CARD, +// secondCardType: CARD_TYPE.SECOND_CARD, +// cardStatus: CARD_SELECTED_STATUS.FALSE, +// }; +export default {}; diff --git a/client/src/components/RushCardDescription/index.stories.tsx b/client/src/components/RushCardDescription/index.stories.tsx index 7f5c11d1..f28b9035 100644 --- a/client/src/components/RushCardDescription/index.stories.tsx +++ b/client/src/components/RushCardDescription/index.stories.tsx @@ -1,56 +1,57 @@ -import { Meta, StoryFn } from "@storybook/react"; -import RushCardDescription from "@/components/RushCardDescription"; -import { CARD_COLOR, CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; - -export default { - title: "Components/RushCardDescription", - component: RushCardDescription, - argTypes: { - color: { - control: { type: "select" }, - options: Object.values(CARD_COLOR), - description: "The background color of the card", - table: { - type: { summary: "CARD_COLOR" }, - defaultValue: { summary: CARD_COLOR.GREEN }, - }, - }, - day: { - control: { type: "select" }, - options: Object.values(CARD_DAYS), - description: "The current day for selecting the card details", - table: { - type: { summary: "CARD_DAYS" }, - defaultValue: { summary: CARD_DAYS.DAY1 }, - }, - }, - cardType: { - control: { type: "select" }, - options: Object.values(CARD_TYPE), - description: "두 개의 카드 중 하나", - table: { - type: { summary: "CARD_TYPE" }, - defaultValue: { summary: CARD_TYPE.FIRST_CARD }, - }, - }, - cardStatus: { - control: { type: "select" }, - options: Object.values(CARD_SELECTED_STATUS), - description: "The selection status of the card", - table: { - type: { summary: "CARD_SELECTED_STATUS" }, - defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, - }, - }, - }, -} as Meta; - -const Template: StoryFn = (args) => ; - -export const Default = Template.bind({}); -Default.args = { - color: CARD_COLOR.GREEN, - day: CARD_DAYS.DAY5, - cardType: CARD_TYPE.FIRST_CARD, - cardStatus: CARD_SELECTED_STATUS.TRUE, -}; +// import { Meta, StoryFn } from "@storybook/react"; +// import RushCardDescription from "@/components/RushCardDescription"; +// import { CARD_COLOR, CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; +// +// export default { +// title: "Components/RushCardDescription", +// component: RushCardDescription, +// argTypes: { +// color: { +// control: { type: "select" }, +// options: Object.values(CARD_COLOR), +// description: "The background color of the card", +// table: { +// type: { summary: "CARD_COLOR" }, +// defaultValue: { summary: CARD_COLOR.GREEN }, +// }, +// }, +// day: { +// control: { type: "select" }, +// options: Object.values(CARD_DAYS), +// description: "The current day for selecting the card details", +// table: { +// type: { summary: "CARD_DAYS" }, +// defaultValue: { summary: CARD_DAYS.DAY1 }, +// }, +// }, +// cardType: { +// control: { type: "select" }, +// options: Object.values(CARD_TYPE), +// description: "두 개의 카드 중 하나", +// table: { +// type: { summary: "CARD_TYPE" }, +// defaultValue: { summary: CARD_TYPE.FIRST_CARD }, +// }, +// }, +// cardStatus: { +// control: { type: "select" }, +// options: Object.values(CARD_SELECTED_STATUS), +// description: "The selection status of the card", +// table: { +// type: { summary: "CARD_SELECTED_STATUS" }, +// defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, +// }, +// }, +// }, +// } as Meta; +// +// const Template: StoryFn = (args) => ; +// +// export const Default = Template.bind({}); +// Default.args = { +// color: CARD_COLOR.GREEN, +// day: CARD_DAYS.DAY5, +// cardType: CARD_TYPE.FIRST_CARD, +// cardStatus: CARD_SELECTED_STATUS.TRUE, +// }; +export default {}; From 285744beebe4253c74c15aa64597fcb36d56da99 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 17:22:05 +0900 Subject: [PATCH 039/111] =?UTF-8?q?chore:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=20API=20=EB=AF=B8=EC=97=B0=EB=8F=99=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/BalanceGame.tsx | 55 ++++++++++--------- .../features/Rush/BalanceGame/CardOptions.tsx | 2 +- .../Rush/BalanceGame/SelectedCard.tsx | 2 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index daddca6c..8d4f2371 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -15,36 +15,37 @@ import useCountDown from "@/hooks/useCountDown.ts"; import { SectionKeyProps } from "@/types/sections.ts"; export function BalanceGame({ id }: SectionKeyProps) { - const [cookies] = useCookies([COOKIE_TOKEN_KEY]); + // const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const { gameState, setGameState, updateUserParticipationStatus } = useBalanceGameContext(); - const [initialCountdown, setInitialCountdown] = useState(null); + // const [initialCountdown, setInitialCountdown] = useState(null); - useEffect(() => { - (async () => { - try { - const rushData = await RushAPI.getRush(); - const currentEvent = rushData.events.find( - (event) => event.rushEventId === rushData.todayEventId - ); - - if (rushData.serverDateTime && currentEvent?.startDateTime) { - const serverTime = new Date(rushData.serverDateTime).getTime(); - const startTime = new Date(currentEvent.startDateTime).getTime(); - const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); - setInitialCountdown(countdown); - } - - const userParticipated = await RushAPI.getRushUserParticipationStatus( - cookies[COOKIE_TOKEN_KEY] - ); - updateUserParticipationStatus(userParticipated); - } catch (error) { - console.error("Error:", error); - } - })(); - }, []); + // useEffect(() => { + // (async () => { + // try { + // const rushData = await RushAPI.getRush(); + // const currentEvent = rushData.events.find( + // (event) => event.rushEventId === rushData.todayEventId + // ); + // + // if (rushData.serverDateTime && currentEvent?.startDateTime) { + // const serverTime = new Date(rushData.serverDateTime).getTime(); + // const startTime = new Date(currentEvent.startDateTime).getTime(); + // const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); + // setInitialCountdown(countdown); + // } + // + // const userParticipated = await RushAPI.getRushUserParticipationStatus( + // cookies[COOKIE_TOKEN_KEY] + // ); + // updateUserParticipationStatus(userParticipated); + // } catch (error) { + // console.error("Error:", error); + // } + // })(); + // }, []); - const countdown = useCountDown(initialCountdown || 0); + // const countdown = useCountDown(initialCountdown || 0); + const countdown = useCountDown(20); useEffect(() => { if (countdown === 0 && gameState.phase === "PRE_EVENT") { diff --git a/client/src/features/Rush/BalanceGame/CardOptions.tsx b/client/src/features/Rush/BalanceGame/CardOptions.tsx index b6250235..689930e2 100644 --- a/client/src/features/Rush/BalanceGame/CardOptions.tsx +++ b/client/src/features/Rush/BalanceGame/CardOptions.tsx @@ -1,3 +1,3 @@ export default function CardOptions() { - return <>; + return
test
; } diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/SelectedCard.tsx index e90314a4..8c83e3c3 100644 --- a/client/src/features/Rush/BalanceGame/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGame/SelectedCard.tsx @@ -1,3 +1,3 @@ export default function SelectedCard() { - return <>; + return
; } From b21ba80a4fcab4005c090f5a69af12cd83fb9929 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 18:32:41 +0900 Subject: [PATCH 040/111] =?UTF-8?q?feat:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=83=81=EC=88=98=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.ts | 178 ++++++++++++++ client/src/constants/Rush/rushCard.tsx | 291 ----------------------- client/src/features/Rush/BalanceGame.tsx | 2 +- 3 files changed, 179 insertions(+), 292 deletions(-) create mode 100644 client/src/constants/Rush/rushCard.ts delete mode 100644 client/src/constants/Rush/rushCard.tsx diff --git a/client/src/constants/Rush/rushCard.ts b/client/src/constants/Rush/rushCard.ts new file mode 100644 index 00000000..5b040b12 --- /dev/null +++ b/client/src/constants/Rush/rushCard.ts @@ -0,0 +1,178 @@ +export const CARD_TYPE = { + LEFT_OPTIONS: "LEFT_OPTIONS", + RIGHT_OPTIONS: "RIGHT_OPTIONS", +} as const; + +export const CARD_COLOR = { + BLUE: "blue", + RED: "red", + YELLOW: "yellow", + GREEN: "green", +} as const; + +export const CARD_DAYS = { + DAY1: 1, + DAY2: 2, + DAY3: 3, + DAY4: 4, + DAY5: 5, + DAY6: 6, +} as const; + +export const CARD_COLORS: { + [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { + LEFT_OPTIONS: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + RIGHT_OPTIONS: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + }; +} = { + [CARD_DAYS.DAY1]: { LEFT_OPTIONS: CARD_COLOR.GREEN, RIGHT_OPTIONS: CARD_COLOR.BLUE }, + [CARD_DAYS.DAY2]: { LEFT_OPTIONS: CARD_COLOR.YELLOW, RIGHT_OPTIONS: CARD_COLOR.RED }, + [CARD_DAYS.DAY3]: { LEFT_OPTIONS: CARD_COLOR.BLUE, RIGHT_OPTIONS: CARD_COLOR.RED }, + [CARD_DAYS.DAY4]: { LEFT_OPTIONS: CARD_COLOR.GREEN, RIGHT_OPTIONS: CARD_COLOR.YELLOW }, + [CARD_DAYS.DAY5]: { LEFT_OPTIONS: CARD_COLOR.GREEN, RIGHT_OPTIONS: CARD_COLOR.RED }, + [CARD_DAYS.DAY6]: { LEFT_OPTIONS: CARD_COLOR.BLUE, RIGHT_OPTIONS: CARD_COLOR.YELLOW }, +}; + +export const CARD_OPTIONS: { + [key: number]: { + LEFT_OPTIONS: { title: string; description: string }; + RIGHT_OPTIONS: { title: string; description: string }; + }; +} = { + [CARD_DAYS.DAY1]: { + LEFT_OPTIONS: { + title: "첫 차는 저렴해야 한다", + description: "가성비 좋게 저렴한 차로 시작해서 차근히 업그레이드하고 싶어", + }, + RIGHT_OPTIONS: { + title: "첫 차는 안전해야 한다", + description: "처음 사는 차인 만큼 안전한 차를 사서 오래 타고 싶어", + }, + }, + [CARD_DAYS.DAY2]: { + LEFT_OPTIONS: { + title: "온라인 쇼핑이 편해서 좋다", + description: "편한 게 최고야! 집에서 인터넷으로 쇼핑할래", + }, + RIGHT_OPTIONS: { + title: "오프라인 쇼핑이 확실해서 좋다", + description: "살 거면 제대로 보고 사야지! 직접 보고 나서 판단할래", + }, + }, + [CARD_DAYS.DAY3]: { + LEFT_OPTIONS: { + title: "텐트 치고 캠핑하기", + description: "캠핑은 텐트가 근본이지!", + }, + RIGHT_OPTIONS: { + title: "차 안에서 차박하기", + description: "가벼운 짐으로 차에서 잠드는 낭만이 좋아", + }, + }, + [CARD_DAYS.DAY4]: { + LEFT_OPTIONS: { + title: "평생 주차 무료로 하기", + description: "요즘 주차장은 너무 비싸 주차비 걱정은 그만 하고 싶어", + }, + RIGHT_OPTIONS: { + title: "평생 주유 무료로 하기", + description: "기름값이 너무 많이 올랐어 주유비가 많이 들어 고민이야", + }, + }, + [CARD_DAYS.DAY5]: { + LEFT_OPTIONS: { + title: "무채색 차가 좋다", + description: "검은색, 흰색, 회색! 오래 타려면 무난한 게 최고야", + }, + RIGHT_OPTIONS: { + title: "컬러풀한 차가 좋다", + description: "무채색은 지루해! 내가 좋아하는 색으로 고를래", + }, + }, + [CARD_DAYS.DAY6]: { + LEFT_OPTIONS: { + title: "주말에는 바다보러 가기", + description: "아까운 주말엔 국내여행이라도 다녀오고 싶어", + }, + RIGHT_OPTIONS: { + title: "주말에는 도심 드라이브", + description: "평일에 너무 피곤했으니 오랜만에 동네 드라이브나 할래", + }, + }, +}; + +export const CARD_RESULTS: { + [key: number]: { + LEFT_OPTIONS: { result_title: string; result_description: string }; + RIGHT_OPTIONS: { result_title: string; result_description: string }; + }; +} = { + [CARD_DAYS.DAY1]: { + LEFT_OPTIONS: { + result_title: "가성비 좋은 도심형 전기차", + result_description: + "캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 첫 차로 캐스퍼 일렉트릭 어떤가요?", + }, + RIGHT_OPTIONS: { + result_title: "가성비 좋은 도심형 전기차", + result_description: + "캐스퍼는 작고 귀엽기만 하다고 생각했나요? 이젠 현대 스마트센스 안전옵션까지 지원해요", + }, + }, + [CARD_DAYS.DAY2]: { + LEFT_OPTIONS: { + result_title: "현대 유일 온라인 예약", + result_description: + "차 살때도 온라인 쇼핑을! 오직 온라인에서만 구매할 수 있는 캐스퍼 일렉트릭", + }, + RIGHT_OPTIONS: { + result_title: "캐스퍼 스튜디오 송파", + result_description: + "캐스퍼 일렉트릭을 원하는 시간에 직접 만나볼 수 있는 무인 전시 스튜디오", + }, + }, + [CARD_DAYS.DAY3]: { + LEFT_OPTIONS: { + result_title: "V2L로 캠핑 준비 끝", + result_description: + "캠핑장 전기 눈치싸움은 이제 그만! 차에서 직접 220V 전원을 연결할 수 있어요", + }, + RIGHT_OPTIONS: { + result_title: "폴 폴딩으로 공간 활용", + result_description: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", + }, + }, + [CARD_DAYS.DAY4]: { + LEFT_OPTIONS: { + result_title: "전기차는 주차비 혜택 받아요", + result_description: "공영주차장 50% 할인 정책으로 주차비 부담을 덜 수 있어요", + }, + RIGHT_OPTIONS: { + result_title: "전기차는 기름값 걱정 없어요", + result_description: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", + }, + }, + [CARD_DAYS.DAY5]: { + LEFT_OPTIONS: { + result_title: "기본 색감도 다채롭게", + result_description: "무채색 컬러도 매트부터 메탈릭까지 다양한 질감으로 구성했어요", + }, + RIGHT_OPTIONS: { + result_title: "신규 색상 5종 출시", + result_description: + "기존 캐스퍼 색상 라인업에 새로운 5종을 추가! 내 차의 개성을 뽐내봐요", + }, + }, + [CARD_DAYS.DAY6]: { + LEFT_OPTIONS: { + result_title: "충전 한 번에 315km", + result_description: + "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", + }, + RIGHT_OPTIONS: { + result_title: "충전 한 번에 315km", + result_description: + "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", + }, + }, +}; diff --git a/client/src/constants/Rush/rushCard.tsx b/client/src/constants/Rush/rushCard.tsx deleted file mode 100644 index b68490ce..00000000 --- a/client/src/constants/Rush/rushCard.tsx +++ /dev/null @@ -1,291 +0,0 @@ -import { ReactNode } from "react"; - -export const CARD_TYPE = { - FIRST_CARD: "FIRST_CARD", - SECOND_CARD: "SECOND_CARD", -} as const; - -export const CARD_COLOR = { - BLUE: "blue", - RED: "red", - YELLOW: "yellow", - GREEN: "green", -} as const; - -export const CARD_SELECTED_STATUS = { - TRUE: "true", - FALSE: "false", -} as const; - -export const CARD_DAYS = { - DAY1: 1, - DAY2: 2, - DAY3: 3, - DAY4: 4, - DAY5: 5, - DAY6: 6, -} as const; - -// TODO: 추후 API 연동 / 색상은 클라이언트 측에서 픽스 -export const CARD_COLORS: { - [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { - FIRST_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; - SECOND_CARD: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; - }; -} = { - [CARD_DAYS.DAY1]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.BLUE }, - [CARD_DAYS.DAY2]: { FIRST_CARD: CARD_COLOR.YELLOW, SECOND_CARD: CARD_COLOR.RED }, - [CARD_DAYS.DAY3]: { FIRST_CARD: CARD_COLOR.BLUE, SECOND_CARD: CARD_COLOR.RED }, - [CARD_DAYS.DAY4]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.YELLOW }, - [CARD_DAYS.DAY5]: { FIRST_CARD: CARD_COLOR.GREEN, SECOND_CARD: CARD_COLOR.RED }, - [CARD_DAYS.DAY6]: { FIRST_CARD: CARD_COLOR.BLUE, SECOND_CARD: CARD_COLOR.YELLOW }, -}; - -export const CARD_TITLES: { [key: number]: { FIRST_CARD: string; SECOND_CARD: string } } = { - [CARD_DAYS.DAY1]: { FIRST_CARD: "첫 차는 저렴해야 한다", SECOND_CARD: "첫 차는 안전해야 한다" }, - [CARD_DAYS.DAY2]: { - FIRST_CARD: "온라인 쇼핑이 편해서 좋다", - SECOND_CARD: "오프라인 쇼핑이 확실해서 좋다", - }, - [CARD_DAYS.DAY3]: { FIRST_CARD: "텐트 치고 캠핑하기", SECOND_CARD: "차 안에서 차박하기" }, - [CARD_DAYS.DAY4]: { FIRST_CARD: "평생 주차 무료로 하기", SECOND_CARD: "평생 주유 무료로 하기" }, - [CARD_DAYS.DAY5]: { FIRST_CARD: "무채색 차가 좋다", SECOND_CARD: "컬러풀한 차가 좋다" }, - [CARD_DAYS.DAY6]: { - FIRST_CARD: "주말에는 바다보러 가기", - SECOND_CARD: "주말에는 도심 드라이브", - }, -}; - -export const CARD_DESCRIPTION: { - [key: number]: { - FIRST_CARD: { - [status in (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS]]: ReactNode[]; - }; - SECOND_CARD: { - [status in (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS]]: ReactNode[]; - }; - }; -} = { - [CARD_DAYS.DAY1]: { - FIRST_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <> - 가성비 좋은 -
- 도심형 전기차 - , - <> - 캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 -
첫 차로 캐스퍼 일렉트릭 어떤가요? - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 가성비 좋게 저렴한 차로 시작해서 -
- 차근히 업그레이드하고 싶어 - , - ], - }, - SECOND_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <> - 가성비 좋은 -
- 도심형 전기차 - , - <> - 캐스퍼는 작고 귀엽기만 하다고 생각했나요? -
- 이젠 현대 스마트센스 안전옵션까지 지원해요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 처음 사는 차인 만큼 -
- 안전한 차를 사서 오래 타고 싶어 - , - ], - }, - }, - [CARD_DAYS.DAY2]: { - FIRST_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>현대 유일 온라인 예약, - <> - 차 살때도 온라인 쇼핑을! -
- 오직 온라인에서만 구매할 수 있는 캐스퍼 일렉트릭 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 편한 게 최고야! -
- 집에서 인터넷으로 쇼핑할래 - , - ], - }, - SECOND_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>캐스퍼 스튜디오 송파, - <> - 캐스퍼 일렉트릭을 원하는 시간에 -
- 직접 만나볼 수 있는 무인 전시 스튜디오 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 살 거면 제대로 보고 사야지! -
- 직접 보고 나서 판단할래 - , - ], - }, - }, - [CARD_DAYS.DAY3]: { - FIRST_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>V2L로 캠핑 준비 끝, - <> - 캠핑장 전기 눈치싸움은 이제 그만! -
- 차에서 직접 220V 전원을 연결할 수 있어요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [<>캠핑은 텐트가 근본이지!], - }, - SECOND_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>폴 폴딩으로 공간 활용, - <> - 모든 시트가 완전히 접혀서 -
- 나만의 작은 방으로 만들 수 있어요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 가벼운 짐으로 -
- 차에서 잠드는 낭만이 좋아 - , - ], - }, - }, - [CARD_DAYS.DAY4]: { - FIRST_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <> - 전기차는 -
- 주차비 혜택 받아요 - , - <> - 공영주차장 50% 할인 정책으로 -
- 주차비 부담을 덜 수 있어요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 요즘 주차장은 너무 비싸 -
- 주차비 걱정은 그만 하고 싶어 - , - ], - }, - SECOND_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <> - 전기차는 -
- 기름값 걱정 없어요 - , - <> - 모든 시트가 완전히 접혀서 -
- 나만의 작은 방으로 만들 수 있어요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 기름값이 너무 많이 올랐어 -
- 주유비가 많이 들어 고민이야 - , - ], - }, - }, - [CARD_DAYS.DAY5]: { - FIRST_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>기본 색감도 다채롭게, - <> - 무채색 컬러도 매트부터 메탈릭까지 -
- 다양한 질감으로 구성했어요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 검은색, 흰색, 회색! -
- 오래 타려면 무난한 게 최고야 - , - ], - }, - SECOND_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>신규 색상 5종 출시, - <> - 기존 캐스퍼 색상 라인업에 새로운 5종을 추가! -
내 차의 개성을 뽐내봐요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 무채색은 지루해! -
- 내가 좋아하는 색으로 고를래 - , - ], - }, - }, - [CARD_DAYS.DAY6]: { - FIRST_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>충전 한 번에 315km, - <> - 엔트리급 전기차의 주행거리 혁신 -
한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 아까운 주말엔 -
- 국내여행이라도 다녀오고 싶어 - , - ], - }, - SECOND_CARD: { - [CARD_SELECTED_STATUS.TRUE]: [ - <>충전 한 번에 315km, - <> - 엔트리급 전기차의 주행거리 혁신 -
한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요 - , - ], - [CARD_SELECTED_STATUS.FALSE]: [ - <> - 평일에 너무 피곤했으니 -
- 오랜만에 동네 드라이브나 할래 - , - ], - }, - }, -}; diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index 8d4f2371..e7e0d662 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -45,7 +45,7 @@ export function BalanceGame({ id }: SectionKeyProps) { // }, []); // const countdown = useCountDown(initialCountdown || 0); - const countdown = useCountDown(20); + const countdown = useCountDown(5); useEffect(() => { if (countdown === 0 && gameState.phase === "PRE_EVENT") { From 51089330e822315be213ee66db20e68af800401d Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 18:41:35 +0900 Subject: [PATCH 041/111] =?UTF-8?q?refactor:=20Rush=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=20=EB=B3=80=EA=B2=BD=EB=90=9C=20mock=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index.stories.tsx | 0 .../index.tsx | 22 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) rename client/src/components/{RushCardDescription => RushCardResultDescription}/index.stories.tsx (100%) rename client/src/components/{RushCardDescription => RushCardResultDescription}/index.tsx (77%) diff --git a/client/src/components/RushCardDescription/index.stories.tsx b/client/src/components/RushCardResultDescription/index.stories.tsx similarity index 100% rename from client/src/components/RushCardDescription/index.stories.tsx rename to client/src/components/RushCardResultDescription/index.stories.tsx diff --git a/client/src/components/RushCardDescription/index.tsx b/client/src/components/RushCardResultDescription/index.tsx similarity index 77% rename from client/src/components/RushCardDescription/index.tsx rename to client/src/components/RushCardResultDescription/index.tsx index b5fb8eb1..4f149f50 100644 --- a/client/src/components/RushCardDescription/index.tsx +++ b/client/src/components/RushCardResultDescription/index.tsx @@ -3,17 +3,15 @@ import Category from "@/components/Category"; import { CARD_COLOR, CARD_DAYS, - CARD_DESCRIPTION, - CARD_SELECTED_STATUS, - CARD_TITLES, + CARD_OPTIONS, + CARD_RESULTS, CARD_TYPE, -} from "@/constants/Rush/rushCard.tsx"; +} from "@/constants/Rush/rushCard"; interface RushCardDescriptionProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; day: (typeof CARD_DAYS)[keyof typeof CARD_DAYS]; cardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE]; - cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS]; } const backgroundGradients = cva( @@ -30,20 +28,20 @@ const backgroundGradients = cva( } ); -export default function RushCardDescription({ +export default function RushCardResultDescription({ color, day, cardType, - cardStatus, }: RushCardDescriptionProps) { - const title = CARD_TITLES[day][cardType]; - const [descriptionTitle, descriptionText] = CARD_DESCRIPTION[day][cardType][cardStatus]; + const mainTitle = CARD_OPTIONS[day][cardType].title; + const title = CARD_RESULTS[day][cardType].result_title; + const description = CARD_RESULTS[day][cardType].result_description; return (
당신의 선택 -

{title}

+

{mainTitle}

지금

63%

@@ -52,8 +50,8 @@ export default function RushCardDescription({

CASPER Electric

-

{descriptionTitle}

-

{descriptionText}

+

{title}

+

{description}

); From 1583b2ecb93d5049a69031aa4f1542a7e2bc5cef Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sat, 10 Aug 2024 18:46:03 +0900 Subject: [PATCH 042/111] =?UTF-8?q?refactor:=20RushCard,=20RushCardCompari?= =?UTF-8?q?son=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EB=90=9C=20mock=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCard/index.tsx | 2 +- .../components/RushCardComparison/index.tsx | 37 +++++++------------ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/client/src/components/RushCard/index.tsx b/client/src/components/RushCard/index.tsx index 93b4b445..3c168a3c 100644 --- a/client/src/components/RushCard/index.tsx +++ b/client/src/components/RushCard/index.tsx @@ -1,5 +1,5 @@ import { cva } from "class-variance-authority"; -import { CARD_COLOR } from "@/constants/Rush/rushCard.tsx"; +import { CARD_COLOR } from "@/constants/Rush/rushCard"; interface RushCardProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; diff --git a/client/src/components/RushCardComparison/index.tsx b/client/src/components/RushCardComparison/index.tsx index 3d98dec9..c11221f8 100644 --- a/client/src/components/RushCardComparison/index.tsx +++ b/client/src/components/RushCardComparison/index.tsx @@ -1,43 +1,32 @@ import RushCard from "@/components/RushCard/index.tsx"; -import { - CARD_COLORS, - CARD_DAYS, - CARD_DESCRIPTION, - CARD_SELECTED_STATUS, - CARD_TITLES, - CARD_TYPE, -} from "@/constants/Rush/rushCard.tsx"; +import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard"; export default function RushCardComparison() { const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; - const firstCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.FIRST_CARD; - const secondCardType: (typeof CARD_TYPE)[keyof typeof CARD_TYPE] = CARD_TYPE.SECOND_CARD; - const cardStatus: (typeof CARD_SELECTED_STATUS)[keyof typeof CARD_SELECTED_STATUS] = - CARD_SELECTED_STATUS.FALSE; - const firstCardColor = CARD_COLORS[currentDay][firstCardType]; - const secondCardColor = CARD_COLORS[currentDay][secondCardType]; + const leftOptionColor = CARD_COLORS[currentDay][CARD_TYPE.LEFT_OPTIONS]; + const rightOptionColor = CARD_COLORS[currentDay][CARD_TYPE.RIGHT_OPTIONS]; - const firstCardTitle = CARD_TITLES[currentDay][firstCardType]; - const secondCardTitle = CARD_TITLES[currentDay][secondCardType]; + const leftOptionTitle = CARD_OPTIONS[currentDay][CARD_TYPE.LEFT_OPTIONS].title; + const rightOptionTitle = CARD_OPTIONS[currentDay][CARD_TYPE.RIGHT_OPTIONS].title; - const firstCardDescription = CARD_DESCRIPTION[currentDay][firstCardType][cardStatus]; - const secondCardDescription = CARD_DESCRIPTION[currentDay][secondCardType][cardStatus]; + const leftOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.LEFT_OPTIONS].description; + const rightOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.RIGHT_OPTIONS].description; return (

VS

); From 13632f1c7c02f7022a810935d034c19f3774a09e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 11:55:18 +0900 Subject: [PATCH 043/111] =?UTF-8?q?design:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4?= =?UTF-8?q?=20=EA=B2=8C=EC=9E=84=20=EC=B9=B4=EB=93=9C=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20width=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCard/index.tsx | 6 +++--- client/src/components/RushCardComparison/index.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/components/RushCard/index.tsx b/client/src/components/RushCard/index.tsx index 3c168a3c..32780233 100644 --- a/client/src/components/RushCard/index.tsx +++ b/client/src/components/RushCard/index.tsx @@ -8,7 +8,7 @@ interface RushCardProps { } const backgroundGradients = cva( - `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800`, + `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800 p-10 break-keep`, { variants: { color: { @@ -27,8 +27,8 @@ const backgroundGradients = cva( export default function RushCard({ color, title, description }: RushCardProps) { return (
-

{title}

-

{description}

+

{title}

+

{description}

); } diff --git a/client/src/components/RushCardComparison/index.tsx b/client/src/components/RushCardComparison/index.tsx index c11221f8..39d208a7 100644 --- a/client/src/components/RushCardComparison/index.tsx +++ b/client/src/components/RushCardComparison/index.tsx @@ -2,7 +2,7 @@ import RushCard from "@/components/RushCard/index.tsx"; import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard"; export default function RushCardComparison() { - const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; + const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; const leftOptionColor = CARD_COLORS[currentDay][CARD_TYPE.LEFT_OPTIONS]; const rightOptionColor = CARD_COLORS[currentDay][CARD_TYPE.RIGHT_OPTIONS]; From a641fa72bd1ff08b21bac5c43b7aaf304e042528 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 12:00:37 +0900 Subject: [PATCH 044/111] =?UTF-8?q?feat:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=B9=B4=EB=93=9C=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/Rush/BalanceGame/CardOptions.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/src/features/Rush/BalanceGame/CardOptions.tsx b/client/src/features/Rush/BalanceGame/CardOptions.tsx index 689930e2..8d09e926 100644 --- a/client/src/features/Rush/BalanceGame/CardOptions.tsx +++ b/client/src/features/Rush/BalanceGame/CardOptions.tsx @@ -1,3 +1,15 @@ +import { motion } from "framer-motion"; +import RushCardComparison from "@/components/RushCardComparison"; +import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; + export default function CardOptions() { - return
test
; + return ( + +

2개의 후보 중 하나를 선택해주세요

+ +
+ ); } From cd4e705192b840aadebbe8f8d823045be1bcf81a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 13:50:23 +0900 Subject: [PATCH 045/111] =?UTF-8?q?feat:=20=EB=B0=B8=EB=9F=B0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=84=A0=ED=83=9D=ED=95=9C=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20=EB=8B=A4=EC=9A=B4=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCountDown/index.tsx | 29 +++++++++++++++++ client/src/features/Rush/BalanceGame.tsx | 2 +- .../features/Rush/BalanceGame/CardOptions.tsx | 31 +++++++++++++++++-- .../Rush/BalanceGame/SelectedCard.tsx | 18 ++++++++++- 4 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 client/src/components/RushCountDown/index.tsx diff --git a/client/src/components/RushCountDown/index.tsx b/client/src/components/RushCountDown/index.tsx new file mode 100644 index 00000000..ade37715 --- /dev/null +++ b/client/src/components/RushCountDown/index.tsx @@ -0,0 +1,29 @@ +interface RushCountDownProps { + countdown: number; +} + +export default function RushCountDown({ countdown }: RushCountDownProps) { + const minutes = Math.floor((countdown % 3600) / 60); + const seconds = countdown % 60; + + const formatTime = (time: number) => time.toString().padStart(2, "0"); + + return ( +
+

+ 밸런스 게임 결과 공개까지 남은 시간 +

+
+ +

Minutes

+

{formatTime(minutes)}

+
+

:

+ +

Seconds

+

{formatTime(seconds)}

+
+
+
+ ); +} diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index e7e0d662..1dcd5f70 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -45,7 +45,7 @@ export function BalanceGame({ id }: SectionKeyProps) { // }, []); // const countdown = useCountDown(initialCountdown || 0); - const countdown = useCountDown(5); + const countdown = useCountDown(1); useEffect(() => { if (countdown === 0 && gameState.phase === "PRE_EVENT") { diff --git a/client/src/features/Rush/BalanceGame/CardOptions.tsx b/client/src/features/Rush/BalanceGame/CardOptions.tsx index 8d09e926..67608fe0 100644 --- a/client/src/features/Rush/BalanceGame/CardOptions.tsx +++ b/client/src/features/Rush/BalanceGame/CardOptions.tsx @@ -1,14 +1,39 @@ +import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import RushCardComparison from "@/components/RushCardComparison"; -import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import RushCountDown from "@/components/RushCountDown"; +import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; +import useCountDown from "@/hooks/useCountDown.ts"; export default function CardOptions() { + const countdown = useCountDown(50); + const [showCountdown, setShowCountdown] = useState(false); + + useEffect(() => { + const timer = setTimeout(() => { + setShowCountdown(true); + }, 5000); + + return () => clearTimeout(timer); + }, []); + return ( -

2개의 후보 중 하나를 선택해주세요

+ {!showCountdown ? ( + + 2개의 후보 중 하나를 선택해주세요 + + ) : ( + + + + )}
); diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/SelectedCard.tsx index 8c83e3c3..e01d9560 100644 --- a/client/src/features/Rush/BalanceGame/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGame/SelectedCard.tsx @@ -1,3 +1,19 @@ +import { motion } from "framer-motion"; +import RushCardResultDescription from "@/components/RushCardResultDescription"; +import RushCountDown from "@/components/RushCountDown"; +import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import useCountDown from "@/hooks/useCountDown.ts"; + export default function SelectedCard() { - return
; + const countdown = useCountDown(5); + + return ( + + + + + ); } From 224f565f60d825f2da8a977b7af6ebc958d46924 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 13:54:50 +0900 Subject: [PATCH 046/111] =?UTF-8?q?refactor:=20CountDown=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/Rush/BalanceGame/CountDown.tsx | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/client/src/features/Rush/BalanceGame/CountDown.tsx b/client/src/features/Rush/BalanceGame/CountDown.tsx index c26de210..13942bbc 100644 --- a/client/src/features/Rush/BalanceGame/CountDown.tsx +++ b/client/src/features/Rush/BalanceGame/CountDown.tsx @@ -6,40 +6,46 @@ interface CountDownProps { countdown: number; } -export default function CountDown({ countdown }: CountDownProps) { +function CountDownTimer({ countdown }: CountDownProps) { const hours = Math.floor(countdown / 3600); const minutes = Math.floor((countdown % 3600) / 60); const seconds = countdown % 60; const formatTime = (time: number) => time.toString().padStart(2, "0"); + return ( +
+

+ 밸런스 게임 주제 공개까지 남은 시간 +

+
+ +

:

+ +

:

+ +
+
+ ); +} + +function TimeDisplay({ label, value }: { label: string; value: string }) { + return ( + +

{label}

+

{value}

+
+ ); +} + +export default function CountDown({ countdown }: CountDownProps) { return ( <> 이제 곧 하단에 밸런스 게임 주제가 공개돼요! -
-

- 밸런스 게임 주제 공개까지 남은 시간 -

-
- -

Hours

-

{formatTime(hours)}

-
-

:

- -

Minutes

-

{formatTime(minutes)}

-
-

:

- -

Seconds

-

{formatTime(seconds)}

-
-
-
+
); From b5f599331f1279f3f8386fd51017d53ff1caddbf Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 13:56:21 +0900 Subject: [PATCH 047/111] =?UTF-8?q?refactor:=20RushCountDown=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCountDown/index.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/client/src/components/RushCountDown/index.tsx b/client/src/components/RushCountDown/index.tsx index ade37715..4051399d 100644 --- a/client/src/components/RushCountDown/index.tsx +++ b/client/src/components/RushCountDown/index.tsx @@ -2,6 +2,15 @@ interface RushCountDownProps { countdown: number; } +function TimeDisplay({ label, value }: { label: string; value: string }) { + return ( + +

{label}

+

{value}

+
+ ); +} + export default function RushCountDown({ countdown }: RushCountDownProps) { const minutes = Math.floor((countdown % 3600) / 60); const seconds = countdown % 60; @@ -14,15 +23,9 @@ export default function RushCountDown({ countdown }: RushCountDownProps) { 밸런스 게임 결과 공개까지 남은 시간

- -

Minutes

-

{formatTime(minutes)}

-
+

:

- -

Seconds

-

{formatTime(seconds)}

-
+
); From f2ecf821380fee8e9207aa346a282eda07fef771 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 14:15:10 +0900 Subject: [PATCH 048/111] =?UTF-8?q?feat:=20RushCard=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=20POST=20API=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EC=98=B5=EC=85=98=20=ED=83=80=EC=9E=85=20number?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCard/index.tsx | 7 +- .../components/RushCardComparison/index.tsx | 17 ++++ client/src/constants/Rush/rushCard.ts | 94 +++++++++++-------- 3 files changed, 77 insertions(+), 41 deletions(-) diff --git a/client/src/components/RushCard/index.tsx b/client/src/components/RushCard/index.tsx index 32780233..1cc259d8 100644 --- a/client/src/components/RushCard/index.tsx +++ b/client/src/components/RushCard/index.tsx @@ -5,10 +5,11 @@ interface RushCardProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; title: string; description: string; + onClick?: () => void; } const backgroundGradients = cva( - `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800 p-10 break-keep`, + `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800 p-10 break-keep cursor-pointer`, { variants: { color: { @@ -24,9 +25,9 @@ const backgroundGradients = cva( } ); -export default function RushCard({ color, title, description }: RushCardProps) { +export default function RushCard({ color, title, description, onClick }: RushCardProps) { return ( -
+

{title}

{description}

diff --git a/client/src/components/RushCardComparison/index.tsx b/client/src/components/RushCardComparison/index.tsx index 39d208a7..9827329d 100644 --- a/client/src/components/RushCardComparison/index.tsx +++ b/client/src/components/RushCardComparison/index.tsx @@ -1,7 +1,11 @@ +import { useCookies } from "react-cookie"; +import { RushAPI } from "@/apis/rushAPI.ts"; import RushCard from "@/components/RushCard/index.tsx"; +import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard"; export default function RushCardComparison() { + const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; const leftOptionColor = CARD_COLORS[currentDay][CARD_TYPE.LEFT_OPTIONS]; @@ -13,12 +17,24 @@ export default function RushCardComparison() { const leftOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.LEFT_OPTIONS].description; const rightOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.RIGHT_OPTIONS].description; + const handleCardSelection = async (optionId: number) => { + const token = cookies.token; + if (!token) return; + + try { + await RushAPI.postSelectedRushOptionApply(token, optionId); + } catch (error) { + console.error("Error: ", error); + } + }; + return (
handleCardSelection(CARD_TYPE.LEFT_OPTIONS)} />

VS @@ -27,6 +43,7 @@ export default function RushCardComparison() { color={rightOptionColor} title={rightOptionTitle} description={rightOptionDescription} + onClick={() => handleCardSelection(CARD_TYPE.RIGHT_OPTIONS)} />

); diff --git a/client/src/constants/Rush/rushCard.ts b/client/src/constants/Rush/rushCard.ts index 5b040b12..b1112b5a 100644 --- a/client/src/constants/Rush/rushCard.ts +++ b/client/src/constants/Rush/rushCard.ts @@ -1,6 +1,6 @@ export const CARD_TYPE = { - LEFT_OPTIONS: "LEFT_OPTIONS", - RIGHT_OPTIONS: "RIGHT_OPTIONS", + LEFT_OPTIONS: 1, + RIGHT_OPTIONS: 2, } as const; export const CARD_COLOR = { @@ -21,80 +21,98 @@ export const CARD_DAYS = { export const CARD_COLORS: { [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { - LEFT_OPTIONS: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; - RIGHT_OPTIONS: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + [CARD_TYPE.LEFT_OPTIONS]: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + [CARD_TYPE.RIGHT_OPTIONS]: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; }; } = { - [CARD_DAYS.DAY1]: { LEFT_OPTIONS: CARD_COLOR.GREEN, RIGHT_OPTIONS: CARD_COLOR.BLUE }, - [CARD_DAYS.DAY2]: { LEFT_OPTIONS: CARD_COLOR.YELLOW, RIGHT_OPTIONS: CARD_COLOR.RED }, - [CARD_DAYS.DAY3]: { LEFT_OPTIONS: CARD_COLOR.BLUE, RIGHT_OPTIONS: CARD_COLOR.RED }, - [CARD_DAYS.DAY4]: { LEFT_OPTIONS: CARD_COLOR.GREEN, RIGHT_OPTIONS: CARD_COLOR.YELLOW }, - [CARD_DAYS.DAY5]: { LEFT_OPTIONS: CARD_COLOR.GREEN, RIGHT_OPTIONS: CARD_COLOR.RED }, - [CARD_DAYS.DAY6]: { LEFT_OPTIONS: CARD_COLOR.BLUE, RIGHT_OPTIONS: CARD_COLOR.YELLOW }, + [CARD_DAYS.DAY1]: { + [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.GREEN, + [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.BLUE, + }, + [CARD_DAYS.DAY2]: { + [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.YELLOW, + [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.RED, + }, + [CARD_DAYS.DAY3]: { + [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.BLUE, + [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.RED, + }, + [CARD_DAYS.DAY4]: { + [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.GREEN, + [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, + }, + [CARD_DAYS.DAY5]: { + [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.GREEN, + [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.RED, + }, + [CARD_DAYS.DAY6]: { + [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.BLUE, + [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, + }, }; export const CARD_OPTIONS: { [key: number]: { - LEFT_OPTIONS: { title: string; description: string }; - RIGHT_OPTIONS: { title: string; description: string }; + [CARD_TYPE.LEFT_OPTIONS]: { title: string; description: string }; + [CARD_TYPE.RIGHT_OPTIONS]: { title: string; description: string }; }; } = { [CARD_DAYS.DAY1]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { title: "첫 차는 저렴해야 한다", description: "가성비 좋게 저렴한 차로 시작해서 차근히 업그레이드하고 싶어", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { title: "첫 차는 안전해야 한다", description: "처음 사는 차인 만큼 안전한 차를 사서 오래 타고 싶어", }, }, [CARD_DAYS.DAY2]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { title: "온라인 쇼핑이 편해서 좋다", description: "편한 게 최고야! 집에서 인터넷으로 쇼핑할래", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { title: "오프라인 쇼핑이 확실해서 좋다", description: "살 거면 제대로 보고 사야지! 직접 보고 나서 판단할래", }, }, [CARD_DAYS.DAY3]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { title: "텐트 치고 캠핑하기", description: "캠핑은 텐트가 근본이지!", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { title: "차 안에서 차박하기", description: "가벼운 짐으로 차에서 잠드는 낭만이 좋아", }, }, [CARD_DAYS.DAY4]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { title: "평생 주차 무료로 하기", description: "요즘 주차장은 너무 비싸 주차비 걱정은 그만 하고 싶어", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { title: "평생 주유 무료로 하기", description: "기름값이 너무 많이 올랐어 주유비가 많이 들어 고민이야", }, }, [CARD_DAYS.DAY5]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { title: "무채색 차가 좋다", description: "검은색, 흰색, 회색! 오래 타려면 무난한 게 최고야", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { title: "컬러풀한 차가 좋다", description: "무채색은 지루해! 내가 좋아하는 색으로 고를래", }, }, [CARD_DAYS.DAY6]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { title: "주말에는 바다보러 가기", description: "아까운 주말엔 국내여행이라도 다녀오고 싶어", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { title: "주말에는 도심 드라이브", description: "평일에 너무 피곤했으니 오랜만에 동네 드라이브나 할래", }, @@ -103,73 +121,73 @@ export const CARD_OPTIONS: { export const CARD_RESULTS: { [key: number]: { - LEFT_OPTIONS: { result_title: string; result_description: string }; - RIGHT_OPTIONS: { result_title: string; result_description: string }; + [CARD_TYPE.LEFT_OPTIONS]: { result_title: string; result_description: string }; + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: string; result_description: string }; }; } = { [CARD_DAYS.DAY1]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { result_title: "가성비 좋은 도심형 전기차", result_description: "캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 첫 차로 캐스퍼 일렉트릭 어떤가요?", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: "가성비 좋은 도심형 전기차", result_description: "캐스퍼는 작고 귀엽기만 하다고 생각했나요? 이젠 현대 스마트센스 안전옵션까지 지원해요", }, }, [CARD_DAYS.DAY2]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { result_title: "현대 유일 온라인 예약", result_description: "차 살때도 온라인 쇼핑을! 오직 온라인에서만 구매할 수 있는 캐스퍼 일렉트릭", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: "캐스퍼 스튜디오 송파", result_description: "캐스퍼 일렉트릭을 원하는 시간에 직접 만나볼 수 있는 무인 전시 스튜디오", }, }, [CARD_DAYS.DAY3]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { result_title: "V2L로 캠핑 준비 끝", result_description: "캠핑장 전기 눈치싸움은 이제 그만! 차에서 직접 220V 전원을 연결할 수 있어요", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: "폴 폴딩으로 공간 활용", result_description: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", }, }, [CARD_DAYS.DAY4]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { result_title: "전기차는 주차비 혜택 받아요", result_description: "공영주차장 50% 할인 정책으로 주차비 부담을 덜 수 있어요", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: "전기차는 기름값 걱정 없어요", result_description: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", }, }, [CARD_DAYS.DAY5]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { result_title: "기본 색감도 다채롭게", result_description: "무채색 컬러도 매트부터 메탈릭까지 다양한 질감으로 구성했어요", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: "신규 색상 5종 출시", result_description: "기존 캐스퍼 색상 라인업에 새로운 5종을 추가! 내 차의 개성을 뽐내봐요", }, }, [CARD_DAYS.DAY6]: { - LEFT_OPTIONS: { + [CARD_TYPE.LEFT_OPTIONS]: { result_title: "충전 한 번에 315km", result_description: "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", }, - RIGHT_OPTIONS: { + [CARD_TYPE.RIGHT_OPTIONS]: { result_title: "충전 한 번에 315km", result_description: "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", From f4a8428bc8ecbadacaf073638fe7161e653f1c71 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 14:25:49 +0900 Subject: [PATCH 049/111] =?UTF-8?q?chore:=20RushCardResultDescription=20Pr?= =?UTF-8?q?ops=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/BalanceGame/SelectedCard.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/SelectedCard.tsx index e01d9560..ead6c3ea 100644 --- a/client/src/features/Rush/BalanceGame/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGame/SelectedCard.tsx @@ -1,6 +1,7 @@ import { motion } from "framer-motion"; import RushCardResultDescription from "@/components/RushCardResultDescription"; import RushCountDown from "@/components/RushCountDown"; +import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import useCountDown from "@/hooks/useCountDown.ts"; @@ -13,7 +14,11 @@ export default function SelectedCard() { {...SCROLL_MOTION(ASCEND)} > - + ); } From a62eba0fddabf7d68dbb774ae8eb7b0729fada0f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 14:39:06 +0900 Subject: [PATCH 050/111] =?UTF-8?q?design:=20RushCardResultDescription,=20?= =?UTF-8?q?RushCard=20=EB=82=B4=EB=B6=80=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20w?= =?UTF-8?q?idth=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/RushCard/index.tsx | 2 +- .../src/components/RushCardResultDescription/index.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/components/RushCard/index.tsx b/client/src/components/RushCard/index.tsx index 1cc259d8..8a6f9c88 100644 --- a/client/src/components/RushCard/index.tsx +++ b/client/src/components/RushCard/index.tsx @@ -28,7 +28,7 @@ const backgroundGradients = cva( export default function RushCard({ color, title, description, onClick }: RushCardProps) { return (
-

{title}

+

{title}

{description}

); diff --git a/client/src/components/RushCardResultDescription/index.tsx b/client/src/components/RushCardResultDescription/index.tsx index 4f149f50..b05d2054 100644 --- a/client/src/components/RushCardResultDescription/index.tsx +++ b/client/src/components/RushCardResultDescription/index.tsx @@ -15,7 +15,7 @@ interface RushCardDescriptionProps { } const backgroundGradients = cva( - `flex gap-[35px] w-[834px] h-[400px] bg-gradient-green rounded-800 py-6 px-[37px] justify-between`, + `flex gap-[35px] w-[834px] h-[400px] bg-gradient-green rounded-800 py-6 px-[37px] justify-between break-keep`, { variants: { color: { @@ -41,7 +41,9 @@ export default function RushCardResultDescription({
당신의 선택 -

{mainTitle}

+

+ {mainTitle} +

지금

63%

@@ -50,8 +52,8 @@ export default function RushCardResultDescription({

CASPER Electric

-

{title}

-

{description}

+

{title}

+

{description}

); From cc1f69b653ae6193c2f2adbbcbe30a96c1138bab Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 17:27:12 +0900 Subject: [PATCH 051/111] =?UTF-8?q?rename:=20arrow=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/public/assets/icons/arrow-line-left.svg | 3 +++ .../public/assets/icons/{arrow.svg => arrow-line-right.svg} | 0 client/src/components/CTAButton/index.tsx | 4 ++-- client/src/features/CasperCustom/CasperCustomFinish.tsx | 4 ++-- client/src/features/Main/Lottery.tsx | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 client/public/assets/icons/arrow-line-left.svg rename client/public/assets/icons/{arrow.svg => arrow-line-right.svg} (100%) diff --git a/client/public/assets/icons/arrow-line-left.svg b/client/public/assets/icons/arrow-line-left.svg new file mode 100644 index 00000000..91c96fe1 --- /dev/null +++ b/client/public/assets/icons/arrow-line-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/assets/icons/arrow.svg b/client/public/assets/icons/arrow-line-right.svg similarity index 100% rename from client/public/assets/icons/arrow.svg rename to client/public/assets/icons/arrow-line-right.svg diff --git a/client/src/components/CTAButton/index.tsx b/client/src/components/CTAButton/index.tsx index f70e19e7..795b0666 100644 --- a/client/src/components/CTAButton/index.tsx +++ b/client/src/components/CTAButton/index.tsx @@ -1,7 +1,7 @@ import { VariantProps, cva } from "class-variance-authority"; import { Link } from "react-router-dom"; import "@/index.css"; -import ArrowIcon from "/public/assets/icons/arrow.svg?react"; +import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; import ShareIcon from "/public/assets/icons/share.svg?react"; const BUTTON_STATUS: Record = { @@ -60,7 +60,7 @@ export default function CTAButton({ const content = ( <> {label} - {hasArrowIcon && } + {hasArrowIcon && } {hasShareIcon && } ); diff --git a/client/src/features/CasperCustom/CasperCustomFinish.tsx b/client/src/features/CasperCustom/CasperCustomFinish.tsx index 5d7222a4..c94fa088 100644 --- a/client/src/features/CasperCustom/CasperCustomFinish.tsx +++ b/client/src/features/CasperCustom/CasperCustomFinish.tsx @@ -13,7 +13,7 @@ import { CASPER_ACTION } from "@/types/casperCustom"; import { saveDomImage } from "@/utils/saveDomImage"; import { Battery } from "./Battery"; import { MyCasperCardFront } from "./MyCasperCardFront"; -import ArrowIcon from "/public/assets/icons/arrow.svg?react"; +import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; interface CasperCustomFinishProps { handleResetStep: () => void; @@ -98,7 +98,7 @@ export function CasperCustomFinish({ handleResetStep }: CasperCustomFinishProps)

다른 사람들의 스마일 로봇 뱃지 보러가기

- + ); diff --git a/client/src/features/Main/Lottery.tsx b/client/src/features/Main/Lottery.tsx index c4c009e7..c91ee463 100644 --- a/client/src/features/Main/Lottery.tsx +++ b/client/src/features/Main/Lottery.tsx @@ -6,7 +6,7 @@ import { LOTTERY_EVENT_DATA } from "@/constants/Main/lotteryEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; -import ArrowIcon from "/public/assets/icons/arrow.svg?react"; +import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; export function Lottery({ id }: SectionKeyProps) { const [startDateTime, setStartDateTime] = useState(null); @@ -76,7 +76,7 @@ export function Lottery({ id }: SectionKeyProps) { className="flex w-[1200px] justify-end gap-1 h-body-1-regular text-n-neutral-500 hover:underline" >

다른 사람들의 스마일 로봇 뱃지 보러가기

- +
); From 72bd7a6579b7ba311656ebfbfd58d0afcf5be928 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 17:28:23 +0900 Subject: [PATCH 052/111] =?UTF-8?q?feat:=20SelectedCard=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Rush/BalanceGame/CurrentRatio.tsx | 3 - .../Rush/BalanceGame/SelectedCard.tsx | 65 +++++++++++++++++-- 2 files changed, 60 insertions(+), 8 deletions(-) delete mode 100644 client/src/features/Rush/BalanceGame/CurrentRatio.tsx diff --git a/client/src/features/Rush/BalanceGame/CurrentRatio.tsx b/client/src/features/Rush/BalanceGame/CurrentRatio.tsx deleted file mode 100644 index f3a06b3b..00000000 --- a/client/src/features/Rush/BalanceGame/CurrentRatio.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function CurrentRatio() { - return <>; -} diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/SelectedCard.tsx index ead6c3ea..95677612 100644 --- a/client/src/features/Rush/BalanceGame/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGame/SelectedCard.tsx @@ -1,24 +1,79 @@ +import { useState } from "react"; import { motion } from "framer-motion"; +import RushCardCurrentRatio from "@/components/RushCardCurrentRatio"; import RushCardResultDescription from "@/components/RushCardResultDescription"; import RushCountDown from "@/components/RushCountDown"; import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import useCountDown from "@/hooks/useCountDown.ts"; +import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; +import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; + +interface SelectedCardProps { + onClick: () => void; +} + +function SelectedCardDescription({ onClick }: SelectedCardProps) { + return ( +
+ +
+ +
+
+ ); +} + +function SelectedCardCurrentRatio({ onClick }: SelectedCardProps) { + return ( +
+
+ +
+ +
+ ); +} export default function SelectedCard() { + const [isDescriptionVisible, setIsDescriptionVisible] = useState(true); const countdown = useCountDown(5); + const handleChangeCardResult = () => { + setIsDescriptionVisible((prev) => !prev); + }; + return ( - + {isDescriptionVisible ? ( + + ) : ( + + )} ); } From df1545fe355f1449cd6110db9bbf9ca846801947 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 18:50:30 +0900 Subject: [PATCH 053/111] =?UTF-8?q?fix:=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=200=EC=B4=88=EA=B9=8C=EC=A7=80=20=EC=B9=B4?= =?UTF-8?q?=EC=9A=B4=ED=8A=B8=20=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/BalanceGame.tsx | 5 +++-- client/src/hooks/useCountDown.ts | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index 1dcd5f70..4b810175 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -48,7 +48,7 @@ export function BalanceGame({ id }: SectionKeyProps) { const countdown = useCountDown(1); useEffect(() => { - if (countdown === 0 && gameState.phase === "PRE_EVENT") { + if (countdown < 0 && gameState.phase === "PRE_EVENT") { setGameState((prev) => ({ ...prev, phase: "EVENT_RUNNING" })); } }, [countdown, gameState.phase, setGameState]); @@ -59,7 +59,8 @@ export function BalanceGame({ id }: SectionKeyProps) { return ; case "EVENT_RUNNING": if (!gameState.userParticipated) { - return ; + // return ; + return ; } else { return ; } diff --git a/client/src/hooks/useCountDown.ts b/client/src/hooks/useCountDown.ts index 50985cb2..c4cae111 100644 --- a/client/src/hooks/useCountDown.ts +++ b/client/src/hooks/useCountDown.ts @@ -4,11 +4,11 @@ export default function useCountDown(initialTime: number) { const [time, setTime] = useState(initialTime); useEffect(() => { - if (time <= 0) return; + if (time < 0) return; const timer = setInterval(() => { setTime((prevTime) => { - if (prevTime <= 0) { + if (prevTime < 0) { clearInterval(timer); return 0; } From 3b11af92c8253cf50ed2cf95de79ac10688cbccb Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 18:51:50 +0900 Subject: [PATCH 054/111] =?UTF-8?q?design:=20SelectedCard=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=9D=B8=ED=84=B0=EB=A0=89?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/Rush/BalanceGame/SelectedCard.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/SelectedCard.tsx index 95677612..e66790ed 100644 --- a/client/src/features/Rush/BalanceGame/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGame/SelectedCard.tsx @@ -4,7 +4,7 @@ import RushCardCurrentRatio from "@/components/RushCardCurrentRatio"; import RushCardResultDescription from "@/components/RushCardResultDescription"; import RushCountDown from "@/components/RushCountDown"; import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; -import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import useCountDown from "@/hooks/useCountDown.ts"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; @@ -15,13 +15,13 @@ interface SelectedCardProps { function SelectedCardDescription({ onClick }: SelectedCardProps) { return ( -
+ -
+
-
+
); } function SelectedCardCurrentRatio({ onClick }: SelectedCardProps) { return ( -
-
+ + +
- -
+ ); } From 16d04093153a31f7df7bba6821eb5174c64a3a0d Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 19:01:36 +0900 Subject: [PATCH 055/111] =?UTF-8?q?design:=20RushCardCurrentRatio=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/public/assets/icons/reload.svg | 5 ++ .../components/RushCardCurrentRatio/index.tsx | 52 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 client/public/assets/icons/reload.svg create mode 100644 client/src/components/RushCardCurrentRatio/index.tsx diff --git a/client/public/assets/icons/reload.svg b/client/public/assets/icons/reload.svg new file mode 100644 index 00000000..9efab965 --- /dev/null +++ b/client/public/assets/icons/reload.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/client/src/components/RushCardCurrentRatio/index.tsx b/client/src/components/RushCardCurrentRatio/index.tsx new file mode 100644 index 00000000..b9b45d39 --- /dev/null +++ b/client/src/components/RushCardCurrentRatio/index.tsx @@ -0,0 +1,52 @@ +import Category from "@/components/Category"; +import Tooltip from "@/components/Tooltip"; +import Reload from "/public/assets/icons/reload.svg?react"; + +const TOOLTIP_CONTENT = () => ( + <> + 새로고침을 눌러 +
+ 실시간으로 바뀌는 결과를 지켜보세요 + +); + +export default function RushCardCurrentRatio() { + return ( +
+ +

실시간 투표 결과

+

+ 이대로 가면 우리 편이 질 수도 있어요! +

+
+
+
+
+

첫 차로 성능 좋은 차

+ 우세해요! +
+
+

첫 차로 저렴한 차

+ 당신의 선택 +
+
+
+

65%

+

35%

+
+
+
+ + + +
+
+ ); +} From 220d8bfae0ef6e7869874200e044a5df333d728a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 19:10:35 +0900 Subject: [PATCH 056/111] =?UTF-8?q?feat:=20Tooltip=205=EC=B4=88=20?= =?UTF-8?q?=ED=9B=84=20=EC=82=AC=EB=9D=BC=EC=A7=80=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/RushCardCurrentRatio/index.tsx | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/client/src/components/RushCardCurrentRatio/index.tsx b/client/src/components/RushCardCurrentRatio/index.tsx index b9b45d39..14a0626b 100644 --- a/client/src/components/RushCardCurrentRatio/index.tsx +++ b/client/src/components/RushCardCurrentRatio/index.tsx @@ -1,3 +1,4 @@ +import { useEffect, useState } from "react"; import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; import Reload from "/public/assets/icons/reload.svg?react"; @@ -10,7 +11,30 @@ const TOOLTIP_CONTENT = () => ( ); +function ReloadButton() { + return ( + + ); +} + export default function RushCardCurrentRatio() { + const [showToggle, setShowToggle] = useState(true); + + useEffect(() => { + const timer = setTimeout(() => { + setShowToggle(false); + }, 5000); + + return () => clearTimeout(timer); + }, []); + return (
@@ -36,16 +60,13 @@ export default function RushCardCurrentRatio() {
- - - + {showToggle ? ( + + + + ) : ( + + )}
); From 6abe5f10792921a7d8aeec471a6dbde3ddb4da08 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 11 Aug 2024 23:58:58 +0900 Subject: [PATCH 057/111] =?UTF-8?q?feat:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EB=B9=84=EC=9C=A8=20API=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=84=A0=ED=83=9D=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=82=B4=EB=B6=80=20=EC=9A=94=EC=86=8C=20?= =?UTF-8?q?=EB=B6=84=EA=B8=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/RushCardComparison/index.tsx | 5 +- .../components/RushCardCurrentRatio/index.tsx | 73 +++++++++++++++---- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/client/src/components/RushCardComparison/index.tsx b/client/src/components/RushCardComparison/index.tsx index 9827329d..38d81358 100644 --- a/client/src/components/RushCardComparison/index.tsx +++ b/client/src/components/RushCardComparison/index.tsx @@ -18,11 +18,8 @@ export default function RushCardComparison() { const rightOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.RIGHT_OPTIONS].description; const handleCardSelection = async (optionId: number) => { - const token = cookies.token; - if (!token) return; - try { - await RushAPI.postSelectedRushOptionApply(token, optionId); + await RushAPI.postSelectedRushOptionApply(cookies[COOKIE_TOKEN_KEY], optionId); } catch (error) { console.error("Error: ", error); } diff --git a/client/src/components/RushCardCurrentRatio/index.tsx b/client/src/components/RushCardCurrentRatio/index.tsx index 14a0626b..9e9e216b 100644 --- a/client/src/components/RushCardCurrentRatio/index.tsx +++ b/client/src/components/RushCardCurrentRatio/index.tsx @@ -1,6 +1,9 @@ import { useEffect, useState } from "react"; +import { useCookies } from "react-cookie"; +import { RushAPI } from "@/apis/rushAPI.ts"; import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; +import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import Reload from "/public/assets/icons/reload.svg?react"; const TOOLTIP_CONTENT = () => ( @@ -11,21 +14,54 @@ const TOOLTIP_CONTENT = () => ( ); -function ReloadButton() { +const MESSAGES = { + WINNING: "이대로 가면 우리 편이 이겨요!", + LOSING: "이대로 가면 우리 편이 질 수도 있어요!", +}; + +function ReloadButton({ onClick }: { onClick: () => void }) { return ( - ); } export default function RushCardCurrentRatio() { + const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const [showToggle, setShowToggle] = useState(true); + const [leftOptionRatio, setLeftOptionRatio] = useState(0); + const [rightOptionRatio, setRightOptionRatio] = useState(0); + const [message, setMessage] = useState(MESSAGES.WINNING); + const [optionId, setOptionId] = useState(null); + + const fetchRushBalance = async () => { + try { + const rushBalanceData = await RushAPI.getRushBalance(cookies[COOKIE_TOKEN_KEY]); + const { optionId, leftOption, rightOption } = rushBalanceData; + + const total = leftOption + rightOption; + const leftRatio = Math.round((leftOption / total) * 100); + const rightRatio = Math.round((rightOption / total) * 100); + + setOptionId(optionId); + setLeftOptionRatio(leftRatio); + setRightOptionRatio(rightRatio); + + const selectedOptionCount = optionId === 1 ? leftOption : rightOption; + const opposingOptionCount = optionId === 1 ? rightOption : leftOption; + + setMessage( + selectedOptionCount > opposingOptionCount ? MESSAGES.WINNING : MESSAGES.LOSING + ); + } catch (error) { + console.error("Error: ", error); + } + }; + + useEffect(() => { + fetchRushBalance(); + }, []); useEffect(() => { const timer = setTimeout(() => { @@ -39,33 +75,38 @@ export default function RushCardCurrentRatio() {

실시간 투표 결과

-

- 이대로 가면 우리 편이 질 수도 있어요! -

+

{message}

첫 차로 성능 좋은 차

- 우세해요! + {leftOptionRatio > rightOptionRatio && ( + 우세해요! + )} + {optionId === 1 && 당신의 선택}

첫 차로 저렴한 차

- 당신의 선택 + {rightOptionRatio > leftOptionRatio && ( + 우세해요! + )} + {optionId === 2 && 당신의 선택}
+ {/* TODO: 비율대로 프로그래스바 움직이는 로직 구현 */}
-

65%

-

35%

+

{leftOptionRatio}%

+

{rightOptionRatio}%

{showToggle ? ( - + ) : ( - + )}
From c0eafebe559a005a0a84cd7b64bba06fcd5d0dff Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 00:04:32 +0900 Subject: [PATCH 058/111] =?UTF-8?q?refactor:=20Rush=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=ED=8C=8C=EC=9D=BC=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/RushCard/index.stories.tsx | 66 ------------- .../RushCardComparison/index.stories.tsx | 92 ------------------- .../index.stories.tsx | 57 ------------ client/src/features/Rush/BalanceGame.tsx | 8 +- .../Rush/BalanceGameCard/RushCard.tsx} | 2 +- .../BalanceGameCard/RushCardComparison.tsx} | 4 +- .../BalanceGameCard/RushCardCurrentRatio.tsx} | 0 .../RushCardResultDescription.tsx} | 2 +- .../Rush/BalanceGameCard/RushCountDown.tsx} | 0 .../CardOptions.tsx | 4 +- .../CountDown.tsx | 0 .../FinalResult.tsx | 0 .../SelectedCard.tsx | 6 +- 13 files changed, 13 insertions(+), 228 deletions(-) delete mode 100644 client/src/components/RushCard/index.stories.tsx delete mode 100644 client/src/components/RushCardComparison/index.stories.tsx delete mode 100644 client/src/components/RushCardResultDescription/index.stories.tsx rename client/src/{components/RushCard/index.tsx => features/Rush/BalanceGameCard/RushCard.tsx} (95%) rename client/src/{components/RushCardComparison/index.tsx => features/Rush/BalanceGameCard/RushCardComparison.tsx} (95%) rename client/src/{components/RushCardCurrentRatio/index.tsx => features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx} (100%) rename client/src/{components/RushCardResultDescription/index.tsx => features/Rush/BalanceGameCard/RushCardResultDescription.tsx} (98%) rename client/src/{components/RushCountDown/index.tsx => features/Rush/BalanceGameCard/RushCountDown.tsx} (100%) rename client/src/features/Rush/{BalanceGame => BalanceGameSection}/CardOptions.tsx (88%) rename client/src/features/Rush/{BalanceGame => BalanceGameSection}/CountDown.tsx (100%) rename client/src/features/Rush/{BalanceGame => BalanceGameSection}/FinalResult.tsx (100%) rename client/src/features/Rush/{BalanceGame => BalanceGameSection}/SelectedCard.tsx (91%) diff --git a/client/src/components/RushCard/index.stories.tsx b/client/src/components/RushCard/index.stories.tsx deleted file mode 100644 index 44b0d36a..00000000 --- a/client/src/components/RushCard/index.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -// import { Meta, StoryFn } from "@storybook/react"; -// import RushCard from "@/components/RushCard"; -// import { CARD_COLOR } from "@/constants/Rush/rushCard"; -// -// export default { -// title: "Components/RushCard", -// component: RushCard, -// argTypes: { -// color: { -// control: { type: "select" }, -// options: Object.values(CARD_COLOR), -// description: "The background gradient color of the card", -// table: { -// type: { summary: "CARD_COLOR" }, -// defaultValue: { summary: CARD_COLOR.GREEN }, -// }, -// }, -// title: { -// control: { type: "text" }, -// description: "The title displayed on the card", -// table: { -// type: { summary: "string" }, -// defaultValue: { summary: "Card Title" }, -// }, -// }, -// description: { -// control: { type: "array" }, -// description: "An array of descriptions displayed on the card", -// table: { -// type: { summary: "ReactNode[]" }, -// defaultValue: { summary: [] }, -// }, -// }, -// }, -// } as Meta; -// -// const Template: StoryFn = (args) => ; -// -// export const BlueCard = Template.bind({}); -// BlueCard.args = { -// color: CARD_COLOR.BLUE, -// title: "Blue Card", -// description: ["This is a blue card", "It has a gradient background"], -// }; -// -// export const RedCard = Template.bind({}); -// RedCard.args = { -// color: CARD_COLOR.RED, -// title: "Red Card", -// description: ["This is a red card", "It has a gradient background"], -// }; -// -// export const YellowCard = Template.bind({}); -// YellowCard.args = { -// color: CARD_COLOR.YELLOW, -// title: "Yellow Card", -// description: ["This is a yellow card", "It has a gradient background"], -// }; -// -// export const GreenCard = Template.bind({}); -// GreenCard.args = { -// color: CARD_COLOR.GREEN, -// title: "Green Card", -// description: ["This is a green card", "It has a gradient background"], -// }; -export default {}; diff --git a/client/src/components/RushCardComparison/index.stories.tsx b/client/src/components/RushCardComparison/index.stories.tsx deleted file mode 100644 index abf4be74..00000000 --- a/client/src/components/RushCardComparison/index.stories.tsx +++ /dev/null @@ -1,92 +0,0 @@ -// import { Meta, StoryFn } from "@storybook/react"; -// import RushCardComparison from "@/components/RushCardComparison"; -// import { CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; -// -// export default { -// title: "Components/RushCardComparison", -// component: RushCardComparison, -// argTypes: { -// currentDay: { -// control: { type: "select" }, -// options: Object.values(CARD_DAYS), -// description: "The current day for selecting the card colors and titles", -// table: { -// type: { summary: "CARD_DAYS" }, -// defaultValue: { summary: CARD_DAYS.DAY1 }, -// }, -// }, -// firstCardType: { -// control: { type: "select" }, -// options: Object.values(CARD_TYPE), -// description: "The type of the first card", -// table: { -// type: { summary: "CARD_TYPE" }, -// defaultValue: { summary: CARD_TYPE.FIRST_CARD }, -// }, -// }, -// secondCardType: { -// control: { type: "select" }, -// options: Object.values(CARD_TYPE), -// description: "The type of the second card", -// table: { -// type: { summary: "CARD_TYPE" }, -// defaultValue: { summary: CARD_TYPE.SECOND_CARD }, -// }, -// }, -// cardStatus: { -// control: { type: "select" }, -// options: Object.values(CARD_SELECTED_STATUS), -// description: "The selection status of the card", -// table: { -// type: { summary: "CARD_SELECTED_STATUS" }, -// defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, -// }, -// }, -// }, -// } as Meta; -// -// const Template: StoryFn = (args) => ; -// -// export const FirstDay = Template.bind({}); -// FirstDay.args = { -// currentDay: CARD_DAYS.DAY1, -// firstCardType: CARD_TYPE.FIRST_CARD, -// secondCardType: CARD_TYPE.SECOND_CARD, -// cardStatus: CARD_SELECTED_STATUS.FALSE, -// }; -// export const SecondDay = Template.bind({}); -// SecondDay.args = { -// currentDay: CARD_DAYS.DAY2, -// firstCardType: CARD_TYPE.FIRST_CARD, -// secondCardType: CARD_TYPE.SECOND_CARD, -// cardStatus: CARD_SELECTED_STATUS.FALSE, -// }; -// export const ThirdDay = Template.bind({}); -// ThirdDay.args = { -// currentDay: CARD_DAYS.DAY3, -// firstCardType: CARD_TYPE.FIRST_CARD, -// secondCardType: CARD_TYPE.SECOND_CARD, -// cardStatus: CARD_SELECTED_STATUS.FALSE, -// }; -// export const FourthDay = Template.bind({}); -// FourthDay.args = { -// currentDay: CARD_DAYS.DAY4, -// firstCardType: CARD_TYPE.FIRST_CARD, -// secondCardType: CARD_TYPE.SECOND_CARD, -// cardStatus: CARD_SELECTED_STATUS.FALSE, -// }; -// export const FifthDay = Template.bind({}); -// FifthDay.args = { -// currentDay: CARD_DAYS.DAY5, -// firstCardType: CARD_TYPE.FIRST_CARD, -// secondCardType: CARD_TYPE.SECOND_CARD, -// cardStatus: CARD_SELECTED_STATUS.FALSE, -// }; -// export const SixthDay = Template.bind({}); -// SixthDay.args = { -// currentDay: CARD_DAYS.DAY6, -// firstCardType: CARD_TYPE.FIRST_CARD, -// secondCardType: CARD_TYPE.SECOND_CARD, -// cardStatus: CARD_SELECTED_STATUS.FALSE, -// }; -export default {}; diff --git a/client/src/components/RushCardResultDescription/index.stories.tsx b/client/src/components/RushCardResultDescription/index.stories.tsx deleted file mode 100644 index f28b9035..00000000 --- a/client/src/components/RushCardResultDescription/index.stories.tsx +++ /dev/null @@ -1,57 +0,0 @@ -// import { Meta, StoryFn } from "@storybook/react"; -// import RushCardDescription from "@/components/RushCardDescription"; -// import { CARD_COLOR, CARD_DAYS, CARD_SELECTED_STATUS, CARD_TYPE } from "@/constants/Rush/rushCard"; -// -// export default { -// title: "Components/RushCardDescription", -// component: RushCardDescription, -// argTypes: { -// color: { -// control: { type: "select" }, -// options: Object.values(CARD_COLOR), -// description: "The background color of the card", -// table: { -// type: { summary: "CARD_COLOR" }, -// defaultValue: { summary: CARD_COLOR.GREEN }, -// }, -// }, -// day: { -// control: { type: "select" }, -// options: Object.values(CARD_DAYS), -// description: "The current day for selecting the card details", -// table: { -// type: { summary: "CARD_DAYS" }, -// defaultValue: { summary: CARD_DAYS.DAY1 }, -// }, -// }, -// cardType: { -// control: { type: "select" }, -// options: Object.values(CARD_TYPE), -// description: "두 개의 카드 중 하나", -// table: { -// type: { summary: "CARD_TYPE" }, -// defaultValue: { summary: CARD_TYPE.FIRST_CARD }, -// }, -// }, -// cardStatus: { -// control: { type: "select" }, -// options: Object.values(CARD_SELECTED_STATUS), -// description: "The selection status of the card", -// table: { -// type: { summary: "CARD_SELECTED_STATUS" }, -// defaultValue: { summary: CARD_SELECTED_STATUS.FALSE }, -// }, -// }, -// }, -// } as Meta; -// -// const Template: StoryFn = (args) => ; -// -// export const Default = Template.bind({}); -// Default.args = { -// color: CARD_COLOR.GREEN, -// day: CARD_DAYS.DAY5, -// cardType: CARD_TYPE.FIRST_CARD, -// cardStatus: CARD_SELECTED_STATUS.TRUE, -// }; -export default {}; diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame.tsx index 4b810175..4932f927 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame.tsx @@ -6,10 +6,10 @@ import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import CardOptions from "@/features/Rush/BalanceGame/CardOptions.tsx"; -import CountDown from "@/features/Rush/BalanceGame/CountDown.tsx"; -import FinalResult from "@/features/Rush/BalanceGame/FinalResult.tsx"; -import SelectedCard from "@/features/Rush/BalanceGame/SelectedCard.tsx"; +import CardOptions from "@/features/Rush/BalanceGameSection/CardOptions.tsx"; +import CountDown from "@/features/Rush/BalanceGameSection/CountDown.tsx"; +import FinalResult from "@/features/Rush/BalanceGameSection/FinalResult.tsx"; +import SelectedCard from "@/features/Rush/BalanceGameSection/SelectedCard.tsx"; import { useBalanceGameContext } from "@/hooks/useBalanceGameContext.ts"; import useCountDown from "@/hooks/useCountDown.ts"; import { SectionKeyProps } from "@/types/sections.ts"; diff --git a/client/src/components/RushCard/index.tsx b/client/src/features/Rush/BalanceGameCard/RushCard.tsx similarity index 95% rename from client/src/components/RushCard/index.tsx rename to client/src/features/Rush/BalanceGameCard/RushCard.tsx index 8a6f9c88..9081632e 100644 --- a/client/src/components/RushCard/index.tsx +++ b/client/src/features/Rush/BalanceGameCard/RushCard.tsx @@ -1,5 +1,5 @@ import { cva } from "class-variance-authority"; -import { CARD_COLOR } from "@/constants/Rush/rushCard"; +import { CARD_COLOR } from "@/constants/Rush/rushCard.ts"; interface RushCardProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; diff --git a/client/src/components/RushCardComparison/index.tsx b/client/src/features/Rush/BalanceGameCard/RushCardComparison.tsx similarity index 95% rename from client/src/components/RushCardComparison/index.tsx rename to client/src/features/Rush/BalanceGameCard/RushCardComparison.tsx index 38d81358..373a27db 100644 --- a/client/src/components/RushCardComparison/index.tsx +++ b/client/src/features/Rush/BalanceGameCard/RushCardComparison.tsx @@ -1,8 +1,8 @@ import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; -import RushCard from "@/components/RushCard/index.tsx"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard"; +import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import RushCard from "@/features/Rush/BalanceGameCard/RushCard.tsx"; export default function RushCardComparison() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); diff --git a/client/src/components/RushCardCurrentRatio/index.tsx b/client/src/features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx similarity index 100% rename from client/src/components/RushCardCurrentRatio/index.tsx rename to client/src/features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx diff --git a/client/src/components/RushCardResultDescription/index.tsx b/client/src/features/Rush/BalanceGameCard/RushCardResultDescription.tsx similarity index 98% rename from client/src/components/RushCardResultDescription/index.tsx rename to client/src/features/Rush/BalanceGameCard/RushCardResultDescription.tsx index b05d2054..c274054b 100644 --- a/client/src/components/RushCardResultDescription/index.tsx +++ b/client/src/features/Rush/BalanceGameCard/RushCardResultDescription.tsx @@ -6,7 +6,7 @@ import { CARD_OPTIONS, CARD_RESULTS, CARD_TYPE, -} from "@/constants/Rush/rushCard"; +} from "@/constants/Rush/rushCard.ts"; interface RushCardDescriptionProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; diff --git a/client/src/components/RushCountDown/index.tsx b/client/src/features/Rush/BalanceGameCard/RushCountDown.tsx similarity index 100% rename from client/src/components/RushCountDown/index.tsx rename to client/src/features/Rush/BalanceGameCard/RushCountDown.tsx diff --git a/client/src/features/Rush/BalanceGame/CardOptions.tsx b/client/src/features/Rush/BalanceGameSection/CardOptions.tsx similarity index 88% rename from client/src/features/Rush/BalanceGame/CardOptions.tsx rename to client/src/features/Rush/BalanceGameSection/CardOptions.tsx index 67608fe0..bf31dd3d 100644 --- a/client/src/features/Rush/BalanceGame/CardOptions.tsx +++ b/client/src/features/Rush/BalanceGameSection/CardOptions.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; -import RushCardComparison from "@/components/RushCardComparison"; -import RushCountDown from "@/components/RushCountDown"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; +import RushCardComparison from "@/features/Rush/BalanceGameCard/RushCardComparison.tsx"; +import RushCountDown from "@/features/Rush/BalanceGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; export default function CardOptions() { diff --git a/client/src/features/Rush/BalanceGame/CountDown.tsx b/client/src/features/Rush/BalanceGameSection/CountDown.tsx similarity index 100% rename from client/src/features/Rush/BalanceGame/CountDown.tsx rename to client/src/features/Rush/BalanceGameSection/CountDown.tsx diff --git a/client/src/features/Rush/BalanceGame/FinalResult.tsx b/client/src/features/Rush/BalanceGameSection/FinalResult.tsx similarity index 100% rename from client/src/features/Rush/BalanceGame/FinalResult.tsx rename to client/src/features/Rush/BalanceGameSection/FinalResult.tsx diff --git a/client/src/features/Rush/BalanceGame/SelectedCard.tsx b/client/src/features/Rush/BalanceGameSection/SelectedCard.tsx similarity index 91% rename from client/src/features/Rush/BalanceGame/SelectedCard.tsx rename to client/src/features/Rush/BalanceGameSection/SelectedCard.tsx index e66790ed..001ba924 100644 --- a/client/src/features/Rush/BalanceGame/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGameSection/SelectedCard.tsx @@ -1,10 +1,10 @@ import { useState } from "react"; import { motion } from "framer-motion"; -import RushCardCurrentRatio from "@/components/RushCardCurrentRatio"; -import RushCardResultDescription from "@/components/RushCardResultDescription"; -import RushCountDown from "@/components/RushCountDown"; import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; +import RushCardCurrentRatio from "@/features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx"; +import RushCardResultDescription from "@/features/Rush/BalanceGameCard/RushCardResultDescription.tsx"; +import RushCountDown from "@/features/Rush/BalanceGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; From 3c4d6bc136a12deb5b1a5e8584a26270ac53f933 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 00:12:31 +0900 Subject: [PATCH 059/111] =?UTF-8?q?refactor:=20features=20Rush=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Rush/{ => BalanceGame}/Background.tsx | 0 .../Rush/{ => BalanceGame}/BalanceGame.tsx | 8 +++--- .../BalanceGameCard/RushCard.tsx | 0 .../BalanceGameCard/RushCardComparison.tsx | 2 +- .../BalanceGameCard/RushCardCurrentRatio.tsx | 0 .../RushCardResultDescription.tsx | 0 .../BalanceGameCard/RushCountDown.tsx | 0 .../BalanceGameSection/CardOptions.tsx | 4 +-- .../BalanceGameSection/CountDown.tsx | 2 +- .../BalanceGameSection/FinalResult.tsx | 0 .../BalanceGameSection/SelectedCard.tsx | 6 ++--- .../Rush/{ => Casper}/CasperCharge.tsx | 4 +-- .../Rush/{ => Casper}/CasperComfortable.tsx | 4 +-- .../Rush/{ => Casper}/CasperDescription.tsx | 2 +- .../features/Rush/{ => Casper}/CasperFar.tsx | 4 +-- .../features/Rush/{ => Casper}/CasperFast.tsx | 4 +-- .../Rush/{ => Casper}/CasperSection.tsx | 0 .../Rush/{ => Casper}/CasperSmartKey.tsx | 2 +- .../{ => Casper}/CasperSubDescription.tsx | 0 .../features/Rush/{ => Casper}/CasperWide.tsx | 4 +-- .../Rush/{ => Electric}/ElectricAdvantage.tsx | 2 +- .../Rush/{ => Electric}/ElectricReason.tsx | 4 +-- .../{ => Electric}/ElectricReasonCard.tsx | 0 .../Rush/{ => Electric}/ElectricSection.tsx | 0 client/src/features/Rush/{ => Extra}/FAQ.tsx | 0 .../src/features/Rush/{ => Extra}/Intro.tsx | 0 .../Rush/{ => Reason}/ReasonFirst.tsx | 2 +- .../Rush/{ => Reason}/ReasonSecond.tsx | 2 +- .../Rush/{ => Reason}/ReasonSection.tsx | 0 client/src/features/Rush/index.tsx | 26 +++++++++---------- 30 files changed, 41 insertions(+), 41 deletions(-) rename client/src/features/Rush/{ => BalanceGame}/Background.tsx (100%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGame.tsx (91%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameCard/RushCard.tsx (100%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameCard/RushCardComparison.tsx (96%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameCard/RushCardCurrentRatio.tsx (100%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameCard/RushCardResultDescription.tsx (100%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameCard/RushCountDown.tsx (100%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameSection/CardOptions.tsx (86%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameSection/CountDown.tsx (96%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameSection/FinalResult.tsx (100%) rename client/src/features/Rush/{ => BalanceGame}/BalanceGameSection/SelectedCard.tsx (92%) rename client/src/features/Rush/{ => Casper}/CasperCharge.tsx (92%) rename client/src/features/Rush/{ => Casper}/CasperComfortable.tsx (94%) rename client/src/features/Rush/{ => Casper}/CasperDescription.tsx (88%) rename client/src/features/Rush/{ => Casper}/CasperFar.tsx (89%) rename client/src/features/Rush/{ => Casper}/CasperFast.tsx (90%) rename client/src/features/Rush/{ => Casper}/CasperSection.tsx (100%) rename client/src/features/Rush/{ => Casper}/CasperSmartKey.tsx (92%) rename client/src/features/Rush/{ => Casper}/CasperSubDescription.tsx (100%) rename client/src/features/Rush/{ => Casper}/CasperWide.tsx (93%) rename client/src/features/Rush/{ => Electric}/ElectricAdvantage.tsx (97%) rename client/src/features/Rush/{ => Electric}/ElectricReason.tsx (87%) rename client/src/features/Rush/{ => Electric}/ElectricReasonCard.tsx (100%) rename client/src/features/Rush/{ => Electric}/ElectricSection.tsx (100%) rename client/src/features/Rush/{ => Extra}/FAQ.tsx (100%) rename client/src/features/Rush/{ => Extra}/Intro.tsx (100%) rename client/src/features/Rush/{ => Reason}/ReasonFirst.tsx (87%) rename client/src/features/Rush/{ => Reason}/ReasonSecond.tsx (84%) rename client/src/features/Rush/{ => Reason}/ReasonSection.tsx (100%) diff --git a/client/src/features/Rush/Background.tsx b/client/src/features/Rush/BalanceGame/Background.tsx similarity index 100% rename from client/src/features/Rush/Background.tsx rename to client/src/features/Rush/BalanceGame/Background.tsx diff --git a/client/src/features/Rush/BalanceGame.tsx b/client/src/features/Rush/BalanceGame/BalanceGame.tsx similarity index 91% rename from client/src/features/Rush/BalanceGame.tsx rename to client/src/features/Rush/BalanceGame/BalanceGame.tsx index 4932f927..12259168 100644 --- a/client/src/features/Rush/BalanceGame.tsx +++ b/client/src/features/Rush/BalanceGame/BalanceGame.tsx @@ -6,10 +6,10 @@ import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import CardOptions from "@/features/Rush/BalanceGameSection/CardOptions.tsx"; -import CountDown from "@/features/Rush/BalanceGameSection/CountDown.tsx"; -import FinalResult from "@/features/Rush/BalanceGameSection/FinalResult.tsx"; -import SelectedCard from "@/features/Rush/BalanceGameSection/SelectedCard.tsx"; +import CardOptions from "@/features/Rush/BalanceGame/BalanceGameSection/CardOptions.tsx"; +import CountDown from "@/features/Rush/BalanceGame/BalanceGameSection/CountDown.tsx"; +import FinalResult from "@/features/Rush/BalanceGame/BalanceGameSection/FinalResult.tsx"; +import SelectedCard from "@/features/Rush/BalanceGame/BalanceGameSection/SelectedCard.tsx"; import { useBalanceGameContext } from "@/hooks/useBalanceGameContext.ts"; import useCountDown from "@/hooks/useCountDown.ts"; import { SectionKeyProps } from "@/types/sections.ts"; diff --git a/client/src/features/Rush/BalanceGameCard/RushCard.tsx b/client/src/features/Rush/BalanceGame/BalanceGameCard/RushCard.tsx similarity index 100% rename from client/src/features/Rush/BalanceGameCard/RushCard.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameCard/RushCard.tsx diff --git a/client/src/features/Rush/BalanceGameCard/RushCardComparison.tsx b/client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardComparison.tsx similarity index 96% rename from client/src/features/Rush/BalanceGameCard/RushCardComparison.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardComparison.tsx index 373a27db..c629ae2a 100644 --- a/client/src/features/Rush/BalanceGameCard/RushCardComparison.tsx +++ b/client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardComparison.tsx @@ -2,7 +2,7 @@ import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; -import RushCard from "@/features/Rush/BalanceGameCard/RushCard.tsx"; +import RushCard from "@/features/Rush/BalanceGame/BalanceGameCard/RushCard.tsx"; export default function RushCardComparison() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); diff --git a/client/src/features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx b/client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardCurrentRatio.tsx similarity index 100% rename from client/src/features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardCurrentRatio.tsx diff --git a/client/src/features/Rush/BalanceGameCard/RushCardResultDescription.tsx b/client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardResultDescription.tsx similarity index 100% rename from client/src/features/Rush/BalanceGameCard/RushCardResultDescription.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameCard/RushCardResultDescription.tsx diff --git a/client/src/features/Rush/BalanceGameCard/RushCountDown.tsx b/client/src/features/Rush/BalanceGame/BalanceGameCard/RushCountDown.tsx similarity index 100% rename from client/src/features/Rush/BalanceGameCard/RushCountDown.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameCard/RushCountDown.tsx diff --git a/client/src/features/Rush/BalanceGameSection/CardOptions.tsx b/client/src/features/Rush/BalanceGame/BalanceGameSection/CardOptions.tsx similarity index 86% rename from client/src/features/Rush/BalanceGameSection/CardOptions.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameSection/CardOptions.tsx index bf31dd3d..07b19ca4 100644 --- a/client/src/features/Rush/BalanceGameSection/CardOptions.tsx +++ b/client/src/features/Rush/BalanceGame/BalanceGameSection/CardOptions.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushCardComparison from "@/features/Rush/BalanceGameCard/RushCardComparison.tsx"; -import RushCountDown from "@/features/Rush/BalanceGameCard/RushCountDown.tsx"; +import RushCardComparison from "@/features/Rush/BalanceGame/BalanceGameCard/RushCardComparison.tsx"; +import RushCountDown from "@/features/Rush/BalanceGame/BalanceGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; export default function CardOptions() { diff --git a/client/src/features/Rush/BalanceGameSection/CountDown.tsx b/client/src/features/Rush/BalanceGame/BalanceGameSection/CountDown.tsx similarity index 96% rename from client/src/features/Rush/BalanceGameSection/CountDown.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameSection/CountDown.tsx index 13942bbc..5f9b1ce5 100644 --- a/client/src/features/Rush/BalanceGameSection/CountDown.tsx +++ b/client/src/features/Rush/BalanceGame/BalanceGameSection/CountDown.tsx @@ -1,6 +1,6 @@ import { motion } from "framer-motion"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { Background } from "@/features/Rush/Background.tsx"; +import { Background } from "@/features/Rush/BalanceGame/Background.tsx"; interface CountDownProps { countdown: number; diff --git a/client/src/features/Rush/BalanceGameSection/FinalResult.tsx b/client/src/features/Rush/BalanceGame/BalanceGameSection/FinalResult.tsx similarity index 100% rename from client/src/features/Rush/BalanceGameSection/FinalResult.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameSection/FinalResult.tsx diff --git a/client/src/features/Rush/BalanceGameSection/SelectedCard.tsx b/client/src/features/Rush/BalanceGame/BalanceGameSection/SelectedCard.tsx similarity index 92% rename from client/src/features/Rush/BalanceGameSection/SelectedCard.tsx rename to client/src/features/Rush/BalanceGame/BalanceGameSection/SelectedCard.tsx index 001ba924..9f6f4f8c 100644 --- a/client/src/features/Rush/BalanceGameSection/SelectedCard.tsx +++ b/client/src/features/Rush/BalanceGame/BalanceGameSection/SelectedCard.tsx @@ -2,9 +2,9 @@ import { useState } from "react"; import { motion } from "framer-motion"; import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushCardCurrentRatio from "@/features/Rush/BalanceGameCard/RushCardCurrentRatio.tsx"; -import RushCardResultDescription from "@/features/Rush/BalanceGameCard/RushCardResultDescription.tsx"; -import RushCountDown from "@/features/Rush/BalanceGameCard/RushCountDown.tsx"; +import RushCardCurrentRatio from "@/features/Rush/BalanceGame/BalanceGameCard/RushCardCurrentRatio.tsx"; +import RushCardResultDescription from "@/features/Rush/BalanceGame/BalanceGameCard/RushCardResultDescription.tsx"; +import RushCountDown from "@/features/Rush/BalanceGame/BalanceGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; diff --git a/client/src/features/Rush/CasperCharge.tsx b/client/src/features/Rush/Casper/CasperCharge.tsx similarity index 92% rename from client/src/features/Rush/CasperCharge.tsx rename to client/src/features/Rush/Casper/CasperCharge.tsx index 10be5124..8aeb5d16 100644 --- a/client/src/features/Rush/CasperCharge.tsx +++ b/client/src/features/Rush/Casper/CasperCharge.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperDescription } from "@/features/Rush/CasperDescription.tsx"; -import { CasperSection } from "@/features/Rush/CasperSection.tsx"; +import { CasperDescription } from "@/features/Rush/Casper/CasperDescription.tsx"; +import { CasperSection } from "@/features/Rush/Casper/CasperSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function CasperCharge({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/CasperComfortable.tsx b/client/src/features/Rush/Casper/CasperComfortable.tsx similarity index 94% rename from client/src/features/Rush/CasperComfortable.tsx rename to client/src/features/Rush/Casper/CasperComfortable.tsx index 82c32e6b..a6765ec4 100644 --- a/client/src/features/Rush/CasperComfortable.tsx +++ b/client/src/features/Rush/Casper/CasperComfortable.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperDescription } from "@/features/Rush/CasperDescription.tsx"; -import { CasperSection } from "@/features/Rush/CasperSection.tsx"; +import { CasperDescription } from "@/features/Rush/Casper/CasperDescription.tsx"; +import { CasperSection } from "@/features/Rush/Casper/CasperSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function CasperComfortable({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/CasperDescription.tsx b/client/src/features/Rush/Casper/CasperDescription.tsx similarity index 88% rename from client/src/features/Rush/CasperDescription.tsx rename to client/src/features/Rush/Casper/CasperDescription.tsx index cf1f4a5d..9e6eba6e 100644 --- a/client/src/features/Rush/CasperDescription.tsx +++ b/client/src/features/Rush/Casper/CasperDescription.tsx @@ -1,7 +1,7 @@ import { ReactNode } from "react"; import { motion } from "framer-motion"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperSubDescription } from "@/features/Rush/CasperSubDescription.tsx"; +import { CasperSubDescription } from "@/features/Rush/Casper/CasperSubDescription.tsx"; interface CasperDescriptionProps { title: ReactNode; diff --git a/client/src/features/Rush/CasperFar.tsx b/client/src/features/Rush/Casper/CasperFar.tsx similarity index 89% rename from client/src/features/Rush/CasperFar.tsx rename to client/src/features/Rush/Casper/CasperFar.tsx index ab4a052f..4c43564c 100644 --- a/client/src/features/Rush/CasperFar.tsx +++ b/client/src/features/Rush/Casper/CasperFar.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperDescription } from "@/features/Rush/CasperDescription.tsx"; -import { CasperSection } from "@/features/Rush/CasperSection.tsx"; +import { CasperDescription } from "@/features/Rush/Casper/CasperDescription.tsx"; +import { CasperSection } from "@/features/Rush/Casper/CasperSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function CasperFar({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/CasperFast.tsx b/client/src/features/Rush/Casper/CasperFast.tsx similarity index 90% rename from client/src/features/Rush/CasperFast.tsx rename to client/src/features/Rush/Casper/CasperFast.tsx index cbb6de1c..dc5bd94f 100644 --- a/client/src/features/Rush/CasperFast.tsx +++ b/client/src/features/Rush/Casper/CasperFast.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperDescription } from "@/features/Rush/CasperDescription.tsx"; -import { CasperSection } from "@/features/Rush/CasperSection.tsx"; +import { CasperDescription } from "@/features/Rush/Casper/CasperDescription.tsx"; +import { CasperSection } from "@/features/Rush/Casper/CasperSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function CasperFast({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/CasperSection.tsx b/client/src/features/Rush/Casper/CasperSection.tsx similarity index 100% rename from client/src/features/Rush/CasperSection.tsx rename to client/src/features/Rush/Casper/CasperSection.tsx diff --git a/client/src/features/Rush/CasperSmartKey.tsx b/client/src/features/Rush/Casper/CasperSmartKey.tsx similarity index 92% rename from client/src/features/Rush/CasperSmartKey.tsx rename to client/src/features/Rush/Casper/CasperSmartKey.tsx index 6a834e10..dca3f92e 100644 --- a/client/src/features/Rush/CasperSmartKey.tsx +++ b/client/src/features/Rush/Casper/CasperSmartKey.tsx @@ -1,6 +1,6 @@ import { motion } from "framer-motion"; import { DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperSubDescription } from "@/features/Rush/CasperSubDescription.tsx"; +import { CasperSubDescription } from "@/features/Rush/Casper/CasperSubDescription.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function CasperSmartKey({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/CasperSubDescription.tsx b/client/src/features/Rush/Casper/CasperSubDescription.tsx similarity index 100% rename from client/src/features/Rush/CasperSubDescription.tsx rename to client/src/features/Rush/Casper/CasperSubDescription.tsx diff --git a/client/src/features/Rush/CasperWide.tsx b/client/src/features/Rush/Casper/CasperWide.tsx similarity index 93% rename from client/src/features/Rush/CasperWide.tsx rename to client/src/features/Rush/Casper/CasperWide.tsx index f5afe7f5..34d94c14 100644 --- a/client/src/features/Rush/CasperWide.tsx +++ b/client/src/features/Rush/Casper/CasperWide.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import { CasperDescription } from "@/features/Rush/CasperDescription.tsx"; -import { CasperSection } from "@/features/Rush/CasperSection.tsx"; +import { CasperDescription } from "@/features/Rush/Casper/CasperDescription.tsx"; +import { CasperSection } from "@/features/Rush/Casper/CasperSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function CasperWide({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/ElectricAdvantage.tsx b/client/src/features/Rush/Electric/ElectricAdvantage.tsx similarity index 97% rename from client/src/features/Rush/ElectricAdvantage.tsx rename to client/src/features/Rush/Electric/ElectricAdvantage.tsx index 1fe9f13f..5955091d 100644 --- a/client/src/features/Rush/ElectricAdvantage.tsx +++ b/client/src/features/Rush/Electric/ElectricAdvantage.tsx @@ -1,4 +1,4 @@ -import { ElectricSection } from "@/features/Rush/ElectricSection.tsx"; +import { ElectricSection } from "@/features/Rush/Electric/ElectricSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function ElectricAdvantage({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/ElectricReason.tsx b/client/src/features/Rush/Electric/ElectricReason.tsx similarity index 87% rename from client/src/features/Rush/ElectricReason.tsx rename to client/src/features/Rush/Electric/ElectricReason.tsx index 81276ef7..1a60ed92 100644 --- a/client/src/features/Rush/ElectricReason.tsx +++ b/client/src/features/Rush/Electric/ElectricReason.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import Toggle from "@/components/Toggle"; import { CARD_DATA, TOGGLE_OPTIONS } from "@/constants/Rush/electricCardData.tsx"; -import { ElectricReasonCard } from "@/features/Rush/ElectricReasonCard.tsx"; -import { ElectricSection } from "@/features/Rush/ElectricSection.tsx"; +import { ElectricReasonCard } from "@/features/Rush/Electric/ElectricReasonCard.tsx"; +import { ElectricSection } from "@/features/Rush/Electric/ElectricSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function ElectricReason({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/ElectricReasonCard.tsx b/client/src/features/Rush/Electric/ElectricReasonCard.tsx similarity index 100% rename from client/src/features/Rush/ElectricReasonCard.tsx rename to client/src/features/Rush/Electric/ElectricReasonCard.tsx diff --git a/client/src/features/Rush/ElectricSection.tsx b/client/src/features/Rush/Electric/ElectricSection.tsx similarity index 100% rename from client/src/features/Rush/ElectricSection.tsx rename to client/src/features/Rush/Electric/ElectricSection.tsx diff --git a/client/src/features/Rush/FAQ.tsx b/client/src/features/Rush/Extra/FAQ.tsx similarity index 100% rename from client/src/features/Rush/FAQ.tsx rename to client/src/features/Rush/Extra/FAQ.tsx diff --git a/client/src/features/Rush/Intro.tsx b/client/src/features/Rush/Extra/Intro.tsx similarity index 100% rename from client/src/features/Rush/Intro.tsx rename to client/src/features/Rush/Extra/Intro.tsx diff --git a/client/src/features/Rush/ReasonFirst.tsx b/client/src/features/Rush/Reason/ReasonFirst.tsx similarity index 87% rename from client/src/features/Rush/ReasonFirst.tsx rename to client/src/features/Rush/Reason/ReasonFirst.tsx index 93386194..b803e904 100644 --- a/client/src/features/Rush/ReasonFirst.tsx +++ b/client/src/features/Rush/Reason/ReasonFirst.tsx @@ -1,4 +1,4 @@ -import { ReasonSection } from "@/features/Rush/ReasonSection.tsx"; +import { ReasonSection } from "@/features/Rush/Reason/ReasonSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function ReasonFirst({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/ReasonSecond.tsx b/client/src/features/Rush/Reason/ReasonSecond.tsx similarity index 84% rename from client/src/features/Rush/ReasonSecond.tsx rename to client/src/features/Rush/Reason/ReasonSecond.tsx index 427cabe3..3dd39657 100644 --- a/client/src/features/Rush/ReasonSecond.tsx +++ b/client/src/features/Rush/Reason/ReasonSecond.tsx @@ -1,4 +1,4 @@ -import { ReasonSection } from "@/features/Rush/ReasonSection.tsx"; +import { ReasonSection } from "@/features/Rush/Reason/ReasonSection.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; export function ReasonSecond({ id }: SectionKeyProps) { diff --git a/client/src/features/Rush/ReasonSection.tsx b/client/src/features/Rush/Reason/ReasonSection.tsx similarity index 100% rename from client/src/features/Rush/ReasonSection.tsx rename to client/src/features/Rush/Reason/ReasonSection.tsx diff --git a/client/src/features/Rush/index.tsx b/client/src/features/Rush/index.tsx index 5e9d9265..8ead84cb 100644 --- a/client/src/features/Rush/index.tsx +++ b/client/src/features/Rush/index.tsx @@ -1,13 +1,13 @@ -export { CasperComfortable } from "./CasperComfortable.tsx"; -export { CasperFar } from "./CasperFar.tsx"; -export { CasperFast } from "./CasperFast.tsx"; -export { CasperSmartKey } from "./CasperSmartKey.tsx"; -export { CasperWide } from "./CasperWide.tsx"; -export { ElectricAdvantage } from "./ElectricAdvantage.tsx"; -export { ElectricReason } from "./ElectricReason.tsx"; -export { FAQ } from "./FAQ.tsx"; -export { Intro } from "./Intro.tsx"; -export { ReasonFirst } from "./ReasonFirst.tsx"; -export { ReasonSecond } from "./ReasonSecond.tsx"; -export { CasperCharge } from "./CasperCharge.tsx"; -export { BalanceGame } from "./BalanceGame.tsx"; +export { CasperComfortable } from "./Casper/CasperComfortable.tsx"; +export { CasperFar } from "./Casper/CasperFar.tsx"; +export { CasperFast } from "./Casper/CasperFast.tsx"; +export { CasperSmartKey } from "./Casper/CasperSmartKey.tsx"; +export { CasperWide } from "./Casper/CasperWide.tsx"; +export { ElectricAdvantage } from "./Electric/ElectricAdvantage.tsx"; +export { ElectricReason } from "./Electric/ElectricReason.tsx"; +export { FAQ } from "./Extra/FAQ.tsx"; +export { Intro } from "./Extra/Intro.tsx"; +export { ReasonFirst } from "./Reason/ReasonFirst.tsx"; +export { ReasonSecond } from "./Reason/ReasonSecond.tsx"; +export { CasperCharge } from "./Casper/CasperCharge.tsx"; +export { BalanceGame } from "./BalanceGame/BalanceGame.tsx"; From 0c409d1a6de1384d3c0aa9c1c32c0bc99e395c1a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 00:27:31 +0900 Subject: [PATCH 060/111] =?UTF-8?q?rename:=20balanceGame=20rushGame=20?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=AA=85=EC=B9=AD=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/PageSections/sections.ts | 2 +- ...anceGameContext.tsx => rushGameContext.tsx} | 12 ++++++------ .../{BalanceGame => RushGame}/Background.tsx | 0 .../BalanceGame.tsx => RushGame/RushGame.tsx} | 18 +++++++++--------- .../RushGameCard}/RushCard.tsx | 0 .../RushGameCard}/RushCardComparison.tsx | 2 +- .../RushGameCard}/RushCardCurrentRatio.tsx | 0 .../RushCardResultDescription.tsx | 0 .../RushGameCard}/RushCountDown.tsx | 0 .../RushGameSection}/CardOptions.tsx | 4 ++-- .../RushGameSection}/CountDown.tsx | 2 +- .../RushGameSection}/FinalResult.tsx | 0 .../RushGameSection}/SelectedCard.tsx | 6 +++--- client/src/features/Rush/index.tsx | 2 +- client/src/hooks/useBalanceGameContext.ts | 10 ---------- client/src/hooks/useRushGameContext.ts | 10 ++++++++++ client/src/pages/Rush/index.tsx | 10 +++++----- .../src/types/{balanceGame.ts => rushGame.ts} | 4 ++-- 18 files changed, 41 insertions(+), 41 deletions(-) rename client/src/contexts/{balanceGameContext.tsx => rushGameContext.tsx} (58%) rename client/src/features/Rush/{BalanceGame => RushGame}/Background.tsx (100%) rename client/src/features/Rush/{BalanceGame/BalanceGame.tsx => RushGame/RushGame.tsx} (85%) rename client/src/features/Rush/{BalanceGame/BalanceGameCard => RushGame/RushGameCard}/RushCard.tsx (100%) rename client/src/features/Rush/{BalanceGame/BalanceGameCard => RushGame/RushGameCard}/RushCardComparison.tsx (96%) rename client/src/features/Rush/{BalanceGame/BalanceGameCard => RushGame/RushGameCard}/RushCardCurrentRatio.tsx (100%) rename client/src/features/Rush/{BalanceGame/BalanceGameCard => RushGame/RushGameCard}/RushCardResultDescription.tsx (100%) rename client/src/features/Rush/{BalanceGame/BalanceGameCard => RushGame/RushGameCard}/RushCountDown.tsx (100%) rename client/src/features/Rush/{BalanceGame/BalanceGameSection => RushGame/RushGameSection}/CardOptions.tsx (86%) rename client/src/features/Rush/{BalanceGame/BalanceGameSection => RushGame/RushGameSection}/CountDown.tsx (96%) rename client/src/features/Rush/{BalanceGame/BalanceGameSection => RushGame/RushGameSection}/FinalResult.tsx (100%) rename client/src/features/Rush/{BalanceGame/BalanceGameSection => RushGame/RushGameSection}/SelectedCard.tsx (90%) delete mode 100644 client/src/hooks/useBalanceGameContext.ts create mode 100644 client/src/hooks/useRushGameContext.ts rename client/src/types/{balanceGame.ts => rushGame.ts} (70%) diff --git a/client/src/constants/PageSections/sections.ts b/client/src/constants/PageSections/sections.ts index c345de06..7d25bc5a 100644 --- a/client/src/constants/PageSections/sections.ts +++ b/client/src/constants/PageSections/sections.ts @@ -18,7 +18,7 @@ export const LOTTERY_SECTIONS = { } as const; export const RUSH_SECTIONS = { - BALANCE_GAME: "BALANCE_GAME", + RUSH_GAME: "RUSH_GAME", INTRO: "INTRO", FAQ: "FAQ", ELECTRIC_REASON: "ELECTRIC_REASON", diff --git a/client/src/contexts/balanceGameContext.tsx b/client/src/contexts/rushGameContext.tsx similarity index 58% rename from client/src/contexts/balanceGameContext.tsx rename to client/src/contexts/rushGameContext.tsx index d9aa83f0..7c77345d 100644 --- a/client/src/contexts/balanceGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,11 +1,11 @@ import { ReactNode, createContext, useState } from "react"; -import { BalanceGameContextType } from "@/types/balanceGame"; import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; +import { RushGameContextType } from "@/types/rushGame.ts"; -export const BalanceGameContext = createContext(undefined); +export const RushGameContext = createContext(undefined); -export const BalanceGameProvider = ({ children }: { children: ReactNode }) => { - const [gameState, setGameState] = useState({ +export const RushGameProvider = ({ children }: { children: ReactNode }) => { + const [gameState, setGameState] = useState({ phase: "PRE_EVENT", userParticipated: false, }); @@ -18,10 +18,10 @@ export const BalanceGameProvider = ({ children }: { children: ReactNode }) => { }; return ( - {children} - + ); }; diff --git a/client/src/features/Rush/BalanceGame/Background.tsx b/client/src/features/Rush/RushGame/Background.tsx similarity index 100% rename from client/src/features/Rush/BalanceGame/Background.tsx rename to client/src/features/Rush/RushGame/Background.tsx diff --git a/client/src/features/Rush/BalanceGame/BalanceGame.tsx b/client/src/features/Rush/RushGame/RushGame.tsx similarity index 85% rename from client/src/features/Rush/BalanceGame/BalanceGame.tsx rename to client/src/features/Rush/RushGame/RushGame.tsx index 12259168..e1cc2d44 100644 --- a/client/src/features/Rush/BalanceGame/BalanceGame.tsx +++ b/client/src/features/Rush/RushGame/RushGame.tsx @@ -6,17 +6,17 @@ import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import CardOptions from "@/features/Rush/BalanceGame/BalanceGameSection/CardOptions.tsx"; -import CountDown from "@/features/Rush/BalanceGame/BalanceGameSection/CountDown.tsx"; -import FinalResult from "@/features/Rush/BalanceGame/BalanceGameSection/FinalResult.tsx"; -import SelectedCard from "@/features/Rush/BalanceGame/BalanceGameSection/SelectedCard.tsx"; -import { useBalanceGameContext } from "@/hooks/useBalanceGameContext.ts"; +import CardOptions from "@/features/Rush/RushGame/RushGameSection/CardOptions.tsx"; +import CountDown from "@/features/Rush/RushGame/RushGameSection/CountDown.tsx"; +import FinalResult from "@/features/Rush/RushGame/RushGameSection/FinalResult.tsx"; +import SelectedCard from "@/features/Rush/RushGame/RushGameSection/SelectedCard.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; +import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { SectionKeyProps } from "@/types/sections.ts"; -export function BalanceGame({ id }: SectionKeyProps) { +export function RushGame({ id }: SectionKeyProps) { // const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const { gameState, setGameState, updateUserParticipationStatus } = useBalanceGameContext(); + const { gameState, setGameState, updateUserParticipationStatus } = useRushGameContext(); // const [initialCountdown, setInitialCountdown] = useState(null); // useEffect(() => { @@ -53,7 +53,7 @@ export function BalanceGame({ id }: SectionKeyProps) { } }, [countdown, gameState.phase, setGameState]); - const renderBalanceGameContent = () => { + const renderRushGameContent = () => { switch (gameState.phase) { case "PRE_EVENT": return ; @@ -76,7 +76,7 @@ export function BalanceGame({ id }: SectionKeyProps) { id={id} className="relative h-screen bg-n-white flex flex-col gap-8 justify-center items-center snap-start" > - {renderBalanceGameContent()} + {renderRushGameContent()} { - const context = useContext(BalanceGameContext); - if (context === undefined) { - throw new Error("useBalanceGameContext must be used within a BalanceGameProvider"); - } - return context; -}; diff --git a/client/src/hooks/useRushGameContext.ts b/client/src/hooks/useRushGameContext.ts new file mode 100644 index 00000000..45d785b5 --- /dev/null +++ b/client/src/hooks/useRushGameContext.ts @@ -0,0 +1,10 @@ +import { useContext } from "react"; +import { RushGameContext } from "@/contexts/rushGameContext.tsx"; + +export const useRushGameContext = () => { + const context = useContext(RushGameContext); + if (context === undefined) { + throw new Error("useRushGameContext must be used within a RushGameProvider"); + } + return context; +}; diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index 26b42302..bbae8192 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -1,9 +1,8 @@ import Footer from "@/components/Footer"; import Notice from "@/components/Notice"; import { RUSH_SECTIONS } from "@/constants/PageSections/sections.ts"; -import { BalanceGameProvider } from "@/contexts/balanceGameContext.tsx"; +import { RushGameProvider } from "@/contexts/rushGameContext.tsx"; import { - BalanceGame, CasperCharge, CasperComfortable, CasperFar, @@ -16,6 +15,7 @@ import { Intro, ReasonFirst, ReasonSecond, + RushGame, } from "@/features/Rush"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; import useScrollTop from "@/hooks/useScrollTop.tsx"; @@ -28,9 +28,9 @@ export default function Rush() { return (
- - - + + + diff --git a/client/src/types/balanceGame.ts b/client/src/types/rushGame.ts similarity index 70% rename from client/src/types/balanceGame.ts rename to client/src/types/rushGame.ts index 50d68d7e..9b4bbcd3 100644 --- a/client/src/types/balanceGame.ts +++ b/client/src/types/rushGame.ts @@ -1,11 +1,11 @@ import React from "react"; import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; -export interface BalanceGameContextType { +export interface RushGameContextType { gameState: { phase: "PRE_EVENT" | "EVENT_RUNNING" | "EVENT_ENDED"; userParticipated: boolean; }; - setGameState: React.Dispatch>; + setGameState: React.Dispatch>; updateUserParticipationStatus: (response: GetRushUserParticipationStatusResponse) => void; } From 8b9def7f807b113ca160ea1965c51fbec4de39e5 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 11:09:33 +0900 Subject: [PATCH 061/111] =?UTF-8?q?chore:=20RushGame=20API=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/Rush/RushGame/RushGame.tsx | 60 +++++++++---------- client/src/features/Rush/index.tsx | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/client/src/features/Rush/RushGame/RushGame.tsx b/client/src/features/Rush/RushGame/RushGame.tsx index e1cc2d44..65022e7a 100644 --- a/client/src/features/Rush/RushGame/RushGame.tsx +++ b/client/src/features/Rush/RushGame/RushGame.tsx @@ -15,37 +15,36 @@ import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { SectionKeyProps } from "@/types/sections.ts"; export function RushGame({ id }: SectionKeyProps) { - // const [cookies] = useCookies([COOKIE_TOKEN_KEY]); + const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const { gameState, setGameState, updateUserParticipationStatus } = useRushGameContext(); - // const [initialCountdown, setInitialCountdown] = useState(null); + const [initialCountdown, setInitialCountdown] = useState(null); - // useEffect(() => { - // (async () => { - // try { - // const rushData = await RushAPI.getRush(); - // const currentEvent = rushData.events.find( - // (event) => event.rushEventId === rushData.todayEventId - // ); - // - // if (rushData.serverDateTime && currentEvent?.startDateTime) { - // const serverTime = new Date(rushData.serverDateTime).getTime(); - // const startTime = new Date(currentEvent.startDateTime).getTime(); - // const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); - // setInitialCountdown(countdown); - // } - // - // const userParticipated = await RushAPI.getRushUserParticipationStatus( - // cookies[COOKIE_TOKEN_KEY] - // ); - // updateUserParticipationStatus(userParticipated); - // } catch (error) { - // console.error("Error:", error); - // } - // })(); - // }, []); + useEffect(() => { + (async () => { + try { + const rushData = await RushAPI.getRush(); + const currentEvent = rushData.events.find( + (event) => event.rushEventId === rushData.todayEventId + ); + + if (rushData.serverDateTime && currentEvent?.startDateTime) { + const serverTime = new Date(rushData.serverDateTime).getTime(); + const startTime = new Date(currentEvent.startDateTime).getTime(); + const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); + setInitialCountdown(countdown); + } - // const countdown = useCountDown(initialCountdown || 0); - const countdown = useCountDown(1); + const userParticipated = await RushAPI.getRushUserParticipationStatus( + cookies[COOKIE_TOKEN_KEY] + ); + updateUserParticipationStatus(userParticipated); + } catch (error) { + console.error("Error:", error); + } + })(); + }, []); + + const countdown = useCountDown(initialCountdown || 0); useEffect(() => { if (countdown < 0 && gameState.phase === "PRE_EVENT") { @@ -59,8 +58,9 @@ export function RushGame({ id }: SectionKeyProps) { return ; case "EVENT_RUNNING": if (!gameState.userParticipated) { - // return ; - return ; + return ; + // return ; + // return ; } else { return ; } diff --git a/client/src/features/Rush/index.tsx b/client/src/features/Rush/index.tsx index e6d311af..3cade298 100644 --- a/client/src/features/Rush/index.tsx +++ b/client/src/features/Rush/index.tsx @@ -10,4 +10,4 @@ export { Intro } from "./Extra/Intro.tsx"; export { ReasonFirst } from "./Reason/ReasonFirst.tsx"; export { ReasonSecond } from "./Reason/ReasonSecond.tsx"; export { CasperCharge } from "./Casper/CasperCharge.tsx"; -export { RushGame } from "@/features/Rush/RushGame/RushGame.tsx"; +export { RushGame } from "./RushGame/RushGame.tsx"; From f0177ffff1b455ee7413234a2397c5f8054db559 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 12:15:56 +0900 Subject: [PATCH 062/111] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=20=ED=8C=9D=EC=97=85=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=ED=9B=85=EC=9C=BC=EB=A1=9C=20=EB=B9=BC?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Rush.tsx | 11 +++++ client/src/features/Main/Section.tsx | 9 +++- client/src/hooks/useAuth.ts | 64 ++++++++++++++++++++++++++++ client/src/pages/Lottery/index.tsx | 54 +++-------------------- 4 files changed, 88 insertions(+), 50 deletions(-) create mode 100644 client/src/hooks/useAuth.ts diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 4df6bf29..f1fc2d3f 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -3,6 +3,7 @@ import { RushAPI } from "@/apis/rushAPI.ts"; import RushEvent, { TotalRushEventsProps } from "@/components/RushEvent"; import { RUSH_EVENT_DATA } from "@/constants/Main/rushEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; +import useAuth from "@/hooks/useAuth.ts"; import { SectionKeyProps } from "@/types/sections.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; @@ -41,6 +42,12 @@ export function Rush({ id }: SectionKeyProps) { })(); }, []); + const { handleClickShortCut, PopupComponent, ToastComponent } = useAuth({ + eventStartDate: startDateTime ?? "", + eventEndDate: endDateTime ?? "", + confirmUrl: "/rush", + }); + return (
@@ -92,6 +100,9 @@ export function Rush({ id }: SectionKeyProps) {
+ + {PopupComponent} + {ToastComponent}
); } diff --git a/client/src/features/Main/Section.tsx b/client/src/features/Main/Section.tsx index 94b410e6..4550643f 100644 --- a/client/src/features/Main/Section.tsx +++ b/client/src/features/Main/Section.tsx @@ -12,6 +12,7 @@ interface SectionProps extends PropsWithChildren, SectionKeyProps { description: string; descriptionColor: string; url?: string; + onClick?: () => void; } export function Section({ @@ -24,6 +25,7 @@ export function Section({ descriptionColor, children, url, + onClick, }: SectionProps) { return (
{children} - +
); diff --git a/client/src/hooks/useAuth.ts b/client/src/hooks/useAuth.ts new file mode 100644 index 00000000..65f974b2 --- /dev/null +++ b/client/src/hooks/useAuth.ts @@ -0,0 +1,64 @@ +import { useState } from "react"; +import { useCookies } from "react-cookie"; +import { AuthAPI } from "@/apis/authAPI.ts"; +import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; +import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext.ts"; +import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext.ts"; +import usePopup from "@/hooks/usePopup.tsx"; +import useToast from "@/hooks/useToast.tsx"; +import { PHONE_NUMBER_ACTION } from "@/types/phoneNumber.ts"; +import { getMsTime } from "@/utils/getMsTime.ts"; + +interface UseAuthProps { + eventStartDate: string; + eventEndDate: string; + confirmUrl: string; +} + +export default function useAuth({ eventStartDate, eventEndDate, confirmUrl }: UseAuthProps) { + const [_cookies, setCookie] = useCookies([COOKIE_TOKEN_KEY]); + + const { phoneNumber } = usePhoneNumberStateContext(); + const dispatch = usePhoneNumberDispatchContext(); + + const [phoneNumberState, setPhoneNumberState] = useState(phoneNumber); + + const handlePhoneNumberChange = (val: string) => { + setPhoneNumberState(val); + }; + + const handlePhoneNumberConfirm = async (val: string) => { + const data = await AuthAPI.getAuthToken({ phoneNumber: val }); + + setCookie(COOKIE_TOKEN_KEY, data.accessToken); + dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: val }); + }; + + const { handleOpenPopup, PopupComponent } = usePopup({ + phoneNumber: phoneNumberState, + handlePhoneNumberChange, + handlePhoneNumberConfirm, + confirmUrl, + }); + const { showToast, ToastComponent } = useToast("이벤트 기간이 아닙니다"); + + const handleClickShortCut = () => { + const startDate = getMsTime(eventStartDate); + const endDate = getMsTime(eventEndDate); + const currentDate = new Date().getTime(); + + const isEventPeriod = currentDate >= startDate && currentDate <= endDate; + + if (isEventPeriod) { + handleOpenPopup(); + } else { + showToast(); + } + }; + + return { + handleClickShortCut, + PopupComponent, + ToastComponent, + }; +} diff --git a/client/src/pages/Lottery/index.tsx b/client/src/pages/Lottery/index.tsx index b1dd1a91..d9496419 100644 --- a/client/src/pages/Lottery/index.tsx +++ b/client/src/pages/Lottery/index.tsx @@ -1,10 +1,6 @@ -import { useState } from "react"; -import { useCookies } from "react-cookie"; import { useLoaderData } from "react-router-dom"; -import { AuthAPI } from "@/apis/authAPI"; import Footer from "@/components/Footer"; import Notice from "@/components/Notice"; -import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token"; import { LOTTERY_SECTIONS } from "@/constants/PageSections/sections.ts"; import { CustomDesign, @@ -17,63 +13,23 @@ import { SmileBadge, WheelDesign, } from "@/features/Lottery"; +import useAuth from "@/hooks/useAuth.ts"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; -import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext"; -import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext"; -import usePopup from "@/hooks/usePopup"; import useScrollTop from "@/hooks/useScrollTop"; -import useToast from "@/hooks/useToast"; import { GetLotteryResponse } from "@/types/lotteryApi"; -import { PHONE_NUMBER_ACTION } from "@/types/phoneNumber"; -import { getMsTime } from "@/utils/getMsTime"; export default function Lottery() { useScrollTop(); const containerRef = useHeaderStyleObserver({ darkSections: [LOTTERY_SECTIONS.HEADLINE, LOTTERY_SECTIONS.SHORT_CUT], }); - - const [_cookies, setCookie] = useCookies([COOKIE_TOKEN_KEY]); - - const { phoneNumber } = usePhoneNumberStateContext(); - const dispatch = usePhoneNumberDispatchContext(); - - const [phoneNumberState, setPhoneNumberState] = useState(phoneNumber); - const data = useLoaderData() as GetLotteryResponse; - const handlePhoneNumberChange = (val: string) => { - setPhoneNumberState(val); - }; - - const handlePhoneNumberConfirm = async (val: string) => { - const data = await AuthAPI.getAuthToken({ phoneNumber: val }); - - setCookie(COOKIE_TOKEN_KEY, data.accessToken); - dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: val }); - }; - - const { handleOpenPopup, PopupComponent } = usePopup({ - phoneNumber: phoneNumberState, - handlePhoneNumberChange, - handlePhoneNumberConfirm, - confirmUrl: `/lottery/custom`, + const { handleClickShortCut, PopupComponent, ToastComponent } = useAuth({ + eventStartDate: data.eventStartDate, + eventEndDate: data.eventEndDate, + confirmUrl: "/lottery/custom", }); - const { showToast, ToastComponent } = useToast("이벤트 기간이 아닙니다"); - - const handleClickShortCut = () => { - const startDate = getMsTime(data.eventStartDate); - const endDate = getMsTime(data.eventEndDate); - const currentDate = new Date().getTime(); - - const isEventPeriod = currentDate >= startDate && currentDate <= endDate; - - if (isEventPeriod) { - handleOpenPopup(); - } else { - showToast(); - } - }; return (
From 86c2c364663fa5e7f7c101b1cba1434b97c6841d Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 12:24:56 +0900 Subject: [PATCH 063/111] =?UTF-8?q?feat:=20RUSH=5FEVENT=5FDATA=EC=99=80=20?= =?UTF-8?q?Rush=20API=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=9D=B8=EB=8D=B1?= =?UTF-8?q?=EC=8A=A4=20=EB=A7=A4=EC=B9=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Main/rushEventData.ts | 7 ------- client/src/features/Main/Rush.tsx | 14 ++++++-------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/client/src/constants/Main/rushEventData.ts b/client/src/constants/Main/rushEventData.ts index edb7eb23..d808d562 100644 --- a/client/src/constants/Main/rushEventData.ts +++ b/client/src/constants/Main/rushEventData.ts @@ -1,37 +1,30 @@ export interface RushEventProps { - id: number; image: string; prizeName: string; } export const RUSH_EVENT_DATA: RushEventProps[] = [ { - id: 1, image: "/assets/main/rush/prize-1.png", prizeName: "영화 예매권", }, { - id: 2, image: "/assets/main/rush/prize-2.png", prizeName: "야구 관람권", }, { - id: 3, image: "/assets/main/rush/prize-3.jpg", prizeName: "올리브영 상품권", }, { - id: 4, image: "/assets/main/rush/prize-4.jpeg", prizeName: "쿠팡 기프트카드", }, { - id: 5, image: "/assets/main/rush/prize-5.jpg", prizeName: "배달의민족 기프트카드", }, { - id: 6, image: "/assets/main/rush/prize-6.jpg", prizeName: "BBQ 기프트카드", }, diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index f1fc2d3f..46db5f6f 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -16,21 +16,19 @@ export function Rush({ id }: SectionKeyProps) { (async () => { const rushData = await RushAPI.getRush(); const serverDateTime = new Date(rushData.serverDateTime); + setStartDateTime(rushData.eventsStartDate); setEndDateTime(rushData.eventsEndDate); - const events = rushData.events.map((event) => { - const rushEvent = RUSH_EVENT_DATA.find((re) => re.id === event.rushEventId) || { - image: "", - prizeName: "", - }; - + const events = rushData.events.map((event, idx) => { + const rushEvent = RUSH_EVENT_DATA[idx]; const eventEndTime = new Date(event.endDateTime); + return { id: event.rushEventId, date: event.startDateTime, - image: rushEvent.image, - prizeName: rushEvent.prizeName, + image: rushEvent?.image || "", + prizeName: rushEvent?.prizeName || "", isPastEvent: serverDateTime > eventEndTime, isTodayEvent: event.rushEventId === rushData.todayEventId && From ef02b9c506c093cdb60af7333df56b325b62bfc1 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 12:33:29 +0900 Subject: [PATCH 064/111] =?UTF-8?q?fix:=20Rush=20API=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20=EB=AA=85=EC=B9=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Notice/index.tsx | 4 ++-- client/src/components/RushEvent/index.tsx | 1 + client/src/features/Main/Rush.tsx | 6 +++--- client/src/features/Rush/RushGame/RushGame.tsx | 4 ++-- client/src/types/rushApi.ts | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index a1bd51af..37d401ca 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -41,8 +41,8 @@ const getEventsDateDetails = async (): Promise<{ ]); const rushEventDetails: EventDateDetails = { - startDate: rushData.eventsStartDate, - endDate: rushData.eventsEndDate, + startDate: rushData.eventStartDate, + endDate: rushData.eventEndDate, activePeriod: rushData.activePeriod, }; diff --git a/client/src/components/RushEvent/index.tsx b/client/src/components/RushEvent/index.tsx index cd0bea57..73eba311 100644 --- a/client/src/components/RushEvent/index.tsx +++ b/client/src/components/RushEvent/index.tsx @@ -2,6 +2,7 @@ import { RushEventProps } from "@/constants/Main/rushEventData.ts"; import { formatSingleDateWithSlash } from "@/utils/formatDate.ts"; export interface TotalRushEventsProps extends RushEventProps { + id: number; date: string; isPastEvent: boolean; isTodayEvent: boolean; diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 46db5f6f..1ca7c111 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -15,10 +15,10 @@ export function Rush({ id }: SectionKeyProps) { useEffect(() => { (async () => { const rushData = await RushAPI.getRush(); - const serverDateTime = new Date(rushData.serverDateTime); + const serverDateTime = new Date(rushData.serverTime); - setStartDateTime(rushData.eventsStartDate); - setEndDateTime(rushData.eventsEndDate); + setStartDateTime(rushData.eventStartDate); + setEndDateTime(rushData.eventEndDate); const events = rushData.events.map((event, idx) => { const rushEvent = RUSH_EVENT_DATA[idx]; diff --git a/client/src/features/Rush/RushGame/RushGame.tsx b/client/src/features/Rush/RushGame/RushGame.tsx index 65022e7a..6f9e968b 100644 --- a/client/src/features/Rush/RushGame/RushGame.tsx +++ b/client/src/features/Rush/RushGame/RushGame.tsx @@ -27,8 +27,8 @@ export function RushGame({ id }: SectionKeyProps) { (event) => event.rushEventId === rushData.todayEventId ); - if (rushData.serverDateTime && currentEvent?.startDateTime) { - const serverTime = new Date(rushData.serverDateTime).getTime(); + if (rushData.serverTime && currentEvent?.startDateTime) { + const serverTime = new Date(rushData.serverTime).getTime(); const startTime = new Date(currentEvent.startDateTime).getTime(); const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); setInitialCountdown(countdown); diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts index 112ca155..a05c9a6a 100644 --- a/client/src/types/rushApi.ts +++ b/client/src/types/rushApi.ts @@ -10,10 +10,10 @@ interface RushCardType { } export interface GetTotalRushEventsResponse { - serverDateTime: string; + serverTime: string; todayEventId: number; - eventsStartDate: string; - eventsEndDate: string; + eventStartDate: string; + eventEndDate: string; activePeriod: number; events: RushEventType[]; } From 83feff9f1e1c739cec0feabe5929ece6dc49bbe5 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 13:18:37 +0900 Subject: [PATCH 065/111] =?UTF-8?q?chore:=20Rush=20startDateTime,=20endDat?= =?UTF-8?q?eTime=20=EC=B4=88=EA=B9=83=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Rush.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 1ca7c111..b037c225 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -9,8 +9,8 @@ import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; export function Rush({ id }: SectionKeyProps) { const [rushEvents, setRushEvents] = useState([]); - const [startDateTime, setStartDateTime] = useState(null); - const [endDateTime, setEndDateTime] = useState(null); + const [startDateTime, setStartDateTime] = useState(""); + const [endDateTime, setEndDateTime] = useState(""); useEffect(() => { (async () => { @@ -41,8 +41,8 @@ export function Rush({ id }: SectionKeyProps) { }, []); const { handleClickShortCut, PopupComponent, ToastComponent } = useAuth({ - eventStartDate: startDateTime ?? "", - eventEndDate: endDateTime ?? "", + eventStartDate: startDateTime, + eventEndDate: endDateTime, confirmUrl: "/rush", }); From 4d48f1179c84a33b3946d0cb3eee1c9e8fee9fd9 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 14:01:52 +0900 Subject: [PATCH 066/111] =?UTF-8?q?feat:=20Main=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EA=B8=B0=EA=B0=84=20TotalAPI=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/totalAPI.ts | 21 +++++++++++++++++++++ client/src/features/Main/Headline.tsx | 8 ++++---- client/src/types/totalApi.ts | 4 ++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 client/src/apis/totalAPI.ts create mode 100644 client/src/types/totalApi.ts diff --git a/client/src/apis/totalAPI.ts b/client/src/apis/totalAPI.ts new file mode 100644 index 00000000..5d4b732a --- /dev/null +++ b/client/src/apis/totalAPI.ts @@ -0,0 +1,21 @@ +import { GetTotalEventDateResponse } from "@/types/totalApi.ts"; + +const baseURL = `${import.meta.env.VITE_API_URL}/event/total`; +const headers = { + "Content-Type": "application/json", +}; + +export const TotalAPI = { + async getTotal(): Promise { + try { + const response = await fetch(`${baseURL}`, { + method: "GET", + headers: headers, + }); + return response.json(); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, +}; diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index 8b8fcdcc..58cf564c 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; -import { LotteryAPI } from "@/apis/lotteryAPI.ts"; +import { TotalAPI } from "@/apis/totalAPI.ts"; import Keyword from "@/components/Keyword"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; @@ -13,9 +13,9 @@ export function Headline({ id }: SectionKeyProps) { useEffect(() => { (async () => { - const lotteryData = await LotteryAPI.getLottery(); - setStartDateTime(lotteryData.eventStartDate); - setEndDateTime(lotteryData.eventEndDate); + const totalData = await TotalAPI.getTotal(); + setStartDateTime(totalData.totalEventStartDate); + setEndDateTime(totalData.totalEventEndDate); })(); }, []); diff --git a/client/src/types/totalApi.ts b/client/src/types/totalApi.ts new file mode 100644 index 00000000..81d4dd36 --- /dev/null +++ b/client/src/types/totalApi.ts @@ -0,0 +1,4 @@ +export interface GetTotalEventDateResponse { + totalEventStartDate: string; + totalEventEndDate: string; +} From 13beb56205c72ee78b55a2cb3389a95844c9de2f Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 14:15:28 +0900 Subject: [PATCH 067/111] =?UTF-8?q?fix:=20=EC=BF=A0=ED=82=A4=20path=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EB=A3=A8=ED=8A=B8=EB=A1=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Rush.tsx | 1 - client/src/hooks/useAuth.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index b037c225..06633fb8 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -55,7 +55,6 @@ export function Rush({ id }: SectionKeyProps) { subtitle="매일 315명에게! 짜릿짜릿 선착순 밸런스 게임" description="매일 오후 10시! 선착순 밸런스 게임 참여하고 선물 받자!" descriptionColor="text-s-red" - url="/rush" onClick={handleClickShortCut} >
diff --git a/client/src/hooks/useAuth.ts b/client/src/hooks/useAuth.ts index 65f974b2..48390182 100644 --- a/client/src/hooks/useAuth.ts +++ b/client/src/hooks/useAuth.ts @@ -30,7 +30,7 @@ export default function useAuth({ eventStartDate, eventEndDate, confirmUrl }: Us const handlePhoneNumberConfirm = async (val: string) => { const data = await AuthAPI.getAuthToken({ phoneNumber: val }); - setCookie(COOKIE_TOKEN_KEY, data.accessToken); + setCookie(COOKIE_TOKEN_KEY, data.accessToken, { path: "/" }); dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: val }); }; From a4e385cc04c0dc4766772244eecb3b0062f716db Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 16:36:05 +0900 Subject: [PATCH 068/111] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?= =?UTF-8?q?=EB=B0=B8=EB=9F=B0=EC=8A=A4=20=EA=B2=8C=EC=9E=84=20=EC=A7=84?= =?UTF-8?q?=EC=9E=85=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/PageSections/sections.ts | 2 +- client/src/features/Main/Rush.tsx | 12 +--- .../features/Rush/{Extra => Common}/FAQ.tsx | 0 client/src/features/Rush/Common/Headline.tsx | 67 +++++++++++++++++++ .../features/Rush/{Extra => Common}/Intro.tsx | 0 client/src/features/Rush/index.tsx | 6 +- .../{Rush => }/RushGame/Background.tsx | 4 +- .../RushGame/RushGameCard/RushCard.tsx | 0 .../RushGameCard/RushCardComparison.tsx | 2 +- .../RushGameCard/RushCardCurrentRatio.tsx | 0 .../RushCardResultDescription.tsx | 0 .../RushGame/RushGameCard/RushCountDown.tsx | 0 .../RushGame/RushGameSection/CardOptions.tsx | 4 +- .../RushGame/RushGameSection/CountDown.tsx | 10 ++- .../RushGame/RushGameSection/FinalResult.tsx | 0 .../RushGame/RushGameSection/SelectedCard.tsx | 6 +- client/src/pages/Rush/index.tsx | 7 +- .../RushGame.tsx => pages/RushGame/index.tsx} | 16 ++--- client/src/router.tsx | 17 ++++- 19 files changed, 109 insertions(+), 44 deletions(-) rename client/src/features/Rush/{Extra => Common}/FAQ.tsx (100%) create mode 100644 client/src/features/Rush/Common/Headline.tsx rename client/src/features/Rush/{Extra => Common}/Intro.tsx (100%) rename client/src/features/{Rush => }/RushGame/Background.tsx (86%) rename client/src/features/{Rush => }/RushGame/RushGameCard/RushCard.tsx (100%) rename client/src/features/{Rush => }/RushGame/RushGameCard/RushCardComparison.tsx (96%) rename client/src/features/{Rush => }/RushGame/RushGameCard/RushCardCurrentRatio.tsx (100%) rename client/src/features/{Rush => }/RushGame/RushGameCard/RushCardResultDescription.tsx (100%) rename client/src/features/{Rush => }/RushGame/RushGameCard/RushCountDown.tsx (100%) rename client/src/features/{Rush => }/RushGame/RushGameSection/CardOptions.tsx (87%) rename client/src/features/{Rush => }/RushGame/RushGameSection/CountDown.tsx (83%) rename client/src/features/{Rush => }/RushGame/RushGameSection/FinalResult.tsx (100%) rename client/src/features/{Rush => }/RushGame/RushGameSection/SelectedCard.tsx (90%) rename client/src/{features/Rush/RushGame/RushGame.tsx => pages/RushGame/index.tsx} (85%) diff --git a/client/src/constants/PageSections/sections.ts b/client/src/constants/PageSections/sections.ts index 7d25bc5a..bbc04fcf 100644 --- a/client/src/constants/PageSections/sections.ts +++ b/client/src/constants/PageSections/sections.ts @@ -18,7 +18,7 @@ export const LOTTERY_SECTIONS = { } as const; export const RUSH_SECTIONS = { - RUSH_GAME: "RUSH_GAME", + HEADLINE: "HEADLINE", INTRO: "INTRO", FAQ: "FAQ", ELECTRIC_REASON: "ELECTRIC_REASON", diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 06633fb8..9ab408df 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -3,7 +3,6 @@ import { RushAPI } from "@/apis/rushAPI.ts"; import RushEvent, { TotalRushEventsProps } from "@/components/RushEvent"; import { RUSH_EVENT_DATA } from "@/constants/Main/rushEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; -import useAuth from "@/hooks/useAuth.ts"; import { SectionKeyProps } from "@/types/sections.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; @@ -40,12 +39,6 @@ export function Rush({ id }: SectionKeyProps) { })(); }, []); - const { handleClickShortCut, PopupComponent, ToastComponent } = useAuth({ - eventStartDate: startDateTime, - eventEndDate: endDateTime, - confirmUrl: "/rush", - }); - return (
@@ -97,9 +90,6 @@ export function Rush({ id }: SectionKeyProps) {
- - {PopupComponent} - {ToastComponent} ); } diff --git a/client/src/features/Rush/Extra/FAQ.tsx b/client/src/features/Rush/Common/FAQ.tsx similarity index 100% rename from client/src/features/Rush/Extra/FAQ.tsx rename to client/src/features/Rush/Common/FAQ.tsx diff --git a/client/src/features/Rush/Common/Headline.tsx b/client/src/features/Rush/Common/Headline.tsx new file mode 100644 index 00000000..eda51169 --- /dev/null +++ b/client/src/features/Rush/Common/Headline.tsx @@ -0,0 +1,67 @@ +import { useEffect, useState } from "react"; +import { motion } from "framer-motion"; +import { RushAPI } from "@/apis/rushAPI.ts"; +import CTAButton from "@/components/CTAButton"; +import Scroll from "@/components/Scroll"; +import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import { Background } from "@/features/RushGame/Background.tsx"; +import useAuth from "@/hooks/useAuth.ts"; +import { SectionKeyProps } from "@/types/sections.ts"; + +export function Headline({ id }: SectionKeyProps) { + const [startDateTime, setStartDateTime] = useState(""); + const [endDateTime, setEndDateTime] = useState(""); + + useEffect(() => { + (async () => { + const rushData = await RushAPI.getRush(); + setStartDateTime(rushData.eventStartDate); + setEndDateTime(rushData.eventEndDate); + })(); + }, []); + + const { handleClickShortCut, PopupComponent, ToastComponent } = useAuth({ + eventStartDate: startDateTime, + eventEndDate: endDateTime, + confirmUrl: "/rush/game", + }); + + return ( +
+ + +

Event 2. 선착순 이벤트

+

+ 캐스퍼 일렉트릭 선착순 밸런스 게임 +
+ 참여하고 선물 받아가세요! +

+
+ + + + +
+ + + +

스크롤

+

하고 캐스퍼 일렉트릭의 놀라운 성능을 알아보세요

+
+
+ + {PopupComponent} + {ToastComponent} +
+ ); +} diff --git a/client/src/features/Rush/Extra/Intro.tsx b/client/src/features/Rush/Common/Intro.tsx similarity index 100% rename from client/src/features/Rush/Extra/Intro.tsx rename to client/src/features/Rush/Common/Intro.tsx diff --git a/client/src/features/Rush/index.tsx b/client/src/features/Rush/index.tsx index 3cade298..972f92fb 100644 --- a/client/src/features/Rush/index.tsx +++ b/client/src/features/Rush/index.tsx @@ -5,9 +5,9 @@ export { CasperSmartKey } from "./Casper/CasperSmartKey.tsx"; export { CasperWide } from "./Casper/CasperWide.tsx"; export { ElectricAdvantage } from "./Electric/ElectricAdvantage.tsx"; export { ElectricReason } from "./Electric/ElectricReason.tsx"; -export { FAQ } from "./Extra/FAQ.tsx"; -export { Intro } from "./Extra/Intro.tsx"; +export { FAQ } from "./Common/FAQ.tsx"; +export { Intro } from "./Common/Intro.tsx"; export { ReasonFirst } from "./Reason/ReasonFirst.tsx"; export { ReasonSecond } from "./Reason/ReasonSecond.tsx"; export { CasperCharge } from "./Casper/CasperCharge.tsx"; -export { RushGame } from "./RushGame/RushGame.tsx"; +export { Headline } from "./Common/Headline.tsx"; diff --git a/client/src/features/Rush/RushGame/Background.tsx b/client/src/features/RushGame/Background.tsx similarity index 86% rename from client/src/features/Rush/RushGame/Background.tsx rename to client/src/features/RushGame/Background.tsx index 769e7eca..ac662f74 100644 --- a/client/src/features/Rush/RushGame/Background.tsx +++ b/client/src/features/RushGame/Background.tsx @@ -15,7 +15,9 @@ export function Background({ children }: PropsWithChildren) {
- {children} +
+ {children} +
); } diff --git a/client/src/features/Rush/RushGame/RushGameCard/RushCard.tsx b/client/src/features/RushGame/RushGameCard/RushCard.tsx similarity index 100% rename from client/src/features/Rush/RushGame/RushGameCard/RushCard.tsx rename to client/src/features/RushGame/RushGameCard/RushCard.tsx diff --git a/client/src/features/Rush/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx similarity index 96% rename from client/src/features/Rush/RushGame/RushGameCard/RushCardComparison.tsx rename to client/src/features/RushGame/RushGameCard/RushCardComparison.tsx index 03cf3b16..a1e86f77 100644 --- a/client/src/features/Rush/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx @@ -2,7 +2,7 @@ import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; -import RushCard from "@/features/Rush/RushGame/RushGameCard/RushCard.tsx"; +import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; export default function RushCardComparison() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); diff --git a/client/src/features/Rush/RushGame/RushGameCard/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx similarity index 100% rename from client/src/features/Rush/RushGame/RushGameCard/RushCardCurrentRatio.tsx rename to client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx diff --git a/client/src/features/Rush/RushGame/RushGameCard/RushCardResultDescription.tsx b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx similarity index 100% rename from client/src/features/Rush/RushGame/RushGameCard/RushCardResultDescription.tsx rename to client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx diff --git a/client/src/features/Rush/RushGame/RushGameCard/RushCountDown.tsx b/client/src/features/RushGame/RushGameCard/RushCountDown.tsx similarity index 100% rename from client/src/features/Rush/RushGame/RushGameCard/RushCountDown.tsx rename to client/src/features/RushGame/RushGameCard/RushCountDown.tsx diff --git a/client/src/features/Rush/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSection/CardOptions.tsx similarity index 87% rename from client/src/features/Rush/RushGame/RushGameSection/CardOptions.tsx rename to client/src/features/RushGame/RushGameSection/CardOptions.tsx index bf36da69..bd4e43a2 100644 --- a/client/src/features/Rush/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSection/CardOptions.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushCardComparison from "@/features/Rush/RushGame/RushGameCard/RushCardComparison.tsx"; -import RushCountDown from "@/features/Rush/RushGame/RushGameCard/RushCountDown.tsx"; +import RushCardComparison from "@/features/RushGame/RushGameCard/RushCardComparison.tsx"; +import RushCountDown from "@/features/RushGame/RushGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; export default function CardOptions() { diff --git a/client/src/features/Rush/RushGame/RushGameSection/CountDown.tsx b/client/src/features/RushGame/RushGameSection/CountDown.tsx similarity index 83% rename from client/src/features/Rush/RushGame/RushGameSection/CountDown.tsx rename to client/src/features/RushGame/RushGameSection/CountDown.tsx index c5cbf061..f80cd300 100644 --- a/client/src/features/Rush/RushGame/RushGameSection/CountDown.tsx +++ b/client/src/features/RushGame/RushGameSection/CountDown.tsx @@ -1,6 +1,6 @@ import { motion } from "framer-motion"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { Background } from "@/features/Rush/RushGame/Background.tsx"; +import { Background } from "@/features/RushGame/Background.tsx"; interface CountDownProps { countdown: number; @@ -14,7 +14,7 @@ function CountDownTimer({ countdown }: CountDownProps) { const formatTime = (time: number) => time.toString().padStart(2, "0"); return ( -
+

밸런스 게임 주제 공개까지 남은 시간

@@ -25,7 +25,7 @@ function CountDownTimer({ countdown }: CountDownProps) {

:

-
+ ); } @@ -44,9 +44,7 @@ export default function CountDown({ countdown }: CountDownProps) { 이제 곧 하단에 밸런스 게임 주제가 공개돼요! - - - + ); } diff --git a/client/src/features/Rush/RushGame/RushGameSection/FinalResult.tsx b/client/src/features/RushGame/RushGameSection/FinalResult.tsx similarity index 100% rename from client/src/features/Rush/RushGame/RushGameSection/FinalResult.tsx rename to client/src/features/RushGame/RushGameSection/FinalResult.tsx diff --git a/client/src/features/Rush/RushGame/RushGameSection/SelectedCard.tsx b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx similarity index 90% rename from client/src/features/Rush/RushGame/RushGameSection/SelectedCard.tsx rename to client/src/features/RushGame/RushGameSection/SelectedCard.tsx index 2f9881fc..f0b7d999 100644 --- a/client/src/features/Rush/RushGame/RushGameSection/SelectedCard.tsx +++ b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx @@ -2,9 +2,9 @@ import { useState } from "react"; import { motion } from "framer-motion"; import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushCardCurrentRatio from "@/features/Rush/RushGame/RushGameCard/RushCardCurrentRatio.tsx"; -import RushCardResultDescription from "@/features/Rush/RushGame/RushGameCard/RushCardResultDescription.tsx"; -import RushCountDown from "@/features/Rush/RushGame/RushGameCard/RushCountDown.tsx"; +import RushCardCurrentRatio from "@/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx"; +import RushCardResultDescription from "@/features/RushGame/RushGameCard/RushCardResultDescription.tsx"; +import RushCountDown from "@/features/RushGame/RushGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; diff --git a/client/src/pages/Rush/index.tsx b/client/src/pages/Rush/index.tsx index bbae8192..43db10e0 100644 --- a/client/src/pages/Rush/index.tsx +++ b/client/src/pages/Rush/index.tsx @@ -1,7 +1,6 @@ import Footer from "@/components/Footer"; import Notice from "@/components/Notice"; import { RUSH_SECTIONS } from "@/constants/PageSections/sections.ts"; -import { RushGameProvider } from "@/contexts/rushGameContext.tsx"; import { CasperCharge, CasperComfortable, @@ -12,10 +11,10 @@ import { ElectricAdvantage, ElectricReason, FAQ, + Headline, Intro, ReasonFirst, ReasonSecond, - RushGame, } from "@/features/Rush"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; import useScrollTop from "@/hooks/useScrollTop.tsx"; @@ -28,9 +27,7 @@ export default function Rush() { return (
- - - + diff --git a/client/src/features/Rush/RushGame/RushGame.tsx b/client/src/pages/RushGame/index.tsx similarity index 85% rename from client/src/features/Rush/RushGame/RushGame.tsx rename to client/src/pages/RushGame/index.tsx index 6f9e968b..33efe163 100644 --- a/client/src/features/Rush/RushGame/RushGame.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -6,15 +6,14 @@ import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import CardOptions from "@/features/Rush/RushGame/RushGameSection/CardOptions.tsx"; -import CountDown from "@/features/Rush/RushGame/RushGameSection/CountDown.tsx"; -import FinalResult from "@/features/Rush/RushGame/RushGameSection/FinalResult.tsx"; -import SelectedCard from "@/features/Rush/RushGame/RushGameSection/SelectedCard.tsx"; +import CardOptions from "@/features/RushGame/RushGameSection/CardOptions.tsx"; +import CountDown from "@/features/RushGame/RushGameSection/CountDown.tsx"; +import FinalResult from "@/features/RushGame/RushGameSection/FinalResult.tsx"; +import SelectedCard from "@/features/RushGame/RushGameSection/SelectedCard.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; -import { SectionKeyProps } from "@/types/sections.ts"; -export function RushGame({ id }: SectionKeyProps) { +export default function RushGame() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const { gameState, setGameState, updateUserParticipationStatus } = useRushGameContext(); const [initialCountdown, setInitialCountdown] = useState(null); @@ -72,10 +71,7 @@ export function RushGame({ id }: SectionKeyProps) { }; return ( -
+
{renderRushGameContent()} , + children: [ + { + index: true, + element: , + }, + { + path: "game", + element: ( + + + + ), + }, + ], }, { path: "lottery/", From e3054b833cf2f08ab966aee0d9d5bd7c2a1fb8df Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 16:52:54 +0900 Subject: [PATCH 069/111] =?UTF-8?q?fix:=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=B4=88=EA=B9=83=EA=B0=92=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=95=88=EB=90=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useCountDown.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/client/src/hooks/useCountDown.ts b/client/src/hooks/useCountDown.ts index c4cae111..1e1cffe3 100644 --- a/client/src/hooks/useCountDown.ts +++ b/client/src/hooks/useCountDown.ts @@ -3,17 +3,15 @@ import { useEffect, useState } from "react"; export default function useCountDown(initialTime: number) { const [time, setTime] = useState(initialTime); + useEffect(() => { + setTime(initialTime); + }, [initialTime]); + useEffect(() => { if (time < 0) return; const timer = setInterval(() => { - setTime((prevTime) => { - if (prevTime < 0) { - clearInterval(timer); - return 0; - } - return prevTime - 1; - }); + if (time >= 0) setTime((prevTime) => prevTime - 1); }, 1000); return () => clearInterval(timer); From 941ea23057e6df2b6ab708de798a9201317a8bcd Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 17:19:15 +0900 Subject: [PATCH 070/111] =?UTF-8?q?feat:=20useTimer=20=ED=9B=85=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20Scroll=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20type=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/Common/Headline.tsx | 2 +- .../RushGame/RushGameCard/RushCardCurrentRatio.tsx | 13 +++---------- .../RushGame/RushGameSection/CardOptions.tsx | 14 +++----------- client/src/hooks/useTimer.ts | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 22 deletions(-) create mode 100644 client/src/hooks/useTimer.ts diff --git a/client/src/features/Rush/Common/Headline.tsx b/client/src/features/Rush/Common/Headline.tsx index eda51169..782dadff 100644 --- a/client/src/features/Rush/Common/Headline.tsx +++ b/client/src/features/Rush/Common/Headline.tsx @@ -54,7 +54,7 @@ export function Headline({ id }: SectionKeyProps) { - +

스크롤

하고 캐스퍼 일렉트릭의 놀라운 성능을 알아보세요

diff --git a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx index 9e9e216b..82f5ef56 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx @@ -4,6 +4,7 @@ import { RushAPI } from "@/apis/rushAPI.ts"; import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; +import useTimer from "@/hooks/useTimer.ts"; import Reload from "/public/assets/icons/reload.svg?react"; const TOOLTIP_CONTENT = () => ( @@ -29,11 +30,11 @@ function ReloadButton({ onClick }: { onClick: () => void }) { export default function RushCardCurrentRatio() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const [showToggle, setShowToggle] = useState(true); const [leftOptionRatio, setLeftOptionRatio] = useState(0); const [rightOptionRatio, setRightOptionRatio] = useState(0); const [message, setMessage] = useState(MESSAGES.WINNING); const [optionId, setOptionId] = useState(null); + const { toggleContents } = useTimer(); const fetchRushBalance = async () => { try { @@ -63,14 +64,6 @@ export default function RushCardCurrentRatio() { fetchRushBalance(); }, []); - useEffect(() => { - const timer = setTimeout(() => { - setShowToggle(false); - }, 5000); - - return () => clearTimeout(timer); - }, []); - return (
@@ -101,7 +94,7 @@ export default function RushCardCurrentRatio() {
- {showToggle ? ( + {toggleContents ? ( diff --git a/client/src/features/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSection/CardOptions.tsx index bd4e43a2..18d34293 100644 --- a/client/src/features/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSection/CardOptions.tsx @@ -1,28 +1,20 @@ -import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import RushCardComparison from "@/features/RushGame/RushGameCard/RushCardComparison.tsx"; import RushCountDown from "@/features/RushGame/RushGameCard/RushCountDown.tsx"; import useCountDown from "@/hooks/useCountDown.ts"; +import useTimer from "@/hooks/useTimer.ts"; export default function CardOptions() { const countdown = useCountDown(50); - const [showCountdown, setShowCountdown] = useState(false); - - useEffect(() => { - const timer = setTimeout(() => { - setShowCountdown(true); - }, 5000); - - return () => clearTimeout(timer); - }, []); + const { toggleContents } = useTimer(); return ( - {!showCountdown ? ( + {toggleContents ? ( { + const timer = setTimeout(() => { + setToggleContents((prev) => !prev); + }, duration); + + return () => clearTimeout(timer); + }, [duration]); + return { toggleContents, setToggleContents }; +} From ed517dc45930299a0b306cf6849878f9fbd8e01e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 17:31:59 +0900 Subject: [PATCH 071/111] =?UTF-8?q?refactor:=20Background=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=8F=B4=EB=8D=94=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RushGame/Background.tsx => components/Background/index.tsx} | 0 client/src/features/Rush/Common/Headline.tsx | 2 +- client/src/features/RushGame/RushGameSection/CountDown.tsx | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename client/src/{features/RushGame/Background.tsx => components/Background/index.tsx} (100%) diff --git a/client/src/features/RushGame/Background.tsx b/client/src/components/Background/index.tsx similarity index 100% rename from client/src/features/RushGame/Background.tsx rename to client/src/components/Background/index.tsx diff --git a/client/src/features/Rush/Common/Headline.tsx b/client/src/features/Rush/Common/Headline.tsx index 782dadff..97e9bc9e 100644 --- a/client/src/features/Rush/Common/Headline.tsx +++ b/client/src/features/Rush/Common/Headline.tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { RushAPI } from "@/apis/rushAPI.ts"; +import { Background } from "@/components/Background"; import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { Background } from "@/features/RushGame/Background.tsx"; import useAuth from "@/hooks/useAuth.ts"; import { SectionKeyProps } from "@/types/sections.ts"; diff --git a/client/src/features/RushGame/RushGameSection/CountDown.tsx b/client/src/features/RushGame/RushGameSection/CountDown.tsx index f80cd300..13243087 100644 --- a/client/src/features/RushGame/RushGameSection/CountDown.tsx +++ b/client/src/features/RushGame/RushGameSection/CountDown.tsx @@ -1,6 +1,6 @@ import { motion } from "framer-motion"; +import { Background } from "@/components/Background"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { Background } from "@/features/RushGame/Background.tsx"; interface CountDownProps { countdown: number; From e7f89afbc7a680e5a0eb863fe8e668e95bfb02da Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 19:10:30 +0900 Subject: [PATCH 072/111] =?UTF-8?q?feat:=20Countdown=20=ED=91=9C=EA=B8=B0?= =?UTF-8?q?=EB=B2=95=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EB=B0=B8=EB=9F=B0?= =?UTF-8?q?=EC=8A=A4=20=EA=B2=8C=EC=9E=84=20=EC=A7=84=ED=96=89=20=EC=B9=B4?= =?UTF-8?q?=EC=9A=B4=ED=8A=B8=EB=8B=A4=EC=9A=B4=20Props=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{RushCountDown.tsx => RushCountdown.tsx} | 4 +- .../RushGame/RushGameSection/CardOptions.tsx | 12 +++--- .../{CountDown.tsx => Countdown.tsx} | 8 ++-- .../RushGame/RushGameSection/SelectedCard.tsx | 16 ++++---- .../{useCountDown.ts => useCountdown.ts} | 2 +- client/src/pages/RushGame/index.tsx | 38 +++++++++++++------ client/src/router.tsx | 2 + 7 files changed, 51 insertions(+), 31 deletions(-) rename client/src/features/RushGame/RushGameCard/{RushCountDown.tsx => RushCountdown.tsx} (92%) rename client/src/features/RushGame/RushGameSection/{CountDown.tsx => Countdown.tsx} (89%) rename client/src/hooks/{useCountDown.ts => useCountdown.ts} (87%) diff --git a/client/src/features/RushGame/RushGameCard/RushCountDown.tsx b/client/src/features/RushGame/RushGameCard/RushCountdown.tsx similarity index 92% rename from client/src/features/RushGame/RushGameCard/RushCountDown.tsx rename to client/src/features/RushGame/RushGameCard/RushCountdown.tsx index 4051399d..6717c360 100644 --- a/client/src/features/RushGame/RushGameCard/RushCountDown.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCountdown.tsx @@ -1,4 +1,4 @@ -interface RushCountDownProps { +interface RushCountdownProps { countdown: number; } @@ -11,7 +11,7 @@ function TimeDisplay({ label, value }: { label: string; value: string }) { ); } -export default function RushCountDown({ countdown }: RushCountDownProps) { +export default function RushCountdown({ countdown }: RushCountdownProps) { const minutes = Math.floor((countdown % 3600) / 60); const seconds = countdown % 60; diff --git a/client/src/features/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSection/CardOptions.tsx index 18d34293..12c23a1e 100644 --- a/client/src/features/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSection/CardOptions.tsx @@ -1,12 +1,14 @@ import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import RushCardComparison from "@/features/RushGame/RushGameCard/RushCardComparison.tsx"; -import RushCountDown from "@/features/RushGame/RushGameCard/RushCountDown.tsx"; -import useCountDown from "@/hooks/useCountDown.ts"; +import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; import useTimer from "@/hooks/useTimer.ts"; -export default function CardOptions() { - const countdown = useCountDown(50); +interface CardOptionsProps { + countdown: number; +} + +export default function CardOptions({ countdown }: CardOptionsProps) { const { toggleContents } = useTimer(); return ( @@ -23,7 +25,7 @@ export default function CardOptions() { ) : ( - + )} diff --git a/client/src/features/RushGame/RushGameSection/CountDown.tsx b/client/src/features/RushGame/RushGameSection/Countdown.tsx similarity index 89% rename from client/src/features/RushGame/RushGameSection/CountDown.tsx rename to client/src/features/RushGame/RushGameSection/Countdown.tsx index 13243087..da1477f4 100644 --- a/client/src/features/RushGame/RushGameSection/CountDown.tsx +++ b/client/src/features/RushGame/RushGameSection/Countdown.tsx @@ -2,11 +2,11 @@ import { motion } from "framer-motion"; import { Background } from "@/components/Background"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -interface CountDownProps { +interface CountdownProps { countdown: number; } -function CountDownTimer({ countdown }: CountDownProps) { +function CountdownTimer({ countdown }: CountdownProps) { const hours = Math.floor(countdown / 3600); const minutes = Math.floor((countdown % 3600) / 60); const seconds = countdown % 60; @@ -38,13 +38,13 @@ function TimeDisplay({ label, value }: { label: string; value: string }) { ); } -export default function CountDown({ countdown }: CountDownProps) { +export default function Countdown({ countdown }: CountdownProps) { return ( <> 이제 곧 하단에 밸런스 게임 주제가 공개돼요! - + ); } diff --git a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx index f0b7d999..abd6fbc8 100644 --- a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx +++ b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx @@ -4,16 +4,19 @@ import { CARD_COLOR, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import RushCardCurrentRatio from "@/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx"; import RushCardResultDescription from "@/features/RushGame/RushGameCard/RushCardResultDescription.tsx"; -import RushCountDown from "@/features/RushGame/RushGameCard/RushCountDown.tsx"; -import useCountDown from "@/hooks/useCountDown.ts"; +import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; interface SelectedCardProps { + countdown: number; +} + +interface SelectedCardChangeProps { onClick: () => void; } -function SelectedCardDescription({ onClick }: SelectedCardProps) { +function SelectedCardDescription({ onClick }: SelectedCardChangeProps) { return ( @@ -55,9 +58,8 @@ function SelectedCardCurrentRatio({ onClick }: SelectedCardProps) { ); } -export default function SelectedCard() { +export default function SelectedCard({ countdown }: SelectedCardProps) { const [isDescriptionVisible, setIsDescriptionVisible] = useState(true); - const countdown = useCountDown(5); const handleChangeCardResult = () => { setIsDescriptionVisible((prev) => !prev); @@ -68,7 +70,7 @@ export default function SelectedCard() { className="flex flex-col gap-3 justify-center items-center pt-14" {...SCROLL_MOTION(ASCEND)} > - + {isDescriptionVisible ? ( ) : ( diff --git a/client/src/hooks/useCountDown.ts b/client/src/hooks/useCountdown.ts similarity index 87% rename from client/src/hooks/useCountDown.ts rename to client/src/hooks/useCountdown.ts index 1e1cffe3..d56e0494 100644 --- a/client/src/hooks/useCountDown.ts +++ b/client/src/hooks/useCountdown.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -export default function useCountDown(initialTime: number) { +export default function useCountdown(initialTime: number) { const [time, setTime] = useState(initialTime); useEffect(() => { diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 33efe163..46cfe41a 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -1,22 +1,28 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { useCookies } from "react-cookie"; +import { useLoaderData } from "react-router-dom"; import { RushAPI } from "@/apis/rushAPI.ts"; import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import CardOptions from "@/features/RushGame/RushGameSection/CardOptions.tsx"; -import CountDown from "@/features/RushGame/RushGameSection/CountDown.tsx"; +import Countdown from "@/features/RushGame/RushGameSection/Countdown.tsx"; import FinalResult from "@/features/RushGame/RushGameSection/FinalResult.tsx"; import SelectedCard from "@/features/RushGame/RushGameSection/SelectedCard.tsx"; -import useCountDown from "@/hooks/useCountDown.ts"; +import useCountdown from "@/hooks/useCountdown.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; +import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; export default function RushGame() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const { gameState, setGameState, updateUserParticipationStatus } = useRushGameContext(); - const [initialCountdown, setInitialCountdown] = useState(null); + const [initialPreCountdown, setInitialPreCountdown] = useState(null); + const [initialRunCountdown, setInitialRunCountdown] = useState(null); + + // TODO: loader 사용으로 바꾸기 + // const data = useLoaderData() as GetTotalRushEventsResponse; useEffect(() => { (async () => { @@ -29,8 +35,13 @@ export default function RushGame() { if (rushData.serverTime && currentEvent?.startDateTime) { const serverTime = new Date(rushData.serverTime).getTime(); const startTime = new Date(currentEvent.startDateTime).getTime(); - const countdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); - setInitialCountdown(countdown); + const endTime = new Date(currentEvent.endDateTime).getTime(); + + const preCountdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); + const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); + + setInitialPreCountdown(preCountdown); + setInitialRunCountdown(runCountdown); } const userParticipated = await RushAPI.getRushUserParticipationStatus( @@ -43,25 +54,28 @@ export default function RushGame() { })(); }, []); - const countdown = useCountDown(initialCountdown || 0); + // const preCountdown = useCountdown(initialPreCountdown || 0); + // const runCountdown = useCountdown(initialRunCountdown || 0); + const preCountdown = useCountdown(3 || 0); + const runCountdown = useCountdown(3 || 0); useEffect(() => { - if (countdown < 0 && gameState.phase === "PRE_EVENT") { + if (preCountdown < 0 && gameState.phase === "PRE_EVENT") { setGameState((prev) => ({ ...prev, phase: "EVENT_RUNNING" })); } - }, [countdown, gameState.phase, setGameState]); + }, [preCountdown, gameState.phase, setGameState]); const renderRushGameContent = () => { switch (gameState.phase) { case "PRE_EVENT": - return ; + return ; case "EVENT_RUNNING": if (!gameState.userParticipated) { - return ; - // return ; + // return ; + return ; // return ; } else { - return ; + return ; } case "EVENT_ENDED": return ; diff --git a/client/src/router.tsx b/client/src/router.tsx index d72d52ca..9d03f1bd 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,4 +1,5 @@ import { createBrowserRouter } from "react-router-dom"; +import { RushAPI } from "@/apis/rushAPI.ts"; import { RushGameProvider } from "@/contexts/rushGameContext.tsx"; import { LotteryAPI } from "./apis/lotteryAPI"; import Layout from "./components/Layout"; @@ -32,6 +33,7 @@ export const router = createBrowserRouter([ ), + loader: RushAPI.getRush, }, ], }, From 610a73e5c4dcdbf7387d2d59d6f449bc4e869b08 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 20:31:14 +0900 Subject: [PATCH 073/111] =?UTF-8?q?design:=20RushCard=20=ED=98=B8=EB=B2=84?= =?UTF-8?q?=20=EC=8B=9C=20CSS=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/RushGame/RushGameCard/RushCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/features/RushGame/RushGameCard/RushCard.tsx b/client/src/features/RushGame/RushGameCard/RushCard.tsx index 9081632e..5fce09fb 100644 --- a/client/src/features/RushGame/RushGameCard/RushCard.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCard.tsx @@ -9,7 +9,7 @@ interface RushCardProps { } const backgroundGradients = cva( - `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800 p-10 break-keep cursor-pointer`, + `flex flex-col gap-2 justify-center items-center w-[360px] h-[400px] text-n-neutral-950 rounded-800 p-10 break-keep cursor-pointer hover:scale-[1.05] hover:duration-200`, { variants: { color: { From 396fd17a459fef6a5a9eaf8cebb722ae76a04605 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 20:54:47 +0900 Subject: [PATCH 074/111] =?UTF-8?q?feat:=20RushCard=20API=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RushGameCard/RushCardComparison.tsx | 30 ++++++++++++++----- client/src/pages/RushGame/index.tsx | 4 +-- client/src/types/rushApi.ts | 4 +-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx index a1e86f77..9f7cc23c 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx @@ -1,21 +1,37 @@ +import { useEffect, useState } from "react"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; +import { GetTodayRushEventResponse } from "@/types/rushApi.ts"; export default function RushCardComparison() { + const [todayRushEventData, setTodayRushEventData] = useState(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; + useEffect(() => { + (async () => { + try { + const todayRushEventData = await RushAPI.getTodayRushEvent( + cookies[COOKIE_TOKEN_KEY] + ); + setTodayRushEventData(todayRushEventData); + } catch (error) { + console.error("Error:", error); + } + })(); + }, []); + + // TODO: 카드 색상 랜덤 + const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; const leftOptionColor = CARD_COLORS[currentDay][CARD_TYPE.LEFT_OPTIONS]; const rightOptionColor = CARD_COLORS[currentDay][CARD_TYPE.RIGHT_OPTIONS]; - const leftOptionTitle = CARD_OPTIONS[currentDay][CARD_TYPE.LEFT_OPTIONS].title; - const rightOptionTitle = CARD_OPTIONS[currentDay][CARD_TYPE.RIGHT_OPTIONS].title; - - const leftOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.LEFT_OPTIONS].description; - const rightOptionDescription = CARD_OPTIONS[currentDay][CARD_TYPE.RIGHT_OPTIONS].description; + const { + leftOption: { mainText: leftOptionTitle = "", subText: leftOptionDescription = "" } = {}, + rightOption: { mainText: rightOptionTitle = "", subText: rightOptionDescription = "" } = {}, + } = todayRushEventData || {}; const handleCardSelection = async (optionId: number) => { try { diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 46cfe41a..9c091769 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -71,8 +71,8 @@ export default function RushGame() { return ; case "EVENT_RUNNING": if (!gameState.userParticipated) { - // return ; - return ; + return ; + // return ; // return ; } else { return ; diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts index a05c9a6a..2f069250 100644 --- a/client/src/types/rushApi.ts +++ b/client/src/types/rushApi.ts @@ -5,8 +5,8 @@ interface RushEventType { } interface RushCardType { - title: string; - description: string; + mainText: string; + subText: string; } export interface GetTotalRushEventsResponse { From 453ae16e983036497b360f95e04f087ab151cfe2 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Mon, 12 Aug 2024 21:15:24 +0900 Subject: [PATCH 075/111] =?UTF-8?q?feat:=20RushCardComparison=20API=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.ts | 106 +++++++++--------- .../RushGame/RushGameCard/RushCard.tsx | 10 +- .../RushGameCard/RushCardComparison.tsx | 33 ++++-- .../RushCardResultDescription.tsx | 12 +- 4 files changed, 85 insertions(+), 76 deletions(-) diff --git a/client/src/constants/Rush/rushCard.ts b/client/src/constants/Rush/rushCard.ts index b1112b5a..be6e0b33 100644 --- a/client/src/constants/Rush/rushCard.ts +++ b/client/src/constants/Rush/rushCard.ts @@ -53,143 +53,141 @@ export const CARD_COLORS: { export const CARD_OPTIONS: { [key: number]: { - [CARD_TYPE.LEFT_OPTIONS]: { title: string; description: string }; - [CARD_TYPE.RIGHT_OPTIONS]: { title: string; description: string }; + [CARD_TYPE.LEFT_OPTIONS]: { mainText: string; subText: string }; + [CARD_TYPE.RIGHT_OPTIONS]: { mainText: string; subText: string }; }; } = { [CARD_DAYS.DAY1]: { [CARD_TYPE.LEFT_OPTIONS]: { - title: "첫 차는 저렴해야 한다", - description: "가성비 좋게 저렴한 차로 시작해서 차근히 업그레이드하고 싶어", + mainText: "첫 차는 저렴해야 한다", + subText: "가성비 좋게 저렴한 차로 시작해서 차근히 업그레이드하고 싶어", }, [CARD_TYPE.RIGHT_OPTIONS]: { - title: "첫 차는 안전해야 한다", - description: "처음 사는 차인 만큼 안전한 차를 사서 오래 타고 싶어", + mainText: "첫 차는 안전해야 한다", + subText: "처음 사는 차인 만큼 안전한 차를 사서 오래 타고 싶어", }, }, [CARD_DAYS.DAY2]: { [CARD_TYPE.LEFT_OPTIONS]: { - title: "온라인 쇼핑이 편해서 좋다", - description: "편한 게 최고야! 집에서 인터넷으로 쇼핑할래", + mainText: "온라인 쇼핑이 편해서 좋다", + subText: "편한 게 최고야! 집에서 인터넷으로 쇼핑할래", }, [CARD_TYPE.RIGHT_OPTIONS]: { - title: "오프라인 쇼핑이 확실해서 좋다", - description: "살 거면 제대로 보고 사야지! 직접 보고 나서 판단할래", + mainText: "오프라인 쇼핑이 확실해서 좋다", + subText: "살 거면 제대로 보고 사야지! 직접 보고 나서 판단할래", }, }, [CARD_DAYS.DAY3]: { [CARD_TYPE.LEFT_OPTIONS]: { - title: "텐트 치고 캠핑하기", - description: "캠핑은 텐트가 근본이지!", + mainText: "텐트 치고 캠핑하기", + subText: "캠핑은 텐트가 근본이지!", }, [CARD_TYPE.RIGHT_OPTIONS]: { - title: "차 안에서 차박하기", - description: "가벼운 짐으로 차에서 잠드는 낭만이 좋아", + mainText: "차 안에서 차박하기", + subText: "가벼운 짐으로 차에서 잠드는 낭만이 좋아", }, }, [CARD_DAYS.DAY4]: { [CARD_TYPE.LEFT_OPTIONS]: { - title: "평생 주차 무료로 하기", - description: "요즘 주차장은 너무 비싸 주차비 걱정은 그만 하고 싶어", + mainText: "평생 주차 무료로 하기", + subText: "요즘 주차장은 너무 비싸 주차비 걱정은 그만 하고 싶어", }, [CARD_TYPE.RIGHT_OPTIONS]: { - title: "평생 주유 무료로 하기", - description: "기름값이 너무 많이 올랐어 주유비가 많이 들어 고민이야", + mainText: "평생 주유 무료로 하기", + subText: "기름값이 너무 많이 올랐어 주유비가 많이 들어 고민이야", }, }, [CARD_DAYS.DAY5]: { [CARD_TYPE.LEFT_OPTIONS]: { - title: "무채색 차가 좋다", - description: "검은색, 흰색, 회색! 오래 타려면 무난한 게 최고야", + mainText: "무채색 차가 좋다", + subText: "검은색, 흰색, 회색! 오래 타려면 무난한 게 최고야", }, [CARD_TYPE.RIGHT_OPTIONS]: { - title: "컬러풀한 차가 좋다", - description: "무채색은 지루해! 내가 좋아하는 색으로 고를래", + mainText: "컬러풀한 차가 좋다", + subText: "무채색은 지루해! 내가 좋아하는 색으로 고를래", }, }, [CARD_DAYS.DAY6]: { [CARD_TYPE.LEFT_OPTIONS]: { - title: "주말에는 바다보러 가기", - description: "아까운 주말엔 국내여행이라도 다녀오고 싶어", + mainText: "주말에는 바다보러 가기", + subText: "아까운 주말엔 국내여행이라도 다녀오고 싶어", }, [CARD_TYPE.RIGHT_OPTIONS]: { - title: "주말에는 도심 드라이브", - description: "평일에 너무 피곤했으니 오랜만에 동네 드라이브나 할래", + mainText: "주말에는 도심 드라이브", + subText: "평일에 너무 피곤했으니 오랜만에 동네 드라이브나 할래", }, }, }; export const CARD_RESULTS: { [key: number]: { - [CARD_TYPE.LEFT_OPTIONS]: { result_title: string; result_description: string }; - [CARD_TYPE.RIGHT_OPTIONS]: { result_title: string; result_description: string }; + [CARD_TYPE.LEFT_OPTIONS]: { resultMainText: string; resultSubText: string }; + [CARD_TYPE.RIGHT_OPTIONS]: { resultMainText: string; resultSubText: string }; }; } = { [CARD_DAYS.DAY1]: { [CARD_TYPE.LEFT_OPTIONS]: { - result_title: "가성비 좋은 도심형 전기차", - result_description: + resultMainText: "가성비 좋은 도심형 전기차", + resultSubText: "캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 첫 차로 캐스퍼 일렉트릭 어떤가요?", }, [CARD_TYPE.RIGHT_OPTIONS]: { - result_title: "가성비 좋은 도심형 전기차", - result_description: + resultMainText: "가성비 좋은 도심형 전기차", + resultSubText: "캐스퍼는 작고 귀엽기만 하다고 생각했나요? 이젠 현대 스마트센스 안전옵션까지 지원해요", }, }, [CARD_DAYS.DAY2]: { [CARD_TYPE.LEFT_OPTIONS]: { - result_title: "현대 유일 온라인 예약", - result_description: + resultMainText: "현대 유일 온라인 예약", + resultSubText: "차 살때도 온라인 쇼핑을! 오직 온라인에서만 구매할 수 있는 캐스퍼 일렉트릭", }, [CARD_TYPE.RIGHT_OPTIONS]: { - result_title: "캐스퍼 스튜디오 송파", - result_description: - "캐스퍼 일렉트릭을 원하는 시간에 직접 만나볼 수 있는 무인 전시 스튜디오", + resultMainText: "캐스퍼 스튜디오 송파", + resultSubText: "캐스퍼 일렉트릭을 원하는 시간에 직접 만나볼 수 있는 무인 전시 스튜디오", }, }, [CARD_DAYS.DAY3]: { [CARD_TYPE.LEFT_OPTIONS]: { - result_title: "V2L로 캠핑 준비 끝", - result_description: + resultMainText: "V2L로 캠핑 준비 끝", + resultSubText: "캠핑장 전기 눈치싸움은 이제 그만! 차에서 직접 220V 전원을 연결할 수 있어요", }, [CARD_TYPE.RIGHT_OPTIONS]: { - result_title: "폴 폴딩으로 공간 활용", - result_description: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", + resultMainText: "폴 폴딩으로 공간 활용", + resultSubText: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", }, }, [CARD_DAYS.DAY4]: { [CARD_TYPE.LEFT_OPTIONS]: { - result_title: "전기차는 주차비 혜택 받아요", - result_description: "공영주차장 50% 할인 정책으로 주차비 부담을 덜 수 있어요", + resultMainText: "전기차는 주차비 혜택 받아요", + resultSubText: "공영주차장 50% 할인 정책으로 주차비 부담을 덜 수 있어요", }, [CARD_TYPE.RIGHT_OPTIONS]: { - result_title: "전기차는 기름값 걱정 없어요", - result_description: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", + resultMainText: "전기차는 기름값 걱정 없어요", + resultSubText: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", }, }, [CARD_DAYS.DAY5]: { [CARD_TYPE.LEFT_OPTIONS]: { - result_title: "기본 색감도 다채롭게", - result_description: "무채색 컬러도 매트부터 메탈릭까지 다양한 질감으로 구성했어요", + resultMainText: "기본 색감도 다채롭게", + resultSubText: "무채색 컬러도 매트부터 메탈릭까지 다양한 질감으로 구성했어요", }, [CARD_TYPE.RIGHT_OPTIONS]: { - result_title: "신규 색상 5종 출시", - result_description: - "기존 캐스퍼 색상 라인업에 새로운 5종을 추가! 내 차의 개성을 뽐내봐요", + resultMainText: "신규 색상 5종 출시", + resultSubText: "기존 캐스퍼 색상 라인업에 새로운 5종을 추가! 내 차의 개성을 뽐내봐요", }, }, [CARD_DAYS.DAY6]: { [CARD_TYPE.LEFT_OPTIONS]: { - result_title: "충전 한 번에 315km", - result_description: + resultMainText: "충전 한 번에 315km", + resultSubText: "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", }, [CARD_TYPE.RIGHT_OPTIONS]: { - result_title: "충전 한 번에 315km", - result_description: + resultMainText: "충전 한 번에 315km", + resultSubText: "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", }, }, diff --git a/client/src/features/RushGame/RushGameCard/RushCard.tsx b/client/src/features/RushGame/RushGameCard/RushCard.tsx index 5fce09fb..b29a3d92 100644 --- a/client/src/features/RushGame/RushGameCard/RushCard.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCard.tsx @@ -3,8 +3,8 @@ import { CARD_COLOR } from "@/constants/Rush/rushCard.ts"; interface RushCardProps { color: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; - title: string; - description: string; + mainText: string; + subText: string; onClick?: () => void; } @@ -25,11 +25,11 @@ const backgroundGradients = cva( } ); -export default function RushCard({ color, title, description, onClick }: RushCardProps) { +export default function RushCard({ color, mainText, subText, onClick }: RushCardProps) { return (
-

{title}

-

{description}

+

{mainText}

+

{subText}

); } diff --git a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx index 9f7cc23c..0217c8ba 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx @@ -2,10 +2,12 @@ import { useEffect, useState } from "react"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; import { GetTodayRushEventResponse } from "@/types/rushApi.ts"; +const TEMP_CURRENT_DAY: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; + export default function RushCardComparison() { const [todayRushEventData, setTodayRushEventData] = useState(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); @@ -23,14 +25,23 @@ export default function RushCardComparison() { })(); }, []); - // TODO: 카드 색상 랜덤 - const currentDay: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY2; - const leftOptionColor = CARD_COLORS[currentDay][CARD_TYPE.LEFT_OPTIONS]; - const rightOptionColor = CARD_COLORS[currentDay][CARD_TYPE.RIGHT_OPTIONS]; + // TODO: 카드 색상 랜덤으로 변경 + const leftOptionColor = CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS]; + const rightOptionColor = CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS]; const { - leftOption: { mainText: leftOptionTitle = "", subText: leftOptionDescription = "" } = {}, - rightOption: { mainText: rightOptionTitle = "", subText: rightOptionDescription = "" } = {}, + leftOption: { + mainText: leftOptionMainText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS] + .mainText, + subText: leftOptionSubText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS] + .subText, + } = {}, + rightOption: { + mainText: rightOptionMainText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS] + .mainText, + subText: rightOptionSubText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS] + .subText, + } = {}, } = todayRushEventData || {}; const handleCardSelection = async (optionId: number) => { @@ -45,8 +56,8 @@ export default function RushCardComparison() {
handleCardSelection(CARD_TYPE.LEFT_OPTIONS)} />

@@ -54,8 +65,8 @@ export default function RushCardComparison() {

handleCardSelection(CARD_TYPE.RIGHT_OPTIONS)} />
diff --git a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx index c274054b..3dc2faee 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx @@ -33,16 +33,16 @@ export default function RushCardResultDescription({ day, cardType, }: RushCardDescriptionProps) { - const mainTitle = CARD_OPTIONS[day][cardType].title; - const title = CARD_RESULTS[day][cardType].result_title; - const description = CARD_RESULTS[day][cardType].result_description; + const mainText = CARD_OPTIONS[day][cardType].mainText; + const resultMainText = CARD_RESULTS[day][cardType].resultMainText; + const resultSubText = CARD_RESULTS[day][cardType].resultSubText; return (
당신의 선택

- {mainTitle} + {mainText}

지금

@@ -52,8 +52,8 @@ export default function RushCardResultDescription({

CASPER Electric

-

{title}

-

{description}

+

{resultMainText}

+

{resultSubText}

); From 97f59486a658eee16cc0f5473b44997cf6eafc5a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 02:22:01 +0900 Subject: [PATCH 076/111] =?UTF-8?q?feat:=20RushCard=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=20=EC=8B=9C=20POST=20=ED=9B=84=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=20=EC=B0=B8=EC=97=AC=20=EC=97=AC=EB=B6=80=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=20=EB=B0=8F=20POST=20=ED=83=80=EC=9E=85=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 8 +++-- .../RushGameCard/RushCardComparison.tsx | 32 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index b9f1ccd4..e5fa3006 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -60,9 +60,13 @@ export const RushAPI = { const response = await fetch(`${baseURL}/options/${optionId}/apply`, { method: "POST", headers: { ...headers, Authorization: `Bearer ${token}` }, - body: JSON.stringify({}), }); - return response.json(); + + if (response.status === 204 || response.status === 404) { + return response.status; + } + + throw new Error(`Unexpected response status: ${response.status}`); } catch (error) { console.error("Error:", error); throw error; diff --git a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx index 0217c8ba..8d1f7c2d 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx @@ -2,8 +2,9 @@ import { useEffect, useState } from "react"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { CARD_COLORS, CARD_DAYS, CARD_OPTIONS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; +import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { GetTodayRushEventResponse } from "@/types/rushApi.ts"; const TEMP_CURRENT_DAY: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; @@ -11,6 +12,7 @@ const TEMP_CURRENT_DAY: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.D export default function RushCardComparison() { const [todayRushEventData, setTodayRushEventData] = useState(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); + const { setUserParticipationStatus } = useRushGameContext(); useEffect(() => { (async () => { @@ -30,23 +32,25 @@ export default function RushCardComparison() { const rightOptionColor = CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS]; const { - leftOption: { - mainText: leftOptionMainText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS] - .mainText, - subText: leftOptionSubText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS] - .subText, - } = {}, - rightOption: { - mainText: rightOptionMainText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS] - .mainText, - subText: rightOptionSubText = CARD_OPTIONS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS] - .subText, - } = {}, + leftOption: { mainText: leftOptionMainText = "", subText: leftOptionSubText = "" } = {}, + rightOption: { mainText: rightOptionMainText = "", subText: rightOptionSubText = "" } = {}, } = todayRushEventData || {}; const handleCardSelection = async (optionId: number) => { try { - await RushAPI.postSelectedRushOptionApply(cookies[COOKIE_TOKEN_KEY], optionId); + const response = await RushAPI.postSelectedRushOptionApply( + cookies[COOKIE_TOKEN_KEY], + optionId + ); + + if (response === 204) { + const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus( + cookies[COOKIE_TOKEN_KEY] + ); + setUserParticipationStatus(userParticipatedStatus); + } else if (response === 404) { + console.log(`Error ${response}`); + } } catch (error) { console.error("Error: ", error); } From 64e2d5ca471980cddeb7b82136a37d9ca6b85c96 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 02:23:15 +0900 Subject: [PATCH 077/111] =?UTF-8?q?fix:=20userParticipated=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=20=EC=95=88=EB=90=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95(API=20GET=20response=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 10 ++++------ client/src/pages/RushGame/index.tsx | 17 +++++++++++++---- client/src/types/rushApi.ts | 9 ++++----- client/src/types/rushGame.ts | 4 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 7c77345d..8de83e37 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -7,20 +7,18 @@ export const RushGameContext = createContext(un export const RushGameProvider = ({ children }: { children: ReactNode }) => { const [gameState, setGameState] = useState({ phase: "PRE_EVENT", - userParticipated: false, + userParticipatedStatus: false, }); - const updateUserParticipationStatus = (response: GetRushUserParticipationStatusResponse) => { + const setUserParticipationStatus = (status: GetRushUserParticipationStatusResponse) => { setGameState((prevState) => ({ ...prevState, - userParticipated: response.result, + userParticipatedStatus: status, })); }; return ( - + {children} ); diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 9c091769..371ef8ad 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -17,7 +17,7 @@ import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; export default function RushGame() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const { gameState, setGameState, updateUserParticipationStatus } = useRushGameContext(); + const { gameState, setGameState, setUserParticipationStatus } = useRushGameContext(); const [initialPreCountdown, setInitialPreCountdown] = useState(null); const [initialRunCountdown, setInitialRunCountdown] = useState(null); @@ -44,10 +44,10 @@ export default function RushGame() { setInitialRunCountdown(runCountdown); } - const userParticipated = await RushAPI.getRushUserParticipationStatus( + const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus( cookies[COOKIE_TOKEN_KEY] ); - updateUserParticipationStatus(userParticipated); + setUserParticipationStatus(userParticipatedStatus); } catch (error) { console.error("Error:", error); } @@ -65,12 +65,21 @@ export default function RushGame() { } }, [preCountdown, gameState.phase, setGameState]); + useEffect(() => { + if (gameState.userParticipatedStatus) { + setGameState((prev) => ({ + ...prev, + phase: "EVENT_RUNNING", + })); + } + }, [gameState.userParticipatedStatus, setGameState]); + const renderRushGameContent = () => { switch (gameState.phase) { case "PRE_EVENT": return ; case "EVENT_RUNNING": - if (!gameState.userParticipated) { + if (!gameState.userParticipatedStatus) { return ; // return ; // return ; diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts index 2f069250..51ef9c18 100644 --- a/client/src/types/rushApi.ts +++ b/client/src/types/rushApi.ts @@ -18,9 +18,7 @@ export interface GetTotalRushEventsResponse { events: RushEventType[]; } -export interface GetRushUserParticipationStatusResponse { - result: boolean; -} +export type GetRushUserParticipationStatusResponse = boolean; export interface GetTodayRushEventResponse { leftOption: RushCardType; @@ -30,8 +28,9 @@ export interface GetTodayRushEventResponse { export type PostSelectedRushCardOptionResponse = 204 | 404; export interface GetRushOptionResultResponse { - resultTitle: string; - resultDescription: string; + mainText: string; + resultMainText: string; + resultSubText: string; } export interface GetRushBalanceResponse { diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index 9b4bbcd3..ca6e1f6e 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -4,8 +4,8 @@ import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; export interface RushGameContextType { gameState: { phase: "PRE_EVENT" | "EVENT_RUNNING" | "EVENT_ENDED"; - userParticipated: boolean; + userParticipatedStatus: boolean; }; setGameState: React.Dispatch>; - updateUserParticipationStatus: (response: GetRushUserParticipationStatusResponse) => void; + setUserParticipationStatus: (status: GetRushUserParticipationStatusResponse) => void; } From 61bd174f849d1576daa5c62dae69ea3d3a5c06d2 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 10:23:23 +0900 Subject: [PATCH 078/111] =?UTF-8?q?feat:=20Rush=20test=20API=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 16 ++++++++++++++++ client/src/features/Main/Headline.tsx | 6 ++++++ client/src/pages/RushGame/index.tsx | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index e5fa3006..53a1e896 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -111,4 +111,20 @@ export const RushAPI = { throw error; } }, + async getRushTodayEventTest(token: string): Promise { + try { + const response = await fetch(`${baseURL}/today/test`, { + method: "GET", + headers: { ...headers, Authorization: `Bearer ${token}` }, + }); + if (response.status === 204 || response.status === 404) { + return response.status; + } + + throw new Error(`Unexpected response status: ${response.status}`); + } catch (error) { + console.error("Error:", error); + throw error; + } + }, }; diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index 58cf564c..08fb048c 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -1,18 +1,24 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; +import { useCookies } from "react-cookie"; +import { RushAPI } from "@/apis/rushAPI.ts"; import { TotalAPI } from "@/apis/totalAPI.ts"; import Keyword from "@/components/Keyword"; import Scroll from "@/components/Scroll"; +import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import { SectionKeyProps } from "@/types/sections.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; export function Headline({ id }: SectionKeyProps) { + const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const [startDateTime, setStartDateTime] = useState(null); const [endDateTime, setEndDateTime] = useState(null); useEffect(() => { (async () => { + // DATA RESET TEST API + await RushAPI.getRushTodayEventTest(cookies[COOKIE_TOKEN_KEY]); const totalData = await TotalAPI.getTotal(); setStartDateTime(totalData.totalEventStartDate); setEndDateTime(totalData.totalEventEndDate); diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 371ef8ad..83ff144c 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -56,6 +56,8 @@ export default function RushGame() { // const preCountdown = useCountdown(initialPreCountdown || 0); // const runCountdown = useCountdown(initialRunCountdown || 0); + + // TEST CODE const preCountdown = useCountdown(3 || 0); const runCountdown = useCountdown(3 || 0); @@ -81,8 +83,6 @@ export default function RushGame() { case "EVENT_RUNNING": if (!gameState.userParticipatedStatus) { return ; - // return ; - // return ; } else { return ; } From 561bf6f93c5af9012713624048f04fdd652957d9 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 12:05:20 +0900 Subject: [PATCH 079/111] =?UTF-8?q?feat:=20useToggleContents=20=ED=86=A0?= =?UTF-8?q?=EA=B8=80=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=ED=9B=85=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Main/Headline.tsx | 6 +++--- .../RushGameCard/RushCardCurrentRatio.tsx | 4 ++-- .../RushGame/RushGameSection/CardOptions.tsx | 4 ++-- .../RushGame/RushGameSection/SelectedCard.tsx | 21 ++++++------------- client/src/hooks/useTimer.ts | 14 ------------- client/src/hooks/useToggleContents.ts | 21 +++++++++++++++++++ 6 files changed, 34 insertions(+), 36 deletions(-) delete mode 100644 client/src/hooks/useTimer.ts create mode 100644 client/src/hooks/useToggleContents.ts diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index 08fb048c..a6588841 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -41,9 +41,9 @@ export function Headline({ id }: SectionKeyProps) { className="w-[667px] h-[300px] mt-10" />

- {startDateTime && endDateTime - ? formatEventDateRangeWithDot(startDateTime, endDateTime) - : ""} + {startDateTime && + endDateTime && + formatEventDateRangeWithDot(startDateTime, endDateTime)}

diff --git a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx index 82f5ef56..98a5d060 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx @@ -4,7 +4,7 @@ import { RushAPI } from "@/apis/rushAPI.ts"; import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import useTimer from "@/hooks/useTimer.ts"; +import useToggleContents from "@/hooks/useToggleContents.ts"; import Reload from "/public/assets/icons/reload.svg?react"; const TOOLTIP_CONTENT = () => ( @@ -34,7 +34,7 @@ export default function RushCardCurrentRatio() { const [rightOptionRatio, setRightOptionRatio] = useState(0); const [message, setMessage] = useState(MESSAGES.WINNING); const [optionId, setOptionId] = useState(null); - const { toggleContents } = useTimer(); + const { toggleContents } = useToggleContents(true, 5000); const fetchRushBalance = async () => { try { diff --git a/client/src/features/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSection/CardOptions.tsx index 12c23a1e..3552f352 100644 --- a/client/src/features/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSection/CardOptions.tsx @@ -2,14 +2,14 @@ import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import RushCardComparison from "@/features/RushGame/RushGameCard/RushCardComparison.tsx"; import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; -import useTimer from "@/hooks/useTimer.ts"; +import useToggleContents from "@/hooks/useToggleContents.ts"; interface CardOptionsProps { countdown: number; } export default function CardOptions({ countdown }: CardOptionsProps) { - const { toggleContents } = useTimer(); + const { toggleContents } = useToggleContents(true, 5000); return ( - +
From 6a9c6473f120e46fdf16a92847085b3d44055413 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 16:27:22 +0900 Subject: [PATCH 082/111] =?UTF-8?q?design:=20RushGame=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F?= =?UTF-8?q?=20padding=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/Common/Headline.tsx | 1 - .../features/RushGame/RushGameSection/CardOptions.tsx | 2 +- .../features/RushGame/RushGameSection/SelectedCard.tsx | 2 +- client/src/pages/RushGame/index.tsx | 9 +-------- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/client/src/features/Rush/Common/Headline.tsx b/client/src/features/Rush/Common/Headline.tsx index 6404b696..281d0101 100644 --- a/client/src/features/Rush/Common/Headline.tsx +++ b/client/src/features/Rush/Common/Headline.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { RushAPI } from "@/apis/rushAPI.ts"; -import { Background } from "@/components/Background"; import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; diff --git a/client/src/features/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSection/CardOptions.tsx index 3552f352..6d22fc3b 100644 --- a/client/src/features/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSection/CardOptions.tsx @@ -13,7 +13,7 @@ export default function CardOptions({ countdown }: CardOptionsProps) { return ( {toggleContents ? ( diff --git a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx index 82901f7c..3b4d18b0 100644 --- a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx +++ b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx @@ -58,7 +58,7 @@ export default function SelectedCard({ countdown }: SelectedCardProps) { return ( diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 83ff144c..f906e621 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -4,9 +4,8 @@ import { useCookies } from "react-cookie"; import { useLoaderData } from "react-router-dom"; import { RushAPI } from "@/apis/rushAPI.ts"; import CTAButton from "@/components/CTAButton"; -import Scroll from "@/components/Scroll"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import CardOptions from "@/features/RushGame/RushGameSection/CardOptions.tsx"; import Countdown from "@/features/RushGame/RushGameSection/Countdown.tsx"; import FinalResult from "@/features/RushGame/RushGameSection/FinalResult.tsx"; @@ -105,12 +104,6 @@ export default function RushGame() {

- - -

스크롤

-

하고 캐스퍼 일렉트릭의 놀라운 성능을 알아보세요

-
-
); } From 4329f35df70f1d6b2a0418f0143ffc1e1b14d2dc Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 17:55:31 +0900 Subject: [PATCH 083/111] =?UTF-8?q?feat:=20RushGame=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EA=B4=80=EB=A6=AC=20=ED=83=80=EC=9E=85=20=EB=B0=8F=20contex?= =?UTF-8?q?t=20=EB=82=B4=EB=B6=80=20getter,=20setter=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 69 +++++++++++++++++++++---- client/src/types/rushGame.ts | 29 +++++++++-- 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 8de83e37..d11332e5 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,24 +1,71 @@ -import { ReactNode, createContext, useState } from "react"; -import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; -import { RushGameContextType } from "@/types/rushGame.ts"; +import { ReactNode, createContext, useCallback, useState } from "react"; +import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; +import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/types/rushGame"; export const RushGameContext = createContext(undefined); export const RushGameProvider = ({ children }: { children: ReactNode }) => { const [gameState, setGameState] = useState({ - phase: "PRE_EVENT", + phase: "NOT_STARTED", + countdown: 0, userParticipatedStatus: false, + userSelectedOption: null, + cardOptions: { + [CARD_TYPE.LEFT_OPTIONS]: { + mainText: "", + subText: "", + color: CARD_COLOR.GREEN, + selectionCount: 0, + }, + [CARD_TYPE.RIGHT_OPTIONS]: { + mainText: "", + subText: "", + color: CARD_COLOR.BLUE, + selectionCount: 0, + }, + }, }); - const setUserParticipationStatus = (status: GetRushUserParticipationStatusResponse) => { - setGameState((prevState) => ({ - ...prevState, - userParticipatedStatus: status, - })); - }; + const setGamePhase = useCallback((phase: GamePhase) => { + setGameState((prevState) => ({ ...prevState, phase })); + }, []); + + const setCountdown = useCallback((countdown: number) => { + setGameState((prevState) => ({ ...prevState, countdown: countdown })); + }, []); + + const setUserParticipationStatus = useCallback((status: boolean) => { + setGameState((prevState) => ({ ...prevState, userParticipatedStatus: status })); + }, []); + + const setUserSelectedOption = useCallback((option: CardOption | null) => { + setGameState((prevState) => ({ ...prevState, userSelectedOption: option })); + }, []); + + const updateCardOption = useCallback( + (option: CardOption, updates: Partial) => { + setGameState((prevState) => ({ + ...prevState, + cardOptions: { + ...prevState.cardOptions, + [option]: { ...prevState.cardOptions[option], ...updates }, + }, + })); + }, + [] + ); return ( - + {children} ); diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index ca6e1f6e..b3774f5a 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -1,11 +1,30 @@ -import React from "react"; -import { GetRushUserParticipationStatusResponse } from "@/types/rushApi.ts"; +import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; + +export type GamePhase = "NOT_STARTED" | "IN_PROGRESS" | "COMPLETED"; +export type CardOption = CARD_TYPE.LEFT_OPTIONS | CARD_TYPE.RIGHT_OPTIONS; + +export interface CardOptionState { + mainText: string; + subText: string; + resultMainText?: string; + resultSubText?: string; + color: CARD_COLOR; + selectionCount: number; +} export interface RushGameContextType { gameState: { - phase: "PRE_EVENT" | "EVENT_RUNNING" | "EVENT_ENDED"; + phase: GamePhase; + countdown: number; userParticipatedStatus: boolean; + userSelectedOption: CardOption | null; + cardOptions: { + [key in CardOption]: CardOptionState; + }; }; - setGameState: React.Dispatch>; - setUserParticipationStatus: (status: GetRushUserParticipationStatusResponse) => void; + setGamePhase: (phase: GamePhase) => void; + setCountdown: (countdown: number) => void; + setUserParticipationStatus: (status: boolean) => void; + setUserSelectedOption: (option: CardOption | null) => void; + updateCardOption: (option: CardOption, updates: Partial) => void; } From 09b0ddad1aba8191483582c71d44d2277734dc15 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 22:01:02 +0900 Subject: [PATCH 084/111] =?UTF-8?q?feat:=20Rush=20=EC=B9=B4=EC=9A=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=8B=A4=EC=9A=B4=20=EC=83=81=ED=83=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20Context=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 72 +++++++++++++++-- .../RushGame/RushGameCard/RushCountdown.tsx | 11 ++- .../RushGame/RushGameSection/CardOptions.tsx | 8 +- .../RushGame/RushGameSection/Countdown.tsx | 18 ++--- .../RushGame/RushGameSection/FinalResult.tsx | 2 +- .../RushGame/RushGameSection/SelectedCard.tsx | 12 +-- client/src/pages/RushGame/index.tsx | 81 +++---------------- client/src/types/rushGame.ts | 11 ++- 8 files changed, 99 insertions(+), 116 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index d11332e5..e300d2a6 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,13 +1,19 @@ -import { ReactNode, createContext, useCallback, useState } from "react"; +import { ReactNode, createContext, useCallback, useEffect, useState } from "react"; +import { useLoaderData } from "react-router-dom"; import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; +import useCountdown from "@/hooks/useCountdown.ts"; +import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/types/rushGame"; export const RushGameContext = createContext(undefined); export const RushGameProvider = ({ children }: { children: ReactNode }) => { + const rushData = useLoaderData() as GetTotalRushEventsResponse; + const [initialPreCountdown, setInitialPreCountdown] = useState(null); + const [initialRunCountdown, setInitialRunCountdown] = useState(null); + const [gameState, setGameState] = useState({ phase: "NOT_STARTED", - countdown: 0, userParticipatedStatus: false, userSelectedOption: null, cardOptions: { @@ -30,10 +36,6 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { setGameState((prevState) => ({ ...prevState, phase })); }, []); - const setCountdown = useCallback((countdown: number) => { - setGameState((prevState) => ({ ...prevState, countdown: countdown })); - }, []); - const setUserParticipationStatus = useCallback((status: boolean) => { setGameState((prevState) => ({ ...prevState, userParticipatedStatus: status })); }, []); @@ -55,12 +57,68 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [] ); + useEffect(() => { + const currentEvent = rushData.events.find( + (event) => event.rushEventId === rushData.todayEventId + ); + if (currentEvent) { + const serverTime = new Date(rushData.serverTime).getTime(); + const startTime = new Date(currentEvent.startDateTime).getTime(); + const endTime = new Date(currentEvent.endDateTime).getTime(); + + switch (gameState.phase) { + case "NOT_STARTED": + if (rushData.serverTime && currentEvent?.startDateTime) { + const preCountdown = Math.max( + 0, + Math.floor((startTime - serverTime) / 1000) + ); + setInitialPreCountdown(preCountdown); + } + break; + case "IN_PROGRESS": + if (rushData.serverTime && currentEvent?.endDateTime) { + const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); + setInitialRunCountdown(runCountdown); + } + break; + } + } + }, [rushData, gameState.phase]); + + const preCountdown = useCountdown(initialPreCountdown || 0); + const runCountdown = useCountdown(initialRunCountdown || 0); + + useEffect(() => { + if (preCountdown < 0 && gameState.phase === "NOT_STARTED") { + setGamePhase("IN_PROGRESS"); + } else if (runCountdown < 0 && gameState.phase === "IN_PROGRESS") { + setGamePhase("COMPLETED"); + } + }, [preCountdown, runCountdown]); + + // TODO: POST 후 사용자 참여 상태 업데이트 및 진행 상태 수정 + // const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus( + // cookies[COOKIE_TOKEN_KEY] + // ); + // setUserParticipationStatus(userParticipatedStatus); + + // useEffect(() => { + // if (gameState.userParticipatedStatus) { + // setGameState((prev) => ({ + // ...prev, + // phase: "IN_PROGRESS", + // })); + // } + // }, [gameState.userParticipatedStatus, setGameState]); + return ( time.toString().padStart(2, "0"); diff --git a/client/src/features/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSection/CardOptions.tsx index 6d22fc3b..cd6d5f2d 100644 --- a/client/src/features/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSection/CardOptions.tsx @@ -4,11 +4,7 @@ import RushCardComparison from "@/features/RushGame/RushGameCard/RushCardCompari import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; import useToggleContents from "@/hooks/useToggleContents.ts"; -interface CardOptionsProps { - countdown: number; -} - -export default function CardOptions({ countdown }: CardOptionsProps) { +export default function CardOptions() { const { toggleContents } = useToggleContents(true, 5000); return ( @@ -25,7 +21,7 @@ export default function CardOptions({ countdown }: CardOptionsProps) { ) : ( - + )} diff --git a/client/src/features/RushGame/RushGameSection/Countdown.tsx b/client/src/features/RushGame/RushGameSection/Countdown.tsx index da1477f4..d2025405 100644 --- a/client/src/features/RushGame/RushGameSection/Countdown.tsx +++ b/client/src/features/RushGame/RushGameSection/Countdown.tsx @@ -1,15 +1,13 @@ import { motion } from "framer-motion"; import { Background } from "@/components/Background"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; +import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; -interface CountdownProps { - countdown: number; -} - -function CountdownTimer({ countdown }: CountdownProps) { - const hours = Math.floor(countdown / 3600); - const minutes = Math.floor((countdown % 3600) / 60); - const seconds = countdown % 60; +function CountdownTimer() { + const { preCountdown } = useRushGameContext(); + const hours = Math.floor(preCountdown / 3600); + const minutes = Math.floor((preCountdown % 3600) / 60); + const seconds = preCountdown % 60; const formatTime = (time: number) => time.toString().padStart(2, "0"); @@ -38,13 +36,13 @@ function TimeDisplay({ label, value }: { label: string; value: string }) { ); } -export default function Countdown({ countdown }: CountdownProps) { +export default function Countdown() { return ( <> 이제 곧 하단에 밸런스 게임 주제가 공개돼요! - + ); } diff --git a/client/src/features/RushGame/RushGameSection/FinalResult.tsx b/client/src/features/RushGame/RushGameSection/FinalResult.tsx index cf395fe8..0766b754 100644 --- a/client/src/features/RushGame/RushGameSection/FinalResult.tsx +++ b/client/src/features/RushGame/RushGameSection/FinalResult.tsx @@ -1,3 +1,3 @@ export default function FinalResult() { - return <>; + return
test
; } diff --git a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx index 3b4d18b0..e7521247 100644 --- a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx +++ b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx @@ -8,14 +8,10 @@ import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; interface SelectedCardProps { - countdown: number; -} - -interface SelectedCardChangeProps { onClick: () => void; } -function SelectedCardDescription({ onClick }: SelectedCardChangeProps) { +function SelectedCardDescription({ onClick }: SelectedCardProps) { return ( @@ -34,7 +30,7 @@ function SelectedCardDescription({ onClick }: SelectedCardChangeProps) { ); } -function SelectedCardCurrentRatio({ onClick }: SelectedCardChangeProps) { +function SelectedCardCurrentRatio({ onClick }: SelectedCardProps) { return ( @@ -53,7 +49,7 @@ function SelectedCardCurrentRatio({ onClick }: SelectedCardChangeProps) { ); } -export default function SelectedCard({ countdown }: SelectedCardProps) { +export default function SelectedCard() { const { toggleContents, toggle } = useToggleContents(); return ( @@ -61,7 +57,7 @@ export default function SelectedCard({ countdown }: SelectedCardProps) { className="flex flex-col gap-3 justify-center items-center pt-6" {...SCROLL_MOTION(ASCEND)} > - + {toggleContents ? ( ) : ( diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index f906e621..0d09c286 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -1,91 +1,28 @@ -import { useEffect, useState } from "react"; import { motion } from "framer-motion"; -import { useCookies } from "react-cookie"; -import { useLoaderData } from "react-router-dom"; -import { RushAPI } from "@/apis/rushAPI.ts"; import CTAButton from "@/components/CTAButton"; -import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import CardOptions from "@/features/RushGame/RushGameSection/CardOptions.tsx"; import Countdown from "@/features/RushGame/RushGameSection/Countdown.tsx"; import FinalResult from "@/features/RushGame/RushGameSection/FinalResult.tsx"; import SelectedCard from "@/features/RushGame/RushGameSection/SelectedCard.tsx"; -import useCountdown from "@/hooks/useCountdown.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; -import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; +// TODO: 계속 카운트 다운에 맞춰 매초 렌더링 되는 문제 해결 export default function RushGame() { - const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const { gameState, setGameState, setUserParticipationStatus } = useRushGameContext(); - const [initialPreCountdown, setInitialPreCountdown] = useState(null); - const [initialRunCountdown, setInitialRunCountdown] = useState(null); - - // TODO: loader 사용으로 바꾸기 - // const data = useLoaderData() as GetTotalRushEventsResponse; - - useEffect(() => { - (async () => { - try { - const rushData = await RushAPI.getRush(); - const currentEvent = rushData.events.find( - (event) => event.rushEventId === rushData.todayEventId - ); - - if (rushData.serverTime && currentEvent?.startDateTime) { - const serverTime = new Date(rushData.serverTime).getTime(); - const startTime = new Date(currentEvent.startDateTime).getTime(); - const endTime = new Date(currentEvent.endDateTime).getTime(); - - const preCountdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); - const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); - - setInitialPreCountdown(preCountdown); - setInitialRunCountdown(runCountdown); - } - - const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus( - cookies[COOKIE_TOKEN_KEY] - ); - setUserParticipationStatus(userParticipatedStatus); - } catch (error) { - console.error("Error:", error); - } - })(); - }, []); - - // const preCountdown = useCountdown(initialPreCountdown || 0); - // const runCountdown = useCountdown(initialRunCountdown || 0); - - // TEST CODE - const preCountdown = useCountdown(3 || 0); - const runCountdown = useCountdown(3 || 0); - - useEffect(() => { - if (preCountdown < 0 && gameState.phase === "PRE_EVENT") { - setGameState((prev) => ({ ...prev, phase: "EVENT_RUNNING" })); - } - }, [preCountdown, gameState.phase, setGameState]); - - useEffect(() => { - if (gameState.userParticipatedStatus) { - setGameState((prev) => ({ - ...prev, - phase: "EVENT_RUNNING", - })); - } - }, [gameState.userParticipatedStatus, setGameState]); + const { gameState } = useRushGameContext(); const renderRushGameContent = () => { + console.log(gameState.phase); switch (gameState.phase) { - case "PRE_EVENT": - return ; - case "EVENT_RUNNING": + case "NOT_STARTED": + return ; + case "IN_PROGRESS": if (!gameState.userParticipatedStatus) { - return ; + return ; } else { - return ; + return ; } - case "EVENT_ENDED": + case "COMPLETED": return ; default: return null; diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index b3774f5a..ca9260b7 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -1,29 +1,28 @@ -import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; - export type GamePhase = "NOT_STARTED" | "IN_PROGRESS" | "COMPLETED"; -export type CardOption = CARD_TYPE.LEFT_OPTIONS | CARD_TYPE.RIGHT_OPTIONS; +export type CardColor = "blue" | "red" | "yellow" | "green"; +export type CardOption = 1 | 2; export interface CardOptionState { mainText: string; subText: string; resultMainText?: string; resultSubText?: string; - color: CARD_COLOR; + color: CardColor; selectionCount: number; } export interface RushGameContextType { gameState: { phase: GamePhase; - countdown: number; userParticipatedStatus: boolean; userSelectedOption: CardOption | null; cardOptions: { [key in CardOption]: CardOptionState; }; }; + preCountdown: number; + runCountdown: number; setGamePhase: (phase: GamePhase) => void; - setCountdown: (countdown: number) => void; setUserParticipationStatus: (status: boolean) => void; setUserSelectedOption: (option: CardOption | null) => void; updateCardOption: (option: CardOption, updates: Partial) => void; From f6808f2b7bcfa55a2e0cc925952e3d4dd78e4956 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Tue, 13 Aug 2024 22:08:01 +0900 Subject: [PATCH 085/111] =?UTF-8?q?fix:=20=EA=B2=8C=EC=9E=84=EC=9D=B4=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=20=EC=A7=84=ED=96=89=20=EC=A4=91=EC=9D=B8=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EC=97=90=EC=84=9C=200:0:0=EC=9D=B4=20?= =?UTF-8?q?=EB=9C=A8=EA=B3=A0=20=EA=B2=8C=EC=9E=84=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=84=98=EC=96=B4=EA=B0=80=EB=8A=94=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index e300d2a6..2f1b59a7 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -90,9 +90,9 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { const runCountdown = useCountdown(initialRunCountdown || 0); useEffect(() => { - if (preCountdown < 0 && gameState.phase === "NOT_STARTED") { + if (preCountdown <= 0 && gameState.phase === "NOT_STARTED") { setGamePhase("IN_PROGRESS"); - } else if (runCountdown < 0 && gameState.phase === "IN_PROGRESS") { + } else if (runCountdown <= 0 && gameState.phase === "IN_PROGRESS") { setGamePhase("COMPLETED"); } }, [preCountdown, runCountdown]); From 1e7c40f18bad12354fb61426dabd84621460943c Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Wed, 14 Aug 2024 00:09:56 +0900 Subject: [PATCH 086/111] =?UTF-8?q?feat:=20POST=20=ED=9B=84=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EC=B0=B8=EC=97=AC=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B0=8F=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EA=B0=80=20=EC=84=A0=ED=83=9D=ED=95=9C=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EB=B2=88=ED=98=B8=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 34 +++++++++++-------- .../RushGameCard/RushCardComparison.tsx | 10 +++--- client/src/pages/RushGame/index.tsx | 2 +- client/src/types/rushGame.ts | 2 ++ 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 2f1b59a7..4868cfca 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,5 +1,6 @@ import { ReactNode, createContext, useCallback, useEffect, useState } from "react"; import { useLoaderData } from "react-router-dom"; +import { RushAPI } from "@/apis/rushAPI.ts"; import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; import useCountdown from "@/hooks/useCountdown.ts"; import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; @@ -86,8 +87,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [rushData, gameState.phase]); - const preCountdown = useCountdown(initialPreCountdown || 0); - const runCountdown = useCountdown(initialRunCountdown || 0); + const preCountdown = useCountdown(initialPreCountdown || 3); + const runCountdown = useCountdown(initialRunCountdown || 5000); useEffect(() => { if (preCountdown <= 0 && gameState.phase === "NOT_STARTED") { @@ -97,20 +98,22 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [preCountdown, runCountdown]); - // TODO: POST 후 사용자 참여 상태 업데이트 및 진행 상태 수정 - // const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus( - // cookies[COOKIE_TOKEN_KEY] - // ); - // setUserParticipationStatus(userParticipatedStatus); + // console.log(gameState.userParticipatedStatus); - // useEffect(() => { - // if (gameState.userParticipatedStatus) { - // setGameState((prev) => ({ - // ...prev, - // phase: "IN_PROGRESS", - // })); - // } - // }, [gameState.userParticipatedStatus, setGameState]); + const updateUserStatusAndSelectedOption = useCallback( + async (token: string, selectedOption: CardOption) => { + try { + const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus(token); + setUserParticipationStatus(userParticipatedStatus); + if (userParticipatedStatus) { + setUserSelectedOption(selectedOption); + } + } catch (error) { + console.error("Error: ", error); + } + }, + [] + ); return ( { setUserParticipationStatus, setUserSelectedOption, updateCardOption, + updateUserStatusAndSelectedOption, }} > {children} diff --git a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx index 8d1f7c2d..9b5abf6e 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx @@ -6,13 +6,14 @@ import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts" import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { GetTodayRushEventResponse } from "@/types/rushApi.ts"; +import { CardOption } from "@/types/rushGame.ts"; const TEMP_CURRENT_DAY: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; export default function RushCardComparison() { const [todayRushEventData, setTodayRushEventData] = useState(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const { setUserParticipationStatus } = useRushGameContext(); + const { updateUserStatusAndSelectedOption } = useRushGameContext(); useEffect(() => { (async () => { @@ -36,7 +37,7 @@ export default function RushCardComparison() { rightOption: { mainText: rightOptionMainText = "", subText: rightOptionSubText = "" } = {}, } = todayRushEventData || {}; - const handleCardSelection = async (optionId: number) => { + const handleCardSelection = async (optionId: CardOption) => { try { const response = await RushAPI.postSelectedRushOptionApply( cookies[COOKIE_TOKEN_KEY], @@ -44,10 +45,7 @@ export default function RushCardComparison() { ); if (response === 204) { - const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus( - cookies[COOKIE_TOKEN_KEY] - ); - setUserParticipationStatus(userParticipatedStatus); + await updateUserStatusAndSelectedOption(cookies[COOKIE_TOKEN_KEY], optionId); } else if (response === 404) { console.log(`Error ${response}`); } diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 0d09c286..002f181e 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -12,7 +12,7 @@ export default function RushGame() { const { gameState } = useRushGameContext(); const renderRushGameContent = () => { - console.log(gameState.phase); + // console.log(gameState.phase); switch (gameState.phase) { case "NOT_STARTED": return ; diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index ca9260b7..fc27171f 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -11,6 +11,7 @@ export interface CardOptionState { selectionCount: number; } +// TODO: 추후 밖에서 안쓰는 함수들 제거 export interface RushGameContextType { gameState: { phase: GamePhase; @@ -26,4 +27,5 @@ export interface RushGameContextType { setUserParticipationStatus: (status: boolean) => void; setUserSelectedOption: (option: CardOption | null) => void; updateCardOption: (option: CardOption, updates: Partial) => void; + updateUserStatusAndSelectedOption: (token: string, selectedOption: CardOption) => Promise; } From edacc263c6bf549a025ef40d647a35613429c567 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Wed, 14 Aug 2024 00:20:34 +0900 Subject: [PATCH 087/111] =?UTF-8?q?feat:=20API=EB=A1=9C=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20=EB=91=90=20=EA=B0=9C=EC=9D=98=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=20=EC=98=B5=EC=85=98=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20context?= =?UTF-8?q?=EC=97=90=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 8 ++-- .../RushGameCard/RushCardComparison.tsx | 46 +++++++++++-------- client/src/types/rushGame.ts | 2 +- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 4868cfca..5907637f 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -45,7 +45,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { setGameState((prevState) => ({ ...prevState, userSelectedOption: option })); }, []); - const updateCardOption = useCallback( + const updateCardOptions = useCallback( (option: CardOption, updates: Partial) => { setGameState((prevState) => ({ ...prevState, @@ -87,6 +87,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [rushData, gameState.phase]); + // FIX: runCountdown이 preCountdown이 카운트다운될 때부터 같이 카운트다운 되고 있는 현상 + // 이건 12시 지나고 다시 확인해볼 것 (어차피 서버에서 받아오는 시간을 사용하기 때문에 문제는 없을듯) const preCountdown = useCountdown(initialPreCountdown || 3); const runCountdown = useCountdown(initialRunCountdown || 5000); @@ -98,7 +100,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [preCountdown, runCountdown]); - // console.log(gameState.userParticipatedStatus); + // console.log(gameState.cardOptions); const updateUserStatusAndSelectedOption = useCallback( async (token: string, selectedOption: CardOption) => { @@ -124,7 +126,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { setGamePhase, setUserParticipationStatus, setUserSelectedOption, - updateCardOption, + updateCardOptions, updateUserStatusAndSelectedOption, }} > diff --git a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx index 9b5abf6e..5f174cac 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx @@ -1,19 +1,18 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; -import { GetTodayRushEventResponse } from "@/types/rushApi.ts"; import { CardOption } from "@/types/rushGame.ts"; const TEMP_CURRENT_DAY: (typeof CARD_DAYS)[keyof typeof CARD_DAYS] = CARD_DAYS.DAY1; export default function RushCardComparison() { - const [todayRushEventData, setTodayRushEventData] = useState(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const { updateUserStatusAndSelectedOption } = useRushGameContext(); + const { gameState, updateUserStatusAndSelectedOption, updateCardOptions } = + useRushGameContext(); useEffect(() => { (async () => { @@ -21,22 +20,26 @@ export default function RushCardComparison() { const todayRushEventData = await RushAPI.getTodayRushEvent( cookies[COOKIE_TOKEN_KEY] ); - setTodayRushEventData(todayRushEventData); + + // TODO: 카드 색상 랜덤으로 변경 + if (todayRushEventData) { + updateCardOptions(CARD_TYPE.LEFT_OPTIONS, { + mainText: todayRushEventData.leftOption.mainText, + subText: todayRushEventData.leftOption.subText, + color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS], + }); + updateCardOptions(CARD_TYPE.RIGHT_OPTIONS, { + mainText: todayRushEventData.rightOption.mainText, + subText: todayRushEventData.rightOption.subText, + color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS], + }); + } } catch (error) { console.error("Error:", error); } })(); }, []); - // TODO: 카드 색상 랜덤으로 변경 - const leftOptionColor = CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS]; - const rightOptionColor = CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS]; - - const { - leftOption: { mainText: leftOptionMainText = "", subText: leftOptionSubText = "" } = {}, - rightOption: { mainText: rightOptionMainText = "", subText: rightOptionSubText = "" } = {}, - } = todayRushEventData || {}; - const handleCardSelection = async (optionId: CardOption) => { try { const response = await RushAPI.postSelectedRushOptionApply( @@ -54,21 +57,24 @@ export default function RushCardComparison() { } }; + const leftOptionData = gameState.cardOptions[CARD_TYPE.LEFT_OPTIONS]; + const rightOptionData = gameState.cardOptions[CARD_TYPE.RIGHT_OPTIONS]; + return (
handleCardSelection(CARD_TYPE.LEFT_OPTIONS)} />

VS

handleCardSelection(CARD_TYPE.RIGHT_OPTIONS)} />
diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index fc27171f..932bb4f3 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -26,6 +26,6 @@ export interface RushGameContextType { setGamePhase: (phase: GamePhase) => void; setUserParticipationStatus: (status: boolean) => void; setUserSelectedOption: (option: CardOption | null) => void; - updateCardOption: (option: CardOption, updates: Partial) => void; + updateCardOptions: (option: CardOption, updates: Partial) => void; updateUserStatusAndSelectedOption: (token: string, selectedOption: CardOption) => Promise; } From fb6ffc7849a80816de5e1d99c48dc20cb7e687f4 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Wed, 14 Aug 2024 11:49:34 +0900 Subject: [PATCH 088/111] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=84=A0=ED=83=9D=ED=95=9C=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=84=A4=EB=AA=85=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20context=EB=A1=9C=20=EC=83=81=ED=83=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 35 ++++++++++++++---- .../RushCardResultDescription.tsx | 36 +++++++++++-------- client/src/types/rushGame.ts | 9 ++--- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 5907637f..184586d6 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -16,17 +16,21 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { const [gameState, setGameState] = useState({ phase: "NOT_STARTED", userParticipatedStatus: false, - userSelectedOption: null, + userSelectedOption: 1, cardOptions: { [CARD_TYPE.LEFT_OPTIONS]: { mainText: "", subText: "", + resultMainText: "", + resultSubText: "", color: CARD_COLOR.GREEN, selectionCount: 0, }, [CARD_TYPE.RIGHT_OPTIONS]: { mainText: "", subText: "", + resultMainText: "", + resultSubText: "", color: CARD_COLOR.BLUE, selectionCount: 0, }, @@ -41,7 +45,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { setGameState((prevState) => ({ ...prevState, userParticipatedStatus: status })); }, []); - const setUserSelectedOption = useCallback((option: CardOption | null) => { + const setUserSelectedOption = useCallback((option: CardOption) => { setGameState((prevState) => ({ ...prevState, userSelectedOption: option })); }, []); @@ -87,10 +91,11 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [rushData, gameState.phase]); - // FIX: runCountdown이 preCountdown이 카운트다운될 때부터 같이 카운트다운 되고 있는 현상 - // 이건 12시 지나고 다시 확인해볼 것 (어차피 서버에서 받아오는 시간을 사용하기 때문에 문제는 없을듯) - const preCountdown = useCountdown(initialPreCountdown || 3); - const runCountdown = useCountdown(initialRunCountdown || 5000); + // const preCountdown = useCountdown(initialPreCountdown || 0); + // const runCountdown = useCountdown(initialRunCountdown || 0); + + const preCountdown = useCountdown(1); + const runCountdown = useCountdown(10000); useEffect(() => { if (preCountdown <= 0 && gameState.phase === "NOT_STARTED") { @@ -100,7 +105,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [preCountdown, runCountdown]); - // console.log(gameState.cardOptions); + console.log(gameState.cardOptions); const updateUserStatusAndSelectedOption = useCallback( async (token: string, selectedOption: CardOption) => { @@ -117,6 +122,21 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [] ); + const getSelectedCardInfo = useCallback( + (option: CardOption) => { + const cardInfo = gameState.cardOptions[option]; + return { + mainText: cardInfo.mainText, + subText: cardInfo.subText, + resultMainText: cardInfo.resultMainText, + resultSubText: cardInfo.resultSubText, + color: cardInfo.color, + selectionCount: cardInfo.selectionCount, + }; + }, + [gameState.userSelectedOption, gameState.cardOptions] + ); + return ( { setUserSelectedOption, updateCardOptions, updateUserStatusAndSelectedOption, + getSelectedCardInfo, }} > {children} diff --git a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx index 977b700a..a6818420 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx @@ -1,14 +1,14 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { cva } from "class-variance-authority"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import Category from "@/components/Category"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLOR } from "@/constants/Rush/rushCard.ts"; -import { GetRushOptionResultResponse } from "@/types/rushApi.ts"; +import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; const backgroundGradients = cva( - `flex gap-[35px] w-[834px] h-[400px] bg-gradient-green rounded-800 py-6 px-[37px] justify-between break-keep`, + `flex gap-[35px] w-[834px] h-[400px] rounded-800 py-6 px-[37px] justify-between break-keep`, { variants: { color: { @@ -17,30 +17,36 @@ const backgroundGradients = cva( [CARD_COLOR.YELLOW]: "bg-gradient-yellow", [CARD_COLOR.GREEN]: "bg-gradient-green", }, + defaultVariants: { + color: CARD_COLOR.GREEN, + }, }, } ); export default function RushCardResultDescription() { - const [userResultData, setUserResultData] = useState(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); + const { gameState, updateCardOptions, getSelectedCardInfo } = useRushGameContext(); useEffect(() => { (async () => { - // TODO: 사용자가 선택한 카드 옵션(1 or 2) Context에 저장해서 받기 - const userResultData = await RushAPI.getRushOptionResult(cookies[COOKIE_TOKEN_KEY], 1); - setUserResultData(userResultData); + const userResultData = await RushAPI.getRushOptionResult( + cookies[COOKIE_TOKEN_KEY], + gameState.userSelectedOption + ); + if (userResultData) { + updateCardOptions(gameState.userSelectedOption, { + mainText: userResultData.mainText, + resultMainText: userResultData.resultMainText, + resultSubText: userResultData.resultSubText, + }); + } })(); }, []); - const { - mainText: mainText = "", - resultMainText: resultMainText = "", - resultSubText: resultSubText = "", - } = userResultData || {}; - - // TODO: RushCard에서 선택한 색상 가져오기 - const color = CARD_COLOR.RED; + const { mainText, resultMainText, resultSubText, color } = getSelectedCardInfo( + gameState.userSelectedOption + ); return (
diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index 932bb4f3..d7b3716c 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -5,8 +5,8 @@ export type CardOption = 1 | 2; export interface CardOptionState { mainText: string; subText: string; - resultMainText?: string; - resultSubText?: string; + resultMainText: string; + resultSubText: string; color: CardColor; selectionCount: number; } @@ -16,7 +16,7 @@ export interface RushGameContextType { gameState: { phase: GamePhase; userParticipatedStatus: boolean; - userSelectedOption: CardOption | null; + userSelectedOption: CardOption; cardOptions: { [key in CardOption]: CardOptionState; }; @@ -25,7 +25,8 @@ export interface RushGameContextType { runCountdown: number; setGamePhase: (phase: GamePhase) => void; setUserParticipationStatus: (status: boolean) => void; - setUserSelectedOption: (option: CardOption | null) => void; + setUserSelectedOption: (option: CardOption) => void; updateCardOptions: (option: CardOption, updates: Partial) => void; updateUserStatusAndSelectedOption: (token: string, selectedOption: CardOption) => Promise; + getSelectedCardInfo: (option: CardOption) => CardOptionState; } From f2e3e60c6a5347fdfa0d203a6974deda09a0e305 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Wed, 14 Aug 2024 12:18:21 +0900 Subject: [PATCH 089/111] =?UTF-8?q?feat:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EB=B9=84=EC=9C=A8=20=EA=B4=80=EB=A0=A8=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=20=EA=B3=B5=ED=86=B5=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 34 ++++++++++++- .../RushGameCard/RushCardCurrentRatio.tsx | 50 +++++-------------- .../RushCardResultDescription.tsx | 8 +-- .../RushGame/RushGameSection/SelectedCard.tsx | 7 +++ client/src/types/rushGame.ts | 2 + 5 files changed, 60 insertions(+), 41 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 184586d6..28ff9b93 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,6 +1,8 @@ import { ReactNode, createContext, useCallback, useEffect, useState } from "react"; +import { useCookies } from "react-cookie"; import { useLoaderData } from "react-router-dom"; import { RushAPI } from "@/apis/rushAPI.ts"; +import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; import useCountdown from "@/hooks/useCountdown.ts"; import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; @@ -9,6 +11,7 @@ import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/t export const RushGameContext = createContext(undefined); export const RushGameProvider = ({ children }: { children: ReactNode }) => { + const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const rushData = useLoaderData() as GetTotalRushEventsResponse; const [initialPreCountdown, setInitialPreCountdown] = useState(null); const [initialRunCountdown, setInitialRunCountdown] = useState(null); @@ -16,7 +19,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { const [gameState, setGameState] = useState({ phase: "NOT_STARTED", userParticipatedStatus: false, - userSelectedOption: 1, + userSelectedOption: CARD_TYPE.LEFT_OPTIONS, cardOptions: { [CARD_TYPE.LEFT_OPTIONS]: { mainText: "", @@ -137,6 +140,33 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [gameState.userSelectedOption, gameState.cardOptions] ); + const fetchRushBalance = useCallback(async (): Promise => { + try { + const rushBalanceData = await RushAPI.getRushBalance(cookies[COOKIE_TOKEN_KEY]); + const { leftOption, rightOption } = rushBalanceData; + + updateCardOptions(CARD_TYPE.LEFT_OPTIONS, { + selectionCount: leftOption, + }); + updateCardOptions(CARD_TYPE.RIGHT_OPTIONS, { + selectionCount: rightOption, + }); + } catch (error) { + console.error("Error: ", error); + } + }, [cookies]); + + const getOptionRatio = useCallback( + (option: CardOption): number => { + const total = + gameState.cardOptions[CARD_TYPE.LEFT_OPTIONS].selectionCount + + gameState.cardOptions[CARD_TYPE.RIGHT_OPTIONS].selectionCount; + if (total === 0) return 0; + return Math.round((gameState.cardOptions[option].selectionCount / total) * 100); + }, + [gameState.cardOptions] + ); + return ( { updateCardOptions, updateUserStatusAndSelectedOption, getSelectedCardInfo, + getOptionRatio, + fetchRushBalance, }} > {children} diff --git a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx index 98a5d060..ff25642c 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx @@ -1,9 +1,7 @@ -import { useEffect, useState } from "react"; -import { useCookies } from "react-cookie"; -import { RushAPI } from "@/apis/rushAPI.ts"; import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; -import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; +import { CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; import Reload from "/public/assets/icons/reload.svg?react"; @@ -29,40 +27,13 @@ function ReloadButton({ onClick }: { onClick: () => void }) { } export default function RushCardCurrentRatio() { - const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const [leftOptionRatio, setLeftOptionRatio] = useState(0); - const [rightOptionRatio, setRightOptionRatio] = useState(0); - const [message, setMessage] = useState(MESSAGES.WINNING); - const [optionId, setOptionId] = useState(null); + const { gameState, getOptionRatio, fetchRushBalance } = useRushGameContext(); const { toggleContents } = useToggleContents(true, 5000); - const fetchRushBalance = async () => { - try { - const rushBalanceData = await RushAPI.getRushBalance(cookies[COOKIE_TOKEN_KEY]); - const { optionId, leftOption, rightOption } = rushBalanceData; + const leftOptionRatio = getOptionRatio(CARD_TYPE.LEFT_OPTIONS); + const rightOptionRatio = getOptionRatio(CARD_TYPE.RIGHT_OPTIONS); - const total = leftOption + rightOption; - const leftRatio = Math.round((leftOption / total) * 100); - const rightRatio = Math.round((rightOption / total) * 100); - - setOptionId(optionId); - setLeftOptionRatio(leftRatio); - setRightOptionRatio(rightRatio); - - const selectedOptionCount = optionId === 1 ? leftOption : rightOption; - const opposingOptionCount = optionId === 1 ? rightOption : leftOption; - - setMessage( - selectedOptionCount > opposingOptionCount ? MESSAGES.WINNING : MESSAGES.LOSING - ); - } catch (error) { - console.error("Error: ", error); - } - }; - - useEffect(() => { - fetchRushBalance(); - }, []); + const message = leftOptionRatio > rightOptionRatio ? MESSAGES.WINNING : MESSAGES.LOSING; return (
@@ -72,19 +43,24 @@ export default function RushCardCurrentRatio() {
+ {/* TODO: 공통 로직 함수로 분리 */}

첫 차로 성능 좋은 차

{leftOptionRatio > rightOptionRatio && ( 우세해요! )} - {optionId === 1 && 당신의 선택} + {gameState.userSelectedOption === CARD_TYPE.LEFT_OPTIONS && ( + 당신의 선택 + )}

첫 차로 저렴한 차

{rightOptionRatio > leftOptionRatio && ( 우세해요! )} - {optionId === 2 && 당신의 선택} + {gameState.userSelectedOption === CARD_TYPE.RIGHT_OPTIONS && ( + 당신의 선택 + )}
{/* TODO: 비율대로 프로그래스바 움직이는 로직 구현 */} diff --git a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx index a6818420..2627b705 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx @@ -26,7 +26,8 @@ const backgroundGradients = cva( export default function RushCardResultDescription() { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); - const { gameState, updateCardOptions, getSelectedCardInfo } = useRushGameContext(); + const { gameState, updateCardOptions, getSelectedCardInfo, getOptionRatio } = + useRushGameContext(); useEffect(() => { (async () => { @@ -48,6 +49,8 @@ export default function RushCardResultDescription() { gameState.userSelectedOption ); + const selectedOptionRatio = getOptionRatio(gameState.userSelectedOption); + return (
@@ -57,8 +60,7 @@ export default function RushCardResultDescription() {

지금

- {/* TODO: 실시간 비율 Context로 저장해서 넣기 */} -

63%

+

{selectedOptionRatio}%

가 선택했어요

diff --git a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx index e7521247..a5c021f3 100644 --- a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx +++ b/client/src/features/RushGame/RushGameSection/SelectedCard.tsx @@ -1,8 +1,10 @@ +import { useEffect } from "react"; import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; import RushCardCurrentRatio from "@/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx"; import RushCardResultDescription from "@/features/RushGame/RushGameCard/RushCardResultDescription.tsx"; import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; +import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; @@ -51,6 +53,11 @@ function SelectedCardCurrentRatio({ onClick }: SelectedCardProps) { export default function SelectedCard() { const { toggleContents, toggle } = useToggleContents(); + const { fetchRushBalance } = useRushGameContext(); + + useEffect(() => { + fetchRushBalance(); + }, []); return ( ) => void; updateUserStatusAndSelectedOption: (token: string, selectedOption: CardOption) => Promise; getSelectedCardInfo: (option: CardOption) => CardOptionState; + getOptionRatio: (option: CardOption) => number; + fetchRushBalance: () => Promise; } From a9af8d7567ecb48e65d0a2d4ddb73fe9af9d9eb2 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Wed, 14 Aug 2024 13:54:15 +0900 Subject: [PATCH 090/111] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EB=B6=84=EA=B8=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RushGameCard/RushCardCurrentRatio.tsx | 83 ++++++++++++++----- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx index ff25642c..0ea5bc3d 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx @@ -3,8 +3,16 @@ import Tooltip from "@/components/Tooltip"; import { CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; +import { CardOption } from "@/types/rushGame.ts"; import Reload from "/public/assets/icons/reload.svg?react"; +interface OptionDisplayProps { + mainText: string; + userSelectedOptionRatio: number; + oppositeOptionRatio: number; + isUserSelected: boolean; +} + const TOOLTIP_CONTENT = () => ( <> 새로고침을 눌러 @@ -15,9 +23,26 @@ const TOOLTIP_CONTENT = () => ( const MESSAGES = { WINNING: "이대로 가면 우리 편이 이겨요!", + TIED: "막상막하! 우리 편에 투표할 친구를 데려오세요!", LOSING: "이대로 가면 우리 편이 질 수도 있어요!", }; +function getMessage(leftRatio: number, rightRatio: number, userSelectedOption: CardOption) { + if (leftRatio >= 49 && leftRatio <= 51 && rightRatio >= 49 && rightRatio <= 51) { + return MESSAGES.TIED; + } + + const userSelectedRatio = + userSelectedOption === CARD_TYPE.LEFT_OPTIONS ? leftRatio : rightRatio; + const oppositeRatio = userSelectedOption === CARD_TYPE.LEFT_OPTIONS ? rightRatio : leftRatio; + + if (userSelectedRatio > oppositeRatio) { + return MESSAGES.WINNING; + } else { + return MESSAGES.LOSING; + } +} + function ReloadButton({ onClick }: { onClick: () => void }) { return (
From 461df268a461104b6b913c67f31442e368bdc25e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Wed, 14 Aug 2024 19:43:20 +0900 Subject: [PATCH 096/111] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=B0=94=20=EB=B9=84=EC=9C=A8=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20CSS=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RushGame/RushGameCard/RushProgressBar.tsx | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/client/src/features/RushGame/RushGameCard/RushProgressBar.tsx b/client/src/features/RushGame/RushGameCard/RushProgressBar.tsx index e484ee05..80f91dcf 100644 --- a/client/src/features/RushGame/RushGameCard/RushProgressBar.tsx +++ b/client/src/features/RushGame/RushGameCard/RushProgressBar.tsx @@ -1,3 +1,4 @@ +import { VariantProps, cva } from "class-variance-authority"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; interface RushProgressBarProps { @@ -5,24 +6,53 @@ interface RushProgressBarProps { rightOptionRatio: number; } -// TODO: 비율대로 프로그래스바 움직이는 로직 구현 +const barStyle = cva("flex items-center", { + variants: { + color: { + green: "bg-gradient-green", + red: "bg-gradient-red", + }, + status: { + winning: "text-n-neutral-950", + losing: "text-n-neutral-500", + }, + textAlign: { + left: "justify-start", + right: "justify-end", + }, + }, + defaultVariants: { + status: "winning", + }, +}); + +type BarStyleProps = VariantProps; + +interface BarProps extends BarStyleProps { + ratio: number; +} + +function Bar({ ratio, color, status, textAlign }: BarProps) { + return ( + +

{ratio}%

+
+ ); +} + export default function RushProgressBar({ leftOptionRatio, rightOptionRatio, }: RushProgressBarProps) { const { gameState } = useRushGameContext(); + const isCompleted = gameState.phase === "COMPLETED"; + const leftStatus = isCompleted && leftOptionRatio < rightOptionRatio ? "losing" : "winning"; + const rightStatus = isCompleted && rightOptionRatio < leftOptionRatio ? "losing" : "winning"; + return ( -
-

- {leftOptionRatio}% -

-

- {rightOptionRatio}% -

+
+ +
); } From 8f4d216cb53edfc852f47ca1731bcd16e35835d2 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 17:16:43 +0900 Subject: [PATCH 097/111] =?UTF-8?q?chore:=20API=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=ED=9B=84=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=83=81=EC=88=98=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C(CARD=5FOPTIONS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.ts | 143 +------------------------- 1 file changed, 1 insertion(+), 142 deletions(-) diff --git a/client/src/constants/Rush/rushCard.ts b/client/src/constants/Rush/rushCard.ts index be6e0b33..0db3a20b 100644 --- a/client/src/constants/Rush/rushCard.ts +++ b/client/src/constants/Rush/rushCard.ts @@ -10,6 +10,7 @@ export const CARD_COLOR = { GREEN: "green", } as const; +// TODO: 카드 색상 랜덤 기능 구현 후 불필요한 상수 데이터 삭제 export const CARD_DAYS = { DAY1: 1, DAY2: 2, @@ -50,145 +51,3 @@ export const CARD_COLORS: { [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, }, }; - -export const CARD_OPTIONS: { - [key: number]: { - [CARD_TYPE.LEFT_OPTIONS]: { mainText: string; subText: string }; - [CARD_TYPE.RIGHT_OPTIONS]: { mainText: string; subText: string }; - }; -} = { - [CARD_DAYS.DAY1]: { - [CARD_TYPE.LEFT_OPTIONS]: { - mainText: "첫 차는 저렴해야 한다", - subText: "가성비 좋게 저렴한 차로 시작해서 차근히 업그레이드하고 싶어", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - mainText: "첫 차는 안전해야 한다", - subText: "처음 사는 차인 만큼 안전한 차를 사서 오래 타고 싶어", - }, - }, - [CARD_DAYS.DAY2]: { - [CARD_TYPE.LEFT_OPTIONS]: { - mainText: "온라인 쇼핑이 편해서 좋다", - subText: "편한 게 최고야! 집에서 인터넷으로 쇼핑할래", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - mainText: "오프라인 쇼핑이 확실해서 좋다", - subText: "살 거면 제대로 보고 사야지! 직접 보고 나서 판단할래", - }, - }, - [CARD_DAYS.DAY3]: { - [CARD_TYPE.LEFT_OPTIONS]: { - mainText: "텐트 치고 캠핑하기", - subText: "캠핑은 텐트가 근본이지!", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - mainText: "차 안에서 차박하기", - subText: "가벼운 짐으로 차에서 잠드는 낭만이 좋아", - }, - }, - [CARD_DAYS.DAY4]: { - [CARD_TYPE.LEFT_OPTIONS]: { - mainText: "평생 주차 무료로 하기", - subText: "요즘 주차장은 너무 비싸 주차비 걱정은 그만 하고 싶어", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - mainText: "평생 주유 무료로 하기", - subText: "기름값이 너무 많이 올랐어 주유비가 많이 들어 고민이야", - }, - }, - [CARD_DAYS.DAY5]: { - [CARD_TYPE.LEFT_OPTIONS]: { - mainText: "무채색 차가 좋다", - subText: "검은색, 흰색, 회색! 오래 타려면 무난한 게 최고야", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - mainText: "컬러풀한 차가 좋다", - subText: "무채색은 지루해! 내가 좋아하는 색으로 고를래", - }, - }, - [CARD_DAYS.DAY6]: { - [CARD_TYPE.LEFT_OPTIONS]: { - mainText: "주말에는 바다보러 가기", - subText: "아까운 주말엔 국내여행이라도 다녀오고 싶어", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - mainText: "주말에는 도심 드라이브", - subText: "평일에 너무 피곤했으니 오랜만에 동네 드라이브나 할래", - }, - }, -}; - -export const CARD_RESULTS: { - [key: number]: { - [CARD_TYPE.LEFT_OPTIONS]: { resultMainText: string; resultSubText: string }; - [CARD_TYPE.RIGHT_OPTIONS]: { resultMainText: string; resultSubText: string }; - }; -} = { - [CARD_DAYS.DAY1]: { - [CARD_TYPE.LEFT_OPTIONS]: { - resultMainText: "가성비 좋은 도심형 전기차", - resultSubText: - "캐스퍼 일렉트릭은 전기차 평균보다 30% 저렴해요 첫 차로 캐스퍼 일렉트릭 어떤가요?", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - resultMainText: "가성비 좋은 도심형 전기차", - resultSubText: - "캐스퍼는 작고 귀엽기만 하다고 생각했나요? 이젠 현대 스마트센스 안전옵션까지 지원해요", - }, - }, - [CARD_DAYS.DAY2]: { - [CARD_TYPE.LEFT_OPTIONS]: { - resultMainText: "현대 유일 온라인 예약", - resultSubText: - "차 살때도 온라인 쇼핑을! 오직 온라인에서만 구매할 수 있는 캐스퍼 일렉트릭", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - resultMainText: "캐스퍼 스튜디오 송파", - resultSubText: "캐스퍼 일렉트릭을 원하는 시간에 직접 만나볼 수 있는 무인 전시 스튜디오", - }, - }, - [CARD_DAYS.DAY3]: { - [CARD_TYPE.LEFT_OPTIONS]: { - resultMainText: "V2L로 캠핑 준비 끝", - resultSubText: - "캠핑장 전기 눈치싸움은 이제 그만! 차에서 직접 220V 전원을 연결할 수 있어요", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - resultMainText: "폴 폴딩으로 공간 활용", - resultSubText: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", - }, - }, - [CARD_DAYS.DAY4]: { - [CARD_TYPE.LEFT_OPTIONS]: { - resultMainText: "전기차는 주차비 혜택 받아요", - resultSubText: "공영주차장 50% 할인 정책으로 주차비 부담을 덜 수 있어요", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - resultMainText: "전기차는 기름값 걱정 없어요", - resultSubText: "모든 시트가 완전히 접혀서 나만의 작은 방으로 만들 수 있어요", - }, - }, - [CARD_DAYS.DAY5]: { - [CARD_TYPE.LEFT_OPTIONS]: { - resultMainText: "기본 색감도 다채롭게", - resultSubText: "무채색 컬러도 매트부터 메탈릭까지 다양한 질감으로 구성했어요", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - resultMainText: "신규 색상 5종 출시", - resultSubText: "기존 캐스퍼 색상 라인업에 새로운 5종을 추가! 내 차의 개성을 뽐내봐요", - }, - }, - [CARD_DAYS.DAY6]: { - [CARD_TYPE.LEFT_OPTIONS]: { - resultMainText: "충전 한 번에 315km", - resultSubText: - "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", - }, - [CARD_TYPE.RIGHT_OPTIONS]: { - resultMainText: "충전 한 번에 315km", - resultSubText: - "엔트리급 전기차의 주행거리 혁신 한 번 충전으로 서울에서 강릉까지 왕복도 거뜬해요", - }, - }, -}; From 9484905e7c6fa754f223192c5455fb3de00fafa9 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 17:18:36 +0900 Subject: [PATCH 098/111] =?UTF-8?q?chore:=20=EC=99=B8=EB=B6=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20context=20=ED=95=A8=EC=88=98=20value=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 3 --- client/src/types/rushGame.ts | 3 --- 2 files changed, 6 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 6830af66..88909f93 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -174,9 +174,6 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { gameState, preCountdown, runCountdown, - setGamePhase, - setUserParticipationStatus, - setUserSelectedOption, updateCardOptions, updateUserStatusAndSelectedOption, getSelectedCardInfo, diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index 810b46a6..d4856561 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -23,9 +23,6 @@ export interface RushGameContextType { }; preCountdown: number; runCountdown: number; - setGamePhase: (phase: GamePhase) => void; - setUserParticipationStatus: (status: boolean) => void; - setUserSelectedOption: (option: CardOption) => void; updateCardOptions: (option: CardOption, updates: Partial) => void; updateUserStatusAndSelectedOption: (token: string, selectedOption: CardOption) => Promise; getSelectedCardInfo: (option: CardOption) => CardOptionState; From cb915bba1a7bc17889c778135d6e0618f11b3dd9 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 17:56:27 +0900 Subject: [PATCH 099/111] =?UTF-8?q?chore:=20=ED=94=84=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=B0=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=82=B4=EB=B6=80=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RushProgressBar.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename client/src/features/RushGame/{RushGameCard => RushGameComponents}/RushProgressBar.tsx (85%) diff --git a/client/src/features/RushGame/RushGameCard/RushProgressBar.tsx b/client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx similarity index 85% rename from client/src/features/RushGame/RushGameCard/RushProgressBar.tsx rename to client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx index 80f91dcf..e43ade3b 100644 --- a/client/src/features/RushGame/RushGameCard/RushProgressBar.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx @@ -6,7 +6,7 @@ interface RushProgressBarProps { rightOptionRatio: number; } -const barStyle = cva("flex items-center", { +const barVariants = cva(`flex items-center`, { variants: { color: { green: "bg-gradient-green", @@ -26,15 +26,15 @@ const barStyle = cva("flex items-center", { }, }); -type BarStyleProps = VariantProps; +type BarVariantsProps = VariantProps; -interface BarProps extends BarStyleProps { +interface BarProps extends BarVariantsProps { ratio: number; } function Bar({ ratio, color, status, textAlign }: BarProps) { return ( - +

{ratio}%

); From 527def5909cf2b828c152d3c82ec43141dd1750a Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 17:57:51 +0900 Subject: [PATCH 100/111] =?UTF-8?q?rename:=20RushGame=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=ED=8F=B4=EB=8D=94=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{RushGameCard => RushGameComponents}/RushCard.tsx | 0 .../RushCardComparison.tsx | 2 +- .../RushCardCurrentRatio.tsx | 2 +- .../RushCardResultDescription.tsx | 0 .../RushCountdown.tsx | 0 .../{RushGameSection => RushGameSections}/CardOptions.tsx | 4 ++-- .../{RushGameSection => RushGameSections}/Countdown.tsx | 0 .../{RushGameSection => RushGameSections}/FinalResult.tsx | 2 +- .../SelectedCard.tsx | 6 +++--- client/src/pages/RushGame/index.tsx | 8 ++++---- client/src/types/rushGame.ts | 1 - 11 files changed, 12 insertions(+), 13 deletions(-) rename client/src/features/RushGame/{RushGameCard => RushGameComponents}/RushCard.tsx (100%) rename client/src/features/RushGame/{RushGameCard => RushGameComponents}/RushCardComparison.tsx (97%) rename client/src/features/RushGame/{RushGameCard => RushGameComponents}/RushCardCurrentRatio.tsx (98%) rename client/src/features/RushGame/{RushGameCard => RushGameComponents}/RushCardResultDescription.tsx (100%) rename client/src/features/RushGame/{RushGameCard => RushGameComponents}/RushCountdown.tsx (100%) rename client/src/features/RushGame/{RushGameSection => RushGameSections}/CardOptions.tsx (84%) rename client/src/features/RushGame/{RushGameSection => RushGameSections}/Countdown.tsx (100%) rename client/src/features/RushGame/{RushGameSection => RushGameSections}/FinalResult.tsx (98%) rename client/src/features/RushGame/{RushGameSection => RushGameSections}/SelectedCard.tsx (92%) diff --git a/client/src/features/RushGame/RushGameCard/RushCard.tsx b/client/src/features/RushGame/RushGameComponents/RushCard.tsx similarity index 100% rename from client/src/features/RushGame/RushGameCard/RushCard.tsx rename to client/src/features/RushGame/RushGameComponents/RushCard.tsx diff --git a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx b/client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx similarity index 97% rename from client/src/features/RushGame/RushGameCard/RushCardComparison.tsx rename to client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx index 5f174cac..0b71e9c0 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx @@ -3,7 +3,7 @@ import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; -import RushCard from "@/features/RushGame/RushGameCard/RushCard.tsx"; +import RushCard from "@/features/RushGame/RushGameComponents/RushCard.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { CardOption } from "@/types/rushGame.ts"; diff --git a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx similarity index 98% rename from client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx rename to client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx index 200877dd..aa0855e3 100644 --- a/client/src/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx @@ -1,7 +1,7 @@ import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; import { CARD_TYPE } from "@/constants/Rush/rushCard.ts"; -import RushProgressBar from "@/features/RushGame/RushGameCard/RushProgressBar.tsx"; +import RushProgressBar from "@/features/RushGame/RushGameComponents/RushProgressBar.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; import { CardOption } from "@/types/rushGame.ts"; diff --git a/client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx b/client/src/features/RushGame/RushGameComponents/RushCardResultDescription.tsx similarity index 100% rename from client/src/features/RushGame/RushGameCard/RushCardResultDescription.tsx rename to client/src/features/RushGame/RushGameComponents/RushCardResultDescription.tsx diff --git a/client/src/features/RushGame/RushGameCard/RushCountdown.tsx b/client/src/features/RushGame/RushGameComponents/RushCountdown.tsx similarity index 100% rename from client/src/features/RushGame/RushGameCard/RushCountdown.tsx rename to client/src/features/RushGame/RushGameComponents/RushCountdown.tsx diff --git a/client/src/features/RushGame/RushGameSection/CardOptions.tsx b/client/src/features/RushGame/RushGameSections/CardOptions.tsx similarity index 84% rename from client/src/features/RushGame/RushGameSection/CardOptions.tsx rename to client/src/features/RushGame/RushGameSections/CardOptions.tsx index cd6d5f2d..3e60479a 100644 --- a/client/src/features/RushGame/RushGameSection/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSections/CardOptions.tsx @@ -1,7 +1,7 @@ import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushCardComparison from "@/features/RushGame/RushGameCard/RushCardComparison.tsx"; -import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; +import RushCardComparison from "@/features/RushGame/RushGameComponents/RushCardComparison.tsx"; +import RushCountdown from "@/features/RushGame/RushGameComponents/RushCountdown.tsx"; import useToggleContents from "@/hooks/useToggleContents.ts"; export default function CardOptions() { diff --git a/client/src/features/RushGame/RushGameSection/Countdown.tsx b/client/src/features/RushGame/RushGameSections/Countdown.tsx similarity index 100% rename from client/src/features/RushGame/RushGameSection/Countdown.tsx rename to client/src/features/RushGame/RushGameSections/Countdown.tsx diff --git a/client/src/features/RushGame/RushGameSection/FinalResult.tsx b/client/src/features/RushGame/RushGameSections/FinalResult.tsx similarity index 98% rename from client/src/features/RushGame/RushGameSection/FinalResult.tsx rename to client/src/features/RushGame/RushGameSections/FinalResult.tsx index b72f1547..6f531ced 100644 --- a/client/src/features/RushGame/RushGameSection/FinalResult.tsx +++ b/client/src/features/RushGame/RushGameSections/FinalResult.tsx @@ -6,7 +6,7 @@ import Category from "@/components/Category"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_TYPE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushProgressBar from "@/features/RushGame/RushGameCard/RushProgressBar.tsx"; +import RushProgressBar from "@/features/RushGame/RushGameComponents/RushProgressBar.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { GetRushResultResponse } from "@/types/rushApi.ts"; diff --git a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx b/client/src/features/RushGame/RushGameSections/SelectedCard.tsx similarity index 92% rename from client/src/features/RushGame/RushGameSection/SelectedCard.tsx rename to client/src/features/RushGame/RushGameSections/SelectedCard.tsx index a5c021f3..f4bdd46d 100644 --- a/client/src/features/RushGame/RushGameSection/SelectedCard.tsx +++ b/client/src/features/RushGame/RushGameSections/SelectedCard.tsx @@ -1,9 +1,9 @@ import { useEffect } from "react"; import { motion } from "framer-motion"; import { ASCEND, DISSOLVE, SCROLL_MOTION } from "@/constants/animation.ts"; -import RushCardCurrentRatio from "@/features/RushGame/RushGameCard/RushCardCurrentRatio.tsx"; -import RushCardResultDescription from "@/features/RushGame/RushGameCard/RushCardResultDescription.tsx"; -import RushCountdown from "@/features/RushGame/RushGameCard/RushCountdown.tsx"; +import RushCardCurrentRatio from "@/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx"; +import RushCardResultDescription from "@/features/RushGame/RushGameComponents/RushCardResultDescription.tsx"; +import RushCountdown from "@/features/RushGame/RushGameComponents/RushCountdown.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; import ArrowLeftIcon from "/public/assets/icons/arrow-line-left.svg?react"; diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index 002f181e..bad6f336 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -1,10 +1,10 @@ import { motion } from "framer-motion"; import CTAButton from "@/components/CTAButton"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import CardOptions from "@/features/RushGame/RushGameSection/CardOptions.tsx"; -import Countdown from "@/features/RushGame/RushGameSection/Countdown.tsx"; -import FinalResult from "@/features/RushGame/RushGameSection/FinalResult.tsx"; -import SelectedCard from "@/features/RushGame/RushGameSection/SelectedCard.tsx"; +import CardOptions from "@/features/RushGame/RushGameSections/CardOptions.tsx"; +import Countdown from "@/features/RushGame/RushGameSections/Countdown.tsx"; +import FinalResult from "@/features/RushGame/RushGameSections/FinalResult.tsx"; +import SelectedCard from "@/features/RushGame/RushGameSections/SelectedCard.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; // TODO: 계속 카운트 다운에 맞춰 매초 렌더링 되는 문제 해결 diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index d4856561..e5c1b479 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -11,7 +11,6 @@ export interface CardOptionState { selectionCount: number; } -// TODO: 추후 밖에서 안쓰는 함수들 제거 export interface RushGameContextType { gameState: { phase: GamePhase; From 9f63c0a8622eea5d7ed597f10c404ed891dec2f2 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 18:14:52 +0900 Subject: [PATCH 101/111] =?UTF-8?q?refactor:=20RushGame=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=83=81=EC=88=98=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EB=B0=8F=20=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/Rush/rushCard.ts | 46 +++--- client/src/contexts/rushGameContext.tsx | 135 ++++++++++-------- .../RushGame/RushGameComponents/RushCard.tsx | 3 +- .../RushGameComponents/RushCardComparison.tsx | 18 +-- .../RushCardCurrentRatio.tsx | 18 +-- .../RushGameComponents/RushProgressBar.tsx | 3 +- .../RushGame/RushGameSections/FinalResult.tsx | 20 +-- client/src/pages/RushGame/index.tsx | 7 +- client/src/types/rushGame.ts | 8 +- 9 files changed, 147 insertions(+), 111 deletions(-) diff --git a/client/src/constants/Rush/rushCard.ts b/client/src/constants/Rush/rushCard.ts index 0db3a20b..d28f0474 100644 --- a/client/src/constants/Rush/rushCard.ts +++ b/client/src/constants/Rush/rushCard.ts @@ -1,7 +1,10 @@ -export const CARD_TYPE = { - LEFT_OPTIONS: 1, - RIGHT_OPTIONS: 2, -} as const; +import { CardColor } from "@/types/rushGame.ts"; + +export const CARD_PHASE = { + NOT_STARTED: "NOT_STARTED", + IN_PROGRESS: "IN_PROGRESS", + COMPLETED: "COMPLETED", +}; export const CARD_COLOR = { BLUE: "blue", @@ -10,7 +13,12 @@ export const CARD_COLOR = { GREEN: "green", } as const; -// TODO: 카드 색상 랜덤 기능 구현 후 불필요한 상수 데이터 삭제 +export const CARD_OPTION = { + LEFT_OPTIONS: 1, + RIGHT_OPTIONS: 2, +} as const; + +// TODO: 카드 색상 랜덤 기능 구현 후 불필요한 상수 데이터 삭제 (CARD_DAYS, CARD_COLORS) export const CARD_DAYS = { DAY1: 1, DAY2: 2, @@ -22,32 +30,32 @@ export const CARD_DAYS = { export const CARD_COLORS: { [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { - [CARD_TYPE.LEFT_OPTIONS]: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; - [CARD_TYPE.RIGHT_OPTIONS]: (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; + [CARD_OPTION.LEFT_OPTIONS]: CardColor; + [CARD_OPTION.RIGHT_OPTIONS]: CardColor; }; } = { [CARD_DAYS.DAY1]: { - [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.GREEN, - [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.BLUE, + [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.GREEN, + [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.BLUE, }, [CARD_DAYS.DAY2]: { - [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.YELLOW, - [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.RED, + [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.YELLOW, + [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.RED, }, [CARD_DAYS.DAY3]: { - [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.BLUE, - [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.RED, + [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.BLUE, + [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.RED, }, [CARD_DAYS.DAY4]: { - [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.GREEN, - [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, + [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.GREEN, + [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, }, [CARD_DAYS.DAY5]: { - [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.GREEN, - [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.RED, + [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.GREEN, + [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.RED, }, [CARD_DAYS.DAY6]: { - [CARD_TYPE.LEFT_OPTIONS]: CARD_COLOR.BLUE, - [CARD_TYPE.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, + [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.BLUE, + [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.YELLOW, }, }; diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 88909f93..706a76c0 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,9 +1,9 @@ import { ReactNode, createContext, useCallback, useEffect, useState } from "react"; import { useCookies } from "react-cookie"; -import { useLoaderData } from "react-router-dom"; +import { useLoaderData, useNavigate } from "react-router-dom"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { CARD_COLOR, CARD_TYPE } from "@/constants/Rush/rushCard"; +import { CARD_COLOR, CARD_OPTION, CARD_PHASE } from "@/constants/Rush/rushCard"; import useCountdown from "@/hooks/useCountdown.ts"; import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/types/rushGame"; @@ -11,17 +11,18 @@ import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/t export const RushGameContext = createContext(undefined); export const RushGameProvider = ({ children }: { children: ReactNode }) => { + const navigate = useNavigate(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const rushData = useLoaderData() as GetTotalRushEventsResponse; - const [initialPreCountdown, setInitialPreCountdown] = useState(null); - const [initialRunCountdown, setInitialRunCountdown] = useState(null); + const [_initialPreCountdown, setInitialPreCountdown] = useState(null); + const [_initialRunCountdown, setInitialRunCountdown] = useState(null); const [gameState, setGameState] = useState({ - phase: "NOT_STARTED", + phase: CARD_PHASE.NOT_STARTED, userParticipatedStatus: false, - userSelectedOption: CARD_TYPE.LEFT_OPTIONS, + userSelectedOption: CARD_OPTION.LEFT_OPTIONS, cardOptions: { - [CARD_TYPE.LEFT_OPTIONS]: { + [CARD_OPTION.LEFT_OPTIONS]: { mainText: "", subText: "", resultMainText: "", @@ -29,7 +30,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { color: CARD_COLOR.GREEN, selectionCount: 0, }, - [CARD_TYPE.RIGHT_OPTIONS]: { + [CARD_OPTION.RIGHT_OPTIONS]: { mainText: "", subText: "", resultMainText: "", @@ -65,51 +66,6 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [] ); - useEffect(() => { - const currentEvent = rushData.events.find( - (event) => event.rushEventId === rushData.todayEventId - ); - if (currentEvent) { - const serverTime = new Date(rushData.serverTime).getTime(); - const startTime = new Date(currentEvent.startDateTime).getTime(); - const endTime = new Date(currentEvent.endDateTime).getTime(); - - switch (gameState.phase) { - case "NOT_STARTED": - if (rushData.serverTime && currentEvent?.startDateTime) { - const preCountdown = Math.max( - 0, - Math.floor((startTime - serverTime) / 1000) - ); - setInitialPreCountdown(preCountdown); - } - break; - case "IN_PROGRESS": - if (rushData.serverTime && currentEvent?.endDateTime) { - const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); - setInitialRunCountdown(runCountdown); - } - break; - } - } - }, [rushData, gameState.phase]); - - // const preCountdown = useCountdown(initialPreCountdown || 0); - // const runCountdown = useCountdown(initialRunCountdown || 0); - - const preCountdown = useCountdown(1); - const runCountdown = useCountdown(10); - - useEffect(() => { - if (preCountdown <= 0 && gameState.phase === "NOT_STARTED") { - setGamePhase("IN_PROGRESS"); - } else if (runCountdown <= 0 && gameState.phase === "IN_PROGRESS") { - setGamePhase("COMPLETED"); - } - }, [preCountdown, runCountdown]); - - // console.log(gameState.cardOptions); - const updateUserStatusAndSelectedOption = useCallback( async (token: string, selectedOption: CardOption) => { try { @@ -145,10 +101,10 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { const rushBalanceData = await RushAPI.getRushBalance(cookies[COOKIE_TOKEN_KEY]); const { leftOption, rightOption } = rushBalanceData; - updateCardOptions(CARD_TYPE.LEFT_OPTIONS, { + updateCardOptions(CARD_OPTION.LEFT_OPTIONS, { selectionCount: leftOption, }); - updateCardOptions(CARD_TYPE.RIGHT_OPTIONS, { + updateCardOptions(CARD_OPTION.RIGHT_OPTIONS, { selectionCount: rightOption, }); } catch (error) { @@ -159,8 +115,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { const getOptionRatio = useCallback( (option: CardOption): number => { const total = - gameState.cardOptions[CARD_TYPE.LEFT_OPTIONS].selectionCount + - gameState.cardOptions[CARD_TYPE.RIGHT_OPTIONS].selectionCount; + gameState.cardOptions[CARD_OPTION.LEFT_OPTIONS].selectionCount + + gameState.cardOptions[CARD_OPTION.RIGHT_OPTIONS].selectionCount; if (total === 0) return 0; const ratio = (gameState.cardOptions[option].selectionCount / total) * 100; return Math.round(ratio * 100) / 100; @@ -168,6 +124,71 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [gameState.cardOptions] ); + useEffect(() => { + const currentEvent = rushData.events.find( + (event) => event.rushEventId === rushData.todayEventId + ); + if (currentEvent) { + const serverTime = new Date(rushData.serverTime).getTime(); + const startTime = new Date(currentEvent.startDateTime).getTime(); + const endTime = new Date(currentEvent.endDateTime).getTime(); + + switch (gameState.phase) { + case CARD_PHASE.NOT_STARTED: + if (rushData.serverTime && currentEvent?.startDateTime) { + const preCountdown = Math.max( + 0, + Math.floor((startTime - serverTime) / 1000) + ); + setInitialPreCountdown(preCountdown); + } + break; + case CARD_PHASE.IN_PROGRESS: + if (rushData.serverTime && currentEvent?.endDateTime) { + const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); + setInitialRunCountdown(runCountdown); + } + break; + } + } + }, [rushData, gameState.phase]); + + // const preCountdown = useCountdown(initialPreCountdown || 0); + // const runCountdown = useCountdown(initialRunCountdown || 0); + + // TEST COUNTDOWN CODE + const preCountdown = useCountdown(3); + const runCountdown = useCountdown(10); + + useEffect(() => { + if (preCountdown <= 0 && gameState.phase === CARD_PHASE.NOT_STARTED) { + setGamePhase(CARD_PHASE.IN_PROGRESS); + } else if (runCountdown <= 0 && gameState.phase === CARD_PHASE.IN_PROGRESS) { + setGamePhase(CARD_PHASE.COMPLETED); + } + }, [preCountdown, runCountdown]); + + // useEffect(() => { + // const currentEvent = rushData.events.find( + // (event) => event.rushEventId === rushData.todayEventId + // ); + // + // if (currentEvent && gameState.phase === CARD_PHASE.COMPLETED) { + // const serverTime = new Date(rushData.serverTime).getTime(); + // const endTime = new Date(currentEvent.endDateTime).getTime(); + // + // if (!gameState.userParticipatedStatus) { + // if (serverTime > endTime) { + // navigate("/rush"); + // // TODO: 이벤트 참여기간 아닌 분기 처리(이벤트 종료 후 그 당일 12시 직전까지) + // } + // } else { + // // TODO: 참여한 사람일 경우 당일 12시 직전까지 계속 "COMPLETED" 상태 유지 + // // TODO: 12시 지나면 다시 "NOT_STARTED" 상태로 변경 + // } + // } + // }, [gameState.phase, gameState.userParticipatedStatus, rushData, navigate]); + return ( void; diff --git a/client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx b/client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx index 0b71e9c0..dad74e3d 100644 --- a/client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCardComparison.tsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; -import { CARD_COLORS, CARD_DAYS, CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import { CARD_COLORS, CARD_DAYS, CARD_OPTION } from "@/constants/Rush/rushCard.ts"; import RushCard from "@/features/RushGame/RushGameComponents/RushCard.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { CardOption } from "@/types/rushGame.ts"; @@ -23,15 +23,15 @@ export default function RushCardComparison() { // TODO: 카드 색상 랜덤으로 변경 if (todayRushEventData) { - updateCardOptions(CARD_TYPE.LEFT_OPTIONS, { + updateCardOptions(CARD_OPTION.LEFT_OPTIONS, { mainText: todayRushEventData.leftOption.mainText, subText: todayRushEventData.leftOption.subText, - color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.LEFT_OPTIONS], + color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_OPTION.LEFT_OPTIONS], }); - updateCardOptions(CARD_TYPE.RIGHT_OPTIONS, { + updateCardOptions(CARD_OPTION.RIGHT_OPTIONS, { mainText: todayRushEventData.rightOption.mainText, subText: todayRushEventData.rightOption.subText, - color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_TYPE.RIGHT_OPTIONS], + color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_OPTION.RIGHT_OPTIONS], }); } } catch (error) { @@ -57,8 +57,8 @@ export default function RushCardComparison() { } }; - const leftOptionData = gameState.cardOptions[CARD_TYPE.LEFT_OPTIONS]; - const rightOptionData = gameState.cardOptions[CARD_TYPE.RIGHT_OPTIONS]; + const leftOptionData = gameState.cardOptions[CARD_OPTION.LEFT_OPTIONS]; + const rightOptionData = gameState.cardOptions[CARD_OPTION.RIGHT_OPTIONS]; return (
@@ -66,7 +66,7 @@ export default function RushCardComparison() { color={leftOptionData.color} mainText={leftOptionData.mainText} subText={leftOptionData.subText} - onClick={() => handleCardSelection(CARD_TYPE.LEFT_OPTIONS)} + onClick={() => handleCardSelection(CARD_OPTION.LEFT_OPTIONS)} />

VS @@ -75,7 +75,7 @@ export default function RushCardComparison() { color={rightOptionData.color} mainText={rightOptionData.mainText} subText={rightOptionData.subText} - onClick={() => handleCardSelection(CARD_TYPE.RIGHT_OPTIONS)} + onClick={() => handleCardSelection(CARD_OPTION.RIGHT_OPTIONS)} />

); diff --git a/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx index aa0855e3..80b17a9b 100644 --- a/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx @@ -1,6 +1,6 @@ import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; -import { CARD_TYPE } from "@/constants/Rush/rushCard.ts"; +import { CARD_OPTION } from "@/constants/Rush/rushCard.ts"; import RushProgressBar from "@/features/RushGame/RushGameComponents/RushProgressBar.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; @@ -34,8 +34,8 @@ function getMessage(leftRatio: number, rightRatio: number, userSelectedOption: C } const userSelectedRatio = - userSelectedOption === CARD_TYPE.LEFT_OPTIONS ? leftRatio : rightRatio; - const oppositeRatio = userSelectedOption === CARD_TYPE.LEFT_OPTIONS ? rightRatio : leftRatio; + userSelectedOption === CARD_OPTION.LEFT_OPTIONS ? leftRatio : rightRatio; + const oppositeRatio = userSelectedOption === CARD_OPTION.LEFT_OPTIONS ? rightRatio : leftRatio; if (userSelectedRatio > oppositeRatio) { return MESSAGES.WINNING; @@ -74,13 +74,13 @@ export default function RushCardCurrentRatio() { useRushGameContext(); const { toggleContents } = useToggleContents(true, 5000); - const leftOptionRatio = getOptionRatio(CARD_TYPE.LEFT_OPTIONS); - const rightOptionRatio = getOptionRatio(CARD_TYPE.RIGHT_OPTIONS); + const leftOptionRatio = getOptionRatio(CARD_OPTION.LEFT_OPTIONS); + const rightOptionRatio = getOptionRatio(CARD_OPTION.RIGHT_OPTIONS); const message = getMessage(leftOptionRatio, rightOptionRatio, gameState.userSelectedOption); - const { mainText: leftMainText } = getSelectedCardInfo(CARD_TYPE.LEFT_OPTIONS); - const { mainText: rightMainText } = getSelectedCardInfo(CARD_TYPE.RIGHT_OPTIONS); + const { mainText: leftMainText } = getSelectedCardInfo(CARD_OPTION.LEFT_OPTIONS); + const { mainText: rightMainText } = getSelectedCardInfo(CARD_OPTION.RIGHT_OPTIONS); return (
@@ -94,13 +94,13 @@ export default function RushCardCurrentRatio() { mainText={leftMainText} userSelectedOptionRatio={leftOptionRatio} oppositeOptionRatio={rightOptionRatio} - isUserSelected={gameState.userSelectedOption === CARD_TYPE.LEFT_OPTIONS} + isUserSelected={gameState.userSelectedOption === CARD_OPTION.LEFT_OPTIONS} />
diff --git a/client/src/pages/RushGame/index.tsx b/client/src/pages/RushGame/index.tsx index bad6f336..96185b9e 100644 --- a/client/src/pages/RushGame/index.tsx +++ b/client/src/pages/RushGame/index.tsx @@ -1,5 +1,6 @@ import { motion } from "framer-motion"; import CTAButton from "@/components/CTAButton"; +import { CARD_PHASE } from "@/constants/Rush/rushCard.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import CardOptions from "@/features/RushGame/RushGameSections/CardOptions.tsx"; import Countdown from "@/features/RushGame/RushGameSections/Countdown.tsx"; @@ -14,15 +15,15 @@ export default function RushGame() { const renderRushGameContent = () => { // console.log(gameState.phase); switch (gameState.phase) { - case "NOT_STARTED": + case CARD_PHASE.NOT_STARTED: return ; - case "IN_PROGRESS": + case CARD_PHASE.IN_PROGRESS: if (!gameState.userParticipatedStatus) { return ; } else { return ; } - case "COMPLETED": + case CARD_PHASE.COMPLETED: return ; default: return null; diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index e5c1b479..18cc990e 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -1,6 +1,8 @@ -export type GamePhase = "NOT_STARTED" | "IN_PROGRESS" | "COMPLETED"; -export type CardColor = "blue" | "red" | "yellow" | "green"; -export type CardOption = 1 | 2; +import { CARD_COLOR, CARD_OPTION, CARD_PHASE } from "@/constants/Rush/rushCard.ts"; + +export type GamePhase = (typeof CARD_PHASE)[keyof typeof CARD_PHASE]; +export type CardColor = (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; +export type CardOption = (typeof CARD_OPTION)[keyof typeof CARD_OPTION]; export interface CardOptionState { mainText: string; From 8a53a53d9dccf3f8397386640add7be5bb8ba58c Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 18:21:25 +0900 Subject: [PATCH 102/111] =?UTF-8?q?chore:=20=EA=B2=8C=EC=9E=84=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20=EB=8B=A4=EC=9A=B4=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 706a76c0..3990d1b0 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -1,6 +1,6 @@ import { ReactNode, createContext, useCallback, useEffect, useState } from "react"; import { useCookies } from "react-cookie"; -import { useLoaderData, useNavigate } from "react-router-dom"; +import { useLoaderData } from "react-router-dom"; import { RushAPI } from "@/apis/rushAPI.ts"; import { COOKIE_TOKEN_KEY } from "@/constants/Auth/token.ts"; import { CARD_COLOR, CARD_OPTION, CARD_PHASE } from "@/constants/Rush/rushCard"; @@ -11,7 +11,7 @@ import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/t export const RushGameContext = createContext(undefined); export const RushGameProvider = ({ children }: { children: ReactNode }) => { - const navigate = useNavigate(); + // const navigate = useNavigate(); const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const rushData = useLoaderData() as GetTotalRushEventsResponse; const [_initialPreCountdown, setInitialPreCountdown] = useState(null); @@ -158,7 +158,7 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { // TEST COUNTDOWN CODE const preCountdown = useCountdown(3); - const runCountdown = useCountdown(10); + const runCountdown = useCountdown(30); useEffect(() => { if (preCountdown <= 0 && gameState.phase === CARD_PHASE.NOT_STARTED) { From c02924a9ec479d9db7c427bc92404a5999d74132 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Thu, 15 Aug 2024 22:56:08 +0900 Subject: [PATCH 103/111] =?UTF-8?q?refactor:=20useAuth=20=ED=9B=85=20?= =?UTF-8?q?=EC=9E=AC=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/features/Rush/Common/Headline.tsx | 56 +------ client/src/hooks/useAuth.ts | 154 ++++++++----------- client/src/pages/Lottery/index.tsx | 56 +------ 3 files changed, 70 insertions(+), 196 deletions(-) diff --git a/client/src/features/Rush/Common/Headline.tsx b/client/src/features/Rush/Common/Headline.tsx index d9348788..a1c0d5d2 100644 --- a/client/src/features/Rush/Common/Headline.tsx +++ b/client/src/features/Rush/Common/Headline.tsx @@ -1,67 +1,21 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback } from "react"; import { motion } from "framer-motion"; -import { useCookies } from "react-cookie"; -import { useLoaderData, useLocation, useNavigate } from "react-router-dom"; -import { AuthAPI } from "@/apis/authAPI.ts"; +import { useLoaderData } from "react-router-dom"; import CTAButton from "@/components/CTAButton"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { COOKIE_KEY } from "@/constants/cookie.ts"; -import useFetch from "@/hooks/useFetch.ts"; -import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext.ts"; -import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext.ts"; +import { useAuth } from "@/hooks/useAuth.ts"; import usePopup from "@/hooks/usePopup.tsx"; import useToast from "@/hooks/useToast.tsx"; -import { PostAuthResponse } from "@/types/authApi.ts"; -import { PHONE_NUMBER_ACTION } from "@/types/phoneNumber.ts"; import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; import { SectionKeyProps } from "@/types/sections.ts"; import { getMsTime } from "@/utils/getMsTime.ts"; export function Headline({ id }: SectionKeyProps) { - const navigate = useNavigate(); - const location = useLocation(); - const queryParams = new URLSearchParams(location.search); - const inviteUser = queryParams.get(COOKIE_KEY.INVITE_USER); - const rushData = useLoaderData() as GetTotalRushEventsResponse; - const [_cookies, setCookie] = useCookies([COOKIE_KEY.ACCESS_TOKEN, COOKIE_KEY.INVITE_USER]); - - const { - data: authToken, - isSuccess: isSuccessGetAuthToken, - fetchData: getAuthToken, - } = useFetch((val: string) => - AuthAPI.getAuthToken({ phoneNumber: val }) - ); - - const { phoneNumber } = usePhoneNumberStateContext(); - const dispatch = usePhoneNumberDispatchContext(); - - const [phoneNumberState, setPhoneNumberState] = useState(phoneNumber); - - useEffect(() => { - if (inviteUser) { - setCookie(COOKIE_KEY.INVITE_USER, inviteUser); - } - }, [inviteUser]); - - useEffect(() => { - if (authToken && isSuccessGetAuthToken) { - setCookie(COOKIE_KEY.ACCESS_TOKEN, authToken.accessToken); - dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: phoneNumberState }); - navigate("/rush/game"); - } - }, [authToken, isSuccessGetAuthToken]); - - const handlePhoneNumberChange = (val: string) => { - setPhoneNumberState(val); - }; - - const handlePhoneNumberConfirm = async (val: string) => { - await getAuthToken(val); - }; + const { phoneNumberState, handlePhoneNumberChange, handlePhoneNumberConfirm } = + useAuth("/rush/game"); const { handleOpenPopup, PopupComponent } = usePopup({ phoneNumber: phoneNumberState, diff --git a/client/src/hooks/useAuth.ts b/client/src/hooks/useAuth.ts index 6637e7a7..2a7b274d 100644 --- a/client/src/hooks/useAuth.ts +++ b/client/src/hooks/useAuth.ts @@ -1,94 +1,60 @@ -// import { useCallback, useEffect, useState } from "react"; -// import { useCookies } from "react-cookie"; -// import { useLoaderData, useLocation, useNavigate } from "react-router-dom"; -// import { AuthAPI } from "@/apis/authAPI.ts"; -// import { COOKIE_KEY } from "@/constants/cookie.ts"; -// import useFetch from "@/hooks/useFetch.ts"; -// import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext.ts"; -// import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext.ts"; -// import usePopup from "@/hooks/usePopup.tsx"; -// import useToast from "@/hooks/useToast.tsx"; -// import { PostAuthResponse } from "@/types/authApi.ts"; -// import { GetLotteryResponse } from "@/types/lotteryApi.ts"; -// import { PHONE_NUMBER_ACTION } from "@/types/phoneNumber.ts"; -// import { getMsTime } from "@/utils/getMsTime.ts"; -// -// interface UseAuthProps { -// eventStartDate: string; -// eventEndDate: string; -// confirmUrl: string; -// } -// -// export default function useAuth({ eventStartDate, eventEndDate, confirmUrl, data }: UseAuthProps) { -// const [_cookies, setCookie] = useCookies([COOKIE_KEY.ACCESS_TOKEN, COOKIE_KEY.INVITE_USER]); -// -// const navigate = useNavigate(); -// const location = useLocation(); -// const queryParams = new URLSearchParams(location.search); -// const inviteUser = queryParams.get(COOKIE_KEY.INVITE_USER); -// -// const { -// data: authToken, -// isSuccess: isSuccessGetAuthToken, -// fetchData: getAuthToken, -// } = useFetch((val: string) => -// AuthAPI.getAuthToken({ phoneNumber: val }) -// ); -// -// const { phoneNumber } = usePhoneNumberStateContext(); -// const dispatch = usePhoneNumberDispatchContext(); -// -// const [phoneNumberState, setPhoneNumberState] = useState(phoneNumber); -// -// useEffect(() => { -// if (inviteUser) { -// setCookie(COOKIE_KEY.INVITE_USER, inviteUser); -// } -// }, [inviteUser]); -// -// useEffect(() => { -// if (authToken && isSuccessGetAuthToken) { -// setCookie(COOKIE_KEY.ACCESS_TOKEN, authToken.accessToken); -// dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: phoneNumberState }); -// navigate(confirmUrl); -// } -// }, [authToken, isSuccessGetAuthToken]); -// -// const handlePhoneNumberChange = (val: string) => { -// setPhoneNumberState(val); -// }; -// -// const handlePhoneNumberConfirm = async (val: string) => { -// const data = await AuthAPI.getAuthToken({ phoneNumber: val }); -// -// setCookie(COOKIE_KEY.ACCESS_TOKEN, data.accessToken, { path: "/" }); -// dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: val }); -// }; -// -// const { handleOpenPopup, PopupComponent } = usePopup({ -// phoneNumber: phoneNumberState, -// handlePhoneNumberChange, -// handlePhoneNumberConfirm, -// }); -// const { showToast, ToastComponent } = useToast("이벤트 기간이 아닙니다"); -// -// const handleClickShortCut = useCallback(() => { -// const startDate = getMsTime(eventStartDate); -// const endDate = getMsTime(eventEndDate); -// const currentDate = new Date().getTime(); -// -// const isEventPeriod = currentDate >= startDate && currentDate <= endDate; -// -// if (isEventPeriod) { -// handleOpenPopup(); -// } else { -// showToast(); -// } -// }, [data]); -// -// return { -// handleClickShortCut, -// PopupComponent, -// ToastComponent, -// }; -// } +import { useEffect, useState } from "react"; +import { useCookies } from "react-cookie"; +import { useLocation, useNavigate } from "react-router-dom"; +import { AuthAPI } from "@/apis/authAPI"; +import { COOKIE_KEY } from "@/constants/cookie"; +import useFetch from "@/hooks/useFetch"; +import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext"; +import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext"; +import { PostAuthResponse } from "@/types/authApi"; +import { PHONE_NUMBER_ACTION } from "@/types/phoneNumber"; + +export function useAuth(redirectUrl: string) { + const navigate = useNavigate(); + const location = useLocation(); + const queryParams = new URLSearchParams(location.search); + const inviteUser = queryParams.get(COOKIE_KEY.INVITE_USER); + + const [_cookies, setCookie] = useCookies([COOKIE_KEY.ACCESS_TOKEN, COOKIE_KEY.INVITE_USER]); + + const { + data: authToken, + isSuccess: isSuccessGetAuthToken, + fetchData: getAuthToken, + } = useFetch((val: string) => + AuthAPI.getAuthToken({ phoneNumber: val }) + ); + + const { phoneNumber } = usePhoneNumberStateContext(); + const dispatch = usePhoneNumberDispatchContext(); + + const [phoneNumberState, setPhoneNumberState] = useState(phoneNumber); + + useEffect(() => { + if (inviteUser) { + setCookie(COOKIE_KEY.INVITE_USER, inviteUser); + } + }, [inviteUser]); + + useEffect(() => { + if (authToken && isSuccessGetAuthToken) { + setCookie(COOKIE_KEY.ACCESS_TOKEN, authToken.accessToken); + dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: phoneNumberState }); + navigate(redirectUrl); + } + }, [authToken, isSuccessGetAuthToken]); + + const handlePhoneNumberChange = (val: string) => { + setPhoneNumberState(val); + }; + + const handlePhoneNumberConfirm = async (val: string) => { + await getAuthToken(val); + }; + + return { + phoneNumberState, + handlePhoneNumberChange, + handlePhoneNumberConfirm, + }; +} diff --git a/client/src/pages/Lottery/index.tsx b/client/src/pages/Lottery/index.tsx index 2b3d3b27..766bead7 100644 --- a/client/src/pages/Lottery/index.tsx +++ b/client/src/pages/Lottery/index.tsx @@ -1,11 +1,8 @@ -import { useCallback, useEffect, useState } from "react"; -import { useCookies } from "react-cookie"; -import { useLoaderData, useLocation, useNavigate } from "react-router-dom"; -import { AuthAPI } from "@/apis/authAPI"; +import { useCallback } from "react"; +import { useLoaderData } from "react-router-dom"; import Footer from "@/components/Footer"; import Notice from "@/components/Notice"; import { LOTTERY_SECTIONS } from "@/constants/PageSections/sections.ts"; -import { COOKIE_KEY } from "@/constants/cookie"; import { CustomDesign, HeadLamp, @@ -17,16 +14,12 @@ import { SmileBadge, WheelDesign, } from "@/features/Lottery"; -import useFetch from "@/hooks/useFetch"; +import { useAuth } from "@/hooks/useAuth.ts"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver.ts"; -import usePhoneNumberDispatchContext from "@/hooks/usePhoneNumberDispatchContext"; -import usePhoneNumberStateContext from "@/hooks/usePhoneNumberStateContext"; import usePopup from "@/hooks/usePopup"; import useScrollTop from "@/hooks/useScrollTop"; import useToast from "@/hooks/useToast"; -import { PostAuthResponse } from "@/types/authApi"; import { GetLotteryResponse } from "@/types/lotteryApi"; -import { PHONE_NUMBER_ACTION } from "@/types/phoneNumber"; import { getMsTime } from "@/utils/getMsTime"; export default function Lottery() { @@ -35,49 +28,10 @@ export default function Lottery() { darkSections: [LOTTERY_SECTIONS.HEADLINE, LOTTERY_SECTIONS.SHORT_CUT], }); - const navigate = useNavigate(); - const location = useLocation(); - const queryParams = new URLSearchParams(location.search); - const inviteUser = queryParams.get(COOKIE_KEY.INVITE_USER); - const lotteryData = useLoaderData() as GetLotteryResponse; - const [_cookies, setCookie] = useCookies([COOKIE_KEY.ACCESS_TOKEN, COOKIE_KEY.INVITE_USER]); - - const { - data: authToken, - isSuccess: isSuccessGetAuthToken, - fetchData: getAuthToken, - } = useFetch((val: string) => - AuthAPI.getAuthToken({ phoneNumber: val }) - ); - - const { phoneNumber } = usePhoneNumberStateContext(); - const dispatch = usePhoneNumberDispatchContext(); - - const [phoneNumberState, setPhoneNumberState] = useState(phoneNumber); - - useEffect(() => { - if (inviteUser) { - setCookie(COOKIE_KEY.INVITE_USER, inviteUser); - } - }, [inviteUser]); - - useEffect(() => { - if (authToken && isSuccessGetAuthToken) { - setCookie(COOKIE_KEY.ACCESS_TOKEN, authToken.accessToken); - dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: phoneNumberState }); - navigate("/lottery/custom"); - } - }, [authToken, isSuccessGetAuthToken]); - - const handlePhoneNumberChange = (val: string) => { - setPhoneNumberState(val); - }; - - const handlePhoneNumberConfirm = async (val: string) => { - await getAuthToken(val); - }; + const { phoneNumberState, handlePhoneNumberChange, handlePhoneNumberConfirm } = + useAuth("/lottery/custom"); const { handleOpenPopup, PopupComponent } = usePopup({ phoneNumber: phoneNumberState, From 06ec8b9161876991784a129b5a438cbfa32c22d1 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 16 Aug 2024 00:36:40 +0900 Subject: [PATCH 104/111] =?UTF-8?q?refactor:=20getMsTime=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 11 ++++++----- client/src/features/Main/Rush.tsx | 5 +++-- client/src/utils/formatDate.ts | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 52af54f5..e6f4080c 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -7,6 +7,7 @@ import { COOKIE_KEY } from "@/constants/cookie.ts"; import useCountdown from "@/hooks/useCountdown.ts"; import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/types/rushGame"; +import { getMsTime } from "@/utils/getMsTime.ts"; export const RushGameContext = createContext(undefined); @@ -129,9 +130,9 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { (event) => event.rushEventId === rushData.todayEventId ); if (currentEvent) { - const serverTime = new Date(rushData.serverTime).getTime(); - const startTime = new Date(currentEvent.startDateTime).getTime(); - const endTime = new Date(currentEvent.endDateTime).getTime(); + const serverTime = getMsTime(rushData.serverTime); + const startTime = getMsTime(currentEvent.startDateTime); + const endTime = getMsTime(currentEvent.endDateTime); switch (gameState.phase) { case CARD_PHASE.NOT_STARTED: @@ -174,8 +175,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { // ); // // if (currentEvent && gameState.phase === CARD_PHASE.COMPLETED) { - // const serverTime = new Date(rushData.serverTime).getTime(); - // const endTime = new Date(currentEvent.endDateTime).getTime(); + // const serverTime = getMsTime(rushData.serverTime); + // const endTime = getMsTime(currentEvent.endDateTime); // // if (!gameState.userParticipatedStatus) { // if (serverTime > endTime) { diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 8ac803cc..d5a337aa 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -5,6 +5,7 @@ import { RUSH_EVENT_DATA } from "@/constants/Main/rushEventData.ts"; import { Section } from "@/features/Main/Section.tsx"; import { SectionKeyProps } from "@/types/sections.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; +import { getMsTime } from "@/utils/getMsTime.ts"; function Rush({ id }: SectionKeyProps) { const [rushEvents, setRushEvents] = useState([]); @@ -14,14 +15,14 @@ function Rush({ id }: SectionKeyProps) { useEffect(() => { (async () => { const rushData = await RushAPI.getRush(); - const serverDateTime = new Date(rushData.serverTime); + const serverDateTime = getMsTime(rushData.serverTime); setStartDateTime(rushData.eventStartDate); setEndDateTime(rushData.eventEndDate); const events = rushData.events.map((event, idx) => { const rushEvent = RUSH_EVENT_DATA[idx]; - const eventEndTime = new Date(event.endDateTime); + const eventEndTime = getMsTime(event.endDateTime); return { id: event.rushEventId, diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index 6c5da89f..f738acf1 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -2,7 +2,7 @@ import { EventDateData } from "@/components/Notice"; const LOADING_DATE_MESSAGE = "날짜를 불러오는 중입니다..."; -export const parseDate = (dateString: string): Date | null => { +const parseDate = (dateString: string): Date | null => { const date = new Date(dateString); return isNaN(date.getTime()) ? null : date; }; From d88b744154d02ac0141797ca5e43a5b3fb44c24d Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 16 Aug 2024 00:39:24 +0900 Subject: [PATCH 105/111] =?UTF-8?q?refactor:=20fetchWithTimeout=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 17 +++++++++-------- client/src/apis/totalAPI.ts | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index 53a1e896..20be7f14 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -7,6 +7,7 @@ import { GetTotalRushEventsResponse, PostSelectedRushCardOptionResponse, } from "@/types/rushApi"; +import { fetchWithTimeout } from "@/utils/fetchWithTimeout.ts"; const baseURL = `${import.meta.env.VITE_API_URL}/event/rush`; const headers = { @@ -16,7 +17,7 @@ const headers = { export const RushAPI = { async getRush(): Promise { try { - const response = await fetch(`${baseURL}`, { + const response = await fetchWithTimeout(`${baseURL}`, { method: "GET", headers: headers, }); @@ -30,7 +31,7 @@ export const RushAPI = { token: string ): Promise { try { - const response = await fetch(`${baseURL}/applied`, { + const response = await fetchWithTimeout(`${baseURL}/applied`, { method: "GET", headers: { ...headers, Authorization: `Bearer ${token}` }, }); @@ -42,7 +43,7 @@ export const RushAPI = { }, async getTodayRushEvent(token: string): Promise { try { - const response = await fetch(`${baseURL}/today`, { + const response = await fetchWithTimeout(`${baseURL}/today`, { method: "GET", headers: { ...headers, Authorization: `Bearer ${token}` }, }); @@ -57,7 +58,7 @@ export const RushAPI = { optionId: number ): Promise { try { - const response = await fetch(`${baseURL}/options/${optionId}/apply`, { + const response = await fetchWithTimeout(`${baseURL}/options/${optionId}/apply`, { method: "POST", headers: { ...headers, Authorization: `Bearer ${token}` }, }); @@ -77,7 +78,7 @@ export const RushAPI = { optionId: number ): Promise { try { - const response = await fetch(`${baseURL}/options/${optionId}/result`, { + const response = await fetchWithTimeout(`${baseURL}/options/${optionId}/result`, { method: "GET", headers: { ...headers, Authorization: `Bearer ${token}` }, }); @@ -89,7 +90,7 @@ export const RushAPI = { }, async getRushBalance(token: string): Promise { try { - const response = await fetch(`${baseURL}/balance`, { + const response = await fetchWithTimeout(`${baseURL}/balance`, { method: "GET", headers: { ...headers, Authorization: `Bearer ${token}` }, }); @@ -101,7 +102,7 @@ export const RushAPI = { }, async getRushResult(token: string): Promise { try { - const response = await fetch(`${baseURL}/result`, { + const response = await fetchWithTimeout(`${baseURL}/result`, { method: "GET", headers: { ...headers, Authorization: `Bearer ${token}` }, }); @@ -113,7 +114,7 @@ export const RushAPI = { }, async getRushTodayEventTest(token: string): Promise { try { - const response = await fetch(`${baseURL}/today/test`, { + const response = await fetchWithTimeout(`${baseURL}/today/test`, { method: "GET", headers: { ...headers, Authorization: `Bearer ${token}` }, }); diff --git a/client/src/apis/totalAPI.ts b/client/src/apis/totalAPI.ts index 5d4b732a..78a8ba81 100644 --- a/client/src/apis/totalAPI.ts +++ b/client/src/apis/totalAPI.ts @@ -1,4 +1,5 @@ import { GetTotalEventDateResponse } from "@/types/totalApi.ts"; +import { fetchWithTimeout } from "@/utils/fetchWithTimeout.ts"; const baseURL = `${import.meta.env.VITE_API_URL}/event/total`; const headers = { @@ -8,7 +9,7 @@ const headers = { export const TotalAPI = { async getTotal(): Promise { try { - const response = await fetch(`${baseURL}`, { + const response = await fetchWithTimeout(`${baseURL}`, { method: "GET", headers: headers, }); From ebf96db4ac2fde4a1c06782662652a3f3cc1d25e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 16 Aug 2024 11:17:10 +0900 Subject: [PATCH 106/111] =?UTF-8?q?chore:=20=EC=B9=B4=EC=9A=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/contexts/rushGameContext.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index e6f4080c..e6aa9ac7 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -154,12 +154,12 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { } }, [rushData, gameState.phase]); - // const preCountdown = useCountdown(initialPreCountdown || 0); - // const runCountdown = useCountdown(initialRunCountdown || 0); + // const preCountdown = useCountdown(initialPreCountdown || 1); + // const runCountdown = useCountdown(initialRunCountdown || 1); // TEST COUNTDOWN CODE - const preCountdown = useCountdown(3); - const runCountdown = useCountdown(30); + const preCountdown = useCountdown(5); + const runCountdown = useCountdown(35); useEffect(() => { if (preCountdown <= 0 && gameState.phase === CARD_PHASE.NOT_STARTED) { From 3d3b90d06d2088e88ec16b1663df886872b8ce6e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 16 Aug 2024 16:27:15 +0900 Subject: [PATCH 107/111] =?UTF-8?q?refactor:=20useFetch=20=ED=9B=85=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 6 +- client/src/components/Notice/index.tsx | 121 +++++++++--------- client/src/contexts/rushGameContext.tsx | 53 +++++--- client/src/features/Main/Headline.tsx | 32 +++-- client/src/features/Main/Lottery.tsx | 25 +++- client/src/features/Main/Rush.tsx | 20 ++- .../RushGameComponents/RushCardComparison.tsx | 87 +++++++------ .../RushCardResultDescription.tsx | 38 ++++-- .../RushGame/RushGameSections/FinalResult.tsx | 26 ++-- client/src/types/rushApi.ts | 4 +- client/src/utils/formatDate.ts | 2 +- 11 files changed, 254 insertions(+), 160 deletions(-) diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index 20be7f14..a2bf00d6 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -5,7 +5,7 @@ import { GetRushUserParticipationStatusResponse, GetTodayRushEventResponse, GetTotalRushEventsResponse, - PostSelectedRushCardOptionResponse, + RushEventStatusCodeResponse, } from "@/types/rushApi"; import { fetchWithTimeout } from "@/utils/fetchWithTimeout.ts"; @@ -56,7 +56,7 @@ export const RushAPI = { async postSelectedRushOptionApply( token: string, optionId: number - ): Promise { + ): Promise { try { const response = await fetchWithTimeout(`${baseURL}/options/${optionId}/apply`, { method: "POST", @@ -112,7 +112,7 @@ export const RushAPI = { throw error; } }, - async getRushTodayEventTest(token: string): Promise { + async getRushTodayEventTest(token: string): Promise { try { const response = await fetchWithTimeout(`${baseURL}/today/test`, { method: "GET", diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index 3b614810..fcce77b4 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -1,6 +1,7 @@ -import React, { memo, useEffect, useState } from "react"; +import React, { memo, useEffect } from "react"; import { LotteryAPI } from "@/apis/lotteryAPI.ts"; import { RushAPI } from "@/apis/rushAPI.ts"; +import useFetch from "@/hooks/useFetch.ts"; import { formatEventDate } from "@/utils/formatDate.ts"; interface EventDateDetails { @@ -30,81 +31,83 @@ const Section: React.FC = ({ title, items, indentedIndices = [] })
); +// TODO: Promise.all 로 묶지 말고 따로 useFetch 써서 하기 const getEventsDateDetails = async (): Promise<{ rush: EventDateDetails; lottery: EventDateDetails; }> => { - try { - const [rushData, lotteryData] = await Promise.all([ - RushAPI.getRush(), - LotteryAPI.getLottery(), - ]); + const [rushData, lotteryData] = await Promise.all([RushAPI.getRush(), LotteryAPI.getLottery()]); - const rushEventDetails: EventDateDetails = { - startDate: rushData.eventStartDate, - endDate: rushData.eventEndDate, - activePeriod: rushData.activePeriod, - }; + const rushEventDetails: EventDateDetails = { + startDate: rushData.eventStartDate, + endDate: rushData.eventEndDate, + activePeriod: rushData.activePeriod, + }; - const lotteryEventDetails: EventDateDetails = { - startDate: lotteryData.eventStartDate, - endDate: lotteryData.eventEndDate, - activePeriod: lotteryData.activePeriod, - }; + const lotteryEventDetails: EventDateDetails = { + startDate: lotteryData.eventStartDate, + endDate: lotteryData.eventEndDate, + activePeriod: lotteryData.activePeriod, + }; - return { - rush: lotteryEventDetails, - lottery: rushEventDetails, - }; - } catch (error) { - console.error("Error: ", error); - return { - rush: { startDate: "", endDate: "", activePeriod: 0 }, - lottery: { startDate: "", endDate: "", activePeriod: 0 }, - }; - } + return { + rush: rushEventDetails, + lottery: lotteryEventDetails, + }; }; function Notice() { - const [eventDateDetails, setEventDateDetails] = useState({}); + const { + data: eventDateDetails, + isSuccess: isSuccessRushAndLottery, + fetchData: getRushAndLotteryEventData, + } = useFetch<{ + rush: EventDateDetails; + lottery: EventDateDetails; + }>(getEventsDateDetails); useEffect(() => { - (async () => { - const details = await getEventsDateDetails(); - setEventDateDetails(details); - })(); + getRushAndLotteryEventData(); }, []); return (

유의사항

-
-
-
+ {isSuccessRushAndLottery && eventDateDetails && ( + <> +
+
+
+ + )}
); } diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index e6aa9ac7..6a7cfe9f 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -5,7 +5,12 @@ import { RushAPI } from "@/apis/rushAPI.ts"; import { CARD_COLOR, CARD_OPTION, CARD_PHASE } from "@/constants/Rush/rushCard"; import { COOKIE_KEY } from "@/constants/cookie.ts"; import useCountdown from "@/hooks/useCountdown.ts"; -import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; +import useFetch from "@/hooks/useFetch.ts"; +import { + GetRushBalanceResponse, + GetRushUserParticipationStatusResponse, + GetTotalRushEventsResponse, +} from "@/types/rushApi.ts"; import { CardOption, CardOptionState, GamePhase, RushGameContextType } from "@/types/rushGame"; import { getMsTime } from "@/utils/getMsTime.ts"; @@ -67,21 +72,28 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [] ); + const { + data: userParticipatedStatus, + isSuccess: isSuccessUserParticipationStatus, + fetchData: getRushUserParticipationStatus, + } = useFetch((token) => + RushAPI.getRushUserParticipationStatus(token) + ); + const updateUserStatusAndSelectedOption = useCallback( async (token: string, selectedOption: CardOption) => { - try { - const userParticipatedStatus = await RushAPI.getRushUserParticipationStatus(token); - setUserParticipationStatus(userParticipatedStatus); - if (userParticipatedStatus) { - setUserSelectedOption(selectedOption); - } - } catch (error) { - console.error("Error: ", error); - } + await getRushUserParticipationStatus(token); + setUserSelectedOption(selectedOption); }, [] ); + useEffect(() => { + if (isSuccessUserParticipationStatus && userParticipatedStatus) { + setUserParticipationStatus(userParticipatedStatus); + } + }, [isSuccessUserParticipationStatus, userParticipatedStatus]); + const getSelectedCardInfo = useCallback( (option: CardOption) => { const cardInfo = gameState.cardOptions[option]; @@ -97,9 +109,18 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { [gameState.userSelectedOption, gameState.cardOptions] ); + const { + data: rushBalanceData, + isSuccess: isSuccessRushBalance, + fetchData: getRushBalance, + } = useFetch((token) => RushAPI.getRushBalance(token)); + const fetchRushBalance = useCallback(async (): Promise => { - try { - const rushBalanceData = await RushAPI.getRushBalance(cookies[COOKIE_KEY.ACCESS_TOKEN]); + await getRushBalance(cookies[COOKIE_KEY.ACCESS_TOKEN]); + }, [cookies, getRushBalance]); + + useEffect(() => { + if (isSuccessRushBalance && rushBalanceData) { const { leftOption, rightOption } = rushBalanceData; updateCardOptions(CARD_OPTION.LEFT_OPTIONS, { @@ -108,10 +129,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { updateCardOptions(CARD_OPTION.RIGHT_OPTIONS, { selectionCount: rightOption, }); - } catch (error) { - console.error("Error: ", error); } - }, [cookies]); + }, [isSuccessRushBalance, rushBalanceData]); const getOptionRatio = useCallback( (option: CardOption): number => { @@ -158,8 +177,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { // const runCountdown = useCountdown(initialRunCountdown || 1); // TEST COUNTDOWN CODE - const preCountdown = useCountdown(5); - const runCountdown = useCountdown(35); + const preCountdown = useCountdown(3); + const runCountdown = useCountdown(10); useEffect(() => { if (preCountdown <= 0 && gameState.phase === CARD_PHASE.NOT_STARTED) { diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index 46566437..d7c44a68 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -7,23 +7,39 @@ import Keyword from "@/components/Keyword"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import { COOKIE_KEY } from "@/constants/cookie.ts"; +import useFetch from "@/hooks/useFetch.ts"; +import { RushEventStatusCodeResponse } from "@/types/rushApi.ts"; import { SectionKeyProps } from "@/types/sections.ts"; +import { GetTotalEventDateResponse } from "@/types/totalApi.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; function Headline({ id }: SectionKeyProps) { const [cookies] = useCookies([COOKIE_KEY.ACCESS_TOKEN]); - const [startDateTime, setStartDateTime] = useState(null); - const [endDateTime, setEndDateTime] = useState(null); + const [startDateTime, setStartDateTime] = useState(""); + const [endDateTime, setEndDateTime] = useState(""); + + // DATA RESET TEST API + const { fetchData: getRushTodayEventTest } = useFetch( + (token) => RushAPI.getRushTodayEventTest(token) + ); + + const { + data: totalData, + isSuccess: isSuccessTotalData, + fetchData: getTotal, + } = useFetch(() => TotalAPI.getTotal()); useEffect(() => { - (async () => { - // DATA RESET TEST API - await RushAPI.getRushTodayEventTest(cookies[COOKIE_KEY.ACCESS_TOKEN]); - const totalData = await TotalAPI.getTotal(); + getRushTodayEventTest(cookies[COOKIE_KEY.ACCESS_TOKEN]); + getTotal(); + }, []); + + useEffect(() => { + if (isSuccessTotalData && totalData) { setStartDateTime(totalData.totalEventStartDate); setEndDateTime(totalData.totalEventEndDate); - })(); - }, []); + } + }, [isSuccessTotalData, totalData]); return (
(null); - const [endDateTime, setEndDateTime] = useState(null); + const [startDateTime, setStartDateTime] = useState(""); + const [endDateTime, setEndDateTime] = useState(""); + + const { + data: lotteryData, + isSuccess: isSuccessLottery, + fetchData: getLottery, + } = useFetch(() => LotteryAPI.getLottery()); useEffect(() => { - (async () => { - const data = await LotteryAPI.getLottery(); - setStartDateTime(data.eventStartDate); - setEndDateTime(data.eventEndDate); - })(); + getLottery(); }, []); + useEffect(() => { + if (isSuccessLottery && lotteryData) { + setStartDateTime(lotteryData.eventStartDate); + setEndDateTime(lotteryData.eventEndDate); + } + }, [isSuccessLottery, lotteryData]); + return (
(""); const [endDateTime, setEndDateTime] = useState(""); + const { + data: rushData, + isSuccess: isSuccessRush, + fetchData: getRush, + } = useFetch(() => RushAPI.getRush()); + + useEffect(() => { + getRush(); + }, []); + useEffect(() => { - (async () => { - const rushData = await RushAPI.getRush(); + if (isSuccessRush && rushData) { const serverDateTime = getMsTime(rushData.serverTime); setStartDateTime(rushData.eventStartDate); @@ -35,10 +46,9 @@ function Rush({ id }: SectionKeyProps) { serverDateTime <= eventEndTime, }; }); - setRushEvents(events); - })(); - }, []); + } + }, [isSuccessRush, rushData]); return (
( + INITIAL_OPTION_NUMBER + ); const { gameState, updateUserStatusAndSelectedOption, updateCardOptions } = useRushGameContext(); - useEffect(() => { - (async () => { - try { - const todayRushEventData = await RushAPI.getTodayRushEvent( - cookies[COOKIE_KEY.ACCESS_TOKEN] - ); + const { + data: todayRushEventData, + isSuccess: isSuccessTodayRushEvent, + fetchData: getTodayRushEvent, + } = useFetch((token) => RushAPI.getTodayRushEvent(token)); - // TODO: 카드 색상 랜덤으로 변경 - if (todayRushEventData) { - updateCardOptions(CARD_OPTION.LEFT_OPTIONS, { - mainText: todayRushEventData.leftOption.mainText, - subText: todayRushEventData.leftOption.subText, - color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_OPTION.LEFT_OPTIONS], - }); - updateCardOptions(CARD_OPTION.RIGHT_OPTIONS, { - mainText: todayRushEventData.rightOption.mainText, - subText: todayRushEventData.rightOption.subText, - color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_OPTION.RIGHT_OPTIONS], - }); - } - } catch (error) { - console.error("Error:", error); - } - })(); + const { + data: postSelectedRushOptionResponse, + isSuccess: isSuccessPostSelectedRushOption, + fetchData: postSelectedRushOptionApply, + } = useFetch( + ({ token, optionId }) => RushAPI.postSelectedRushOptionApply(token, optionId) + ); + + useEffect(() => { + getTodayRushEvent(cookies[COOKIE_KEY.ACCESS_TOKEN]); }, []); + useEffect(() => { + if (isSuccessTodayRushEvent && todayRushEventData) { + // TODO: 카드 색상 랜덤으로 변경 + updateCardOptions(CARD_OPTION.LEFT_OPTIONS, { + mainText: todayRushEventData.leftOption.mainText, + subText: todayRushEventData.leftOption.subText, + color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_OPTION.LEFT_OPTIONS], + }); + updateCardOptions(CARD_OPTION.RIGHT_OPTIONS, { + mainText: todayRushEventData.rightOption.mainText, + subText: todayRushEventData.rightOption.subText, + color: CARD_COLORS[TEMP_CURRENT_DAY][CARD_OPTION.RIGHT_OPTIONS], + }); + } + }, [isSuccessTodayRushEvent, todayRushEventData]); + const handleCardSelection = async (optionId: CardOption) => { - try { - const response = await RushAPI.postSelectedRushOptionApply( - cookies[COOKIE_KEY.ACCESS_TOKEN], - optionId - ); + await postSelectedRushOptionApply({ token: cookies[COOKIE_KEY.ACCESS_TOKEN], optionId }); + setOptionId(optionId); + }; - if (response === 204) { - await updateUserStatusAndSelectedOption(cookies[COOKIE_KEY.ACCESS_TOKEN], optionId); - } else if (response === 404) { - console.log(`Error ${response}`); - } - } catch (error) { - console.error("Error: ", error); + useEffect(() => { + if ( + isSuccessPostSelectedRushOption && + postSelectedRushOptionResponse === 204 && + optionId !== INITIAL_OPTION_NUMBER + ) { + updateUserStatusAndSelectedOption(cookies[COOKIE_KEY.ACCESS_TOKEN], optionId); } - }; + }, [optionId]); const leftOptionData = gameState.cardOptions[CARD_OPTION.LEFT_OPTIONS]; const rightOptionData = gameState.cardOptions[CARD_OPTION.RIGHT_OPTIONS]; diff --git a/client/src/features/RushGame/RushGameComponents/RushCardResultDescription.tsx b/client/src/features/RushGame/RushGameComponents/RushCardResultDescription.tsx index 7477613a..50addc01 100644 --- a/client/src/features/RushGame/RushGameComponents/RushCardResultDescription.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCardResultDescription.tsx @@ -5,7 +5,10 @@ import { RushAPI } from "@/apis/rushAPI.ts"; import Category from "@/components/Category"; import { CARD_COLOR } from "@/constants/Rush/rushCard.ts"; import { COOKIE_KEY } from "@/constants/cookie.ts"; +import useFetch from "@/hooks/useFetch.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; +import { GetRushOptionResultResponse } from "@/types/rushApi.ts"; +import { CardOption } from "@/types/rushGame.ts"; const backgroundGradients = cva( `flex gap-[35px] w-[834px] h-[400px] rounded-800 py-6 px-[37px] justify-between break-keep`, @@ -29,22 +32,31 @@ export default function RushCardResultDescription() { const { gameState, updateCardOptions, getSelectedCardInfo, getOptionRatio } = useRushGameContext(); + const { + data: userResultData, + isSuccess: isSuccessUserResultData, + fetchData: getUserResultData, + } = useFetch( + ({ token, optionId }) => RushAPI.getRushOptionResult(token, optionId) + ); + useEffect(() => { - (async () => { - const userResultData = await RushAPI.getRushOptionResult( - cookies[COOKIE_KEY.ACCESS_TOKEN], - gameState.userSelectedOption - ); - if (userResultData) { - updateCardOptions(gameState.userSelectedOption, { - mainText: userResultData.mainText, - resultMainText: userResultData.resultMainText, - resultSubText: userResultData.resultSubText, - }); - } - })(); + getUserResultData({ + token: cookies[COOKIE_KEY.ACCESS_TOKEN], + optionId: gameState.userSelectedOption, + }); }, []); + useEffect(() => { + if (isSuccessUserResultData && userResultData) { + updateCardOptions(gameState.userSelectedOption, { + mainText: userResultData.mainText, + resultMainText: userResultData.resultMainText, + resultSubText: userResultData.resultSubText, + }); + } + }, [isSuccessUserResultData, userResultData]); + const { mainText, resultMainText, resultSubText, color } = getSelectedCardInfo( gameState.userSelectedOption ); diff --git a/client/src/features/RushGame/RushGameSections/FinalResult.tsx b/client/src/features/RushGame/RushGameSections/FinalResult.tsx index 71e35442..7a187e67 100644 --- a/client/src/features/RushGame/RushGameSections/FinalResult.tsx +++ b/client/src/features/RushGame/RushGameSections/FinalResult.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { motion } from "framer-motion"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; @@ -7,6 +7,7 @@ import { CARD_OPTION } from "@/constants/Rush/rushCard.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import { COOKIE_KEY } from "@/constants/cookie.ts"; import RushProgressBar from "@/features/RushGame/RushGameComponents/RushProgressBar.tsx"; +import useFetch from "@/hooks/useFetch.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { GetRushResultResponse } from "@/types/rushApi.ts"; @@ -47,15 +48,24 @@ function OptionDisplay({ export default function FinalResult() { const [cookies] = useCookies([COOKIE_KEY.ACCESS_TOKEN]); - const [resultData, setResultData] = useState(); const { gameState, getOptionRatio, getSelectedCardInfo, updateCardOptions } = useRushGameContext(); + const { + data: resultData, + isSuccess: isSuccessRushResult, + fetchData: getRushResult, + } = useFetch(() => + RushAPI.getRushResult(cookies[COOKIE_KEY.ACCESS_TOKEN]) + ); + + useEffect(() => { + getRushResult(); + }, []); + useEffect(() => { - (async () => { - const resultData = await RushAPI.getRushResult(cookies[COOKIE_KEY.ACCESS_TOKEN]); + if (resultData && isSuccessRushResult) { const { leftOption, rightOption } = resultData; - setResultData(resultData); updateCardOptions(CARD_OPTION.LEFT_OPTIONS, { selectionCount: leftOption, @@ -63,10 +73,10 @@ export default function FinalResult() { updateCardOptions(CARD_OPTION.RIGHT_OPTIONS, { selectionCount: rightOption, }); - })(); - }, []); + } + }, [resultData, isSuccessRushResult, updateCardOptions]); - const isWinner = resultData?.isWinner || true; + const isWinner = resultData?.winner; const rank = resultData?.rank || 0; const totalParticipants = resultData?.totalParticipants || 0; diff --git a/client/src/types/rushApi.ts b/client/src/types/rushApi.ts index 20fda171..bf87b6af 100644 --- a/client/src/types/rushApi.ts +++ b/client/src/types/rushApi.ts @@ -25,7 +25,7 @@ export interface GetTodayRushEventResponse { rightOption: RushCardType; } -export type PostSelectedRushCardOptionResponse = 204 | 404; +export type RushEventStatusCodeResponse = 204 | 404; export interface GetRushOptionResultResponse { mainText: string; @@ -40,7 +40,7 @@ export interface GetRushBalanceResponse { } export interface GetRushResultResponse { - isWinner: boolean; + winner: boolean; leftOption: number; rightOption: number; rank: number; diff --git a/client/src/utils/formatDate.ts b/client/src/utils/formatDate.ts index f738acf1..6c5da89f 100644 --- a/client/src/utils/formatDate.ts +++ b/client/src/utils/formatDate.ts @@ -2,7 +2,7 @@ import { EventDateData } from "@/components/Notice"; const LOADING_DATE_MESSAGE = "날짜를 불러오는 중입니다..."; -const parseDate = (dateString: string): Date | null => { +export const parseDate = (dateString: string): Date | null => { const date = new Date(dateString); return isNaN(date.getTime()) ? null : date; }; From df54ecdc5d4d4b0aa83ec0c08ef8d9653284cb83 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 16 Aug 2024 16:55:24 +0900 Subject: [PATCH 108/111] =?UTF-8?q?refactor:=20Notice/index.tsx=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=20useFetch=20=ED=9B=85=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=20=EC=8B=9C=20promise.all=20=EB=B9=BC=EA=B3=A0=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Notice/index.tsx | 83 +++++++++++++------------- client/src/utils/formatDate.ts | 4 +- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index fcce77b4..57047504 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -1,7 +1,9 @@ -import React, { memo, useEffect } from "react"; +import React, { memo, useEffect, useMemo } from "react"; import { LotteryAPI } from "@/apis/lotteryAPI.ts"; import { RushAPI } from "@/apis/rushAPI.ts"; import useFetch from "@/hooks/useFetch.ts"; +import { GetLotteryResponse } from "@/types/lotteryApi.ts"; +import { GetTotalRushEventsResponse } from "@/types/rushApi.ts"; import { formatEventDate } from "@/utils/formatDate.ts"; interface EventDateDetails { @@ -10,10 +12,20 @@ interface EventDateDetails { activePeriod: number; } +export type EventType = "rush" | "lottery"; + export interface EventDateData { - [key: string]: EventDateDetails; + [key: EventType]: EventDateDetails; } +const mapToEventDateDetails = ( + data: GetLotteryResponse | GetTotalRushEventsResponse +): EventDateDetails => ({ + startDate: data.eventStartDate, + endDate: data.eventEndDate, + activePeriod: data.activePeriod, +}); + interface SectionProps { title: string; items: string[]; @@ -31,60 +43,47 @@ const Section: React.FC = ({ title, items, indentedIndices = [] })
); -// TODO: Promise.all 로 묶지 말고 따로 useFetch 써서 하기 -const getEventsDateDetails = async (): Promise<{ - rush: EventDateDetails; - lottery: EventDateDetails; -}> => { - const [rushData, lotteryData] = await Promise.all([RushAPI.getRush(), LotteryAPI.getLottery()]); - - const rushEventDetails: EventDateDetails = { - startDate: rushData.eventStartDate, - endDate: rushData.eventEndDate, - activePeriod: rushData.activePeriod, - }; - - const lotteryEventDetails: EventDateDetails = { - startDate: lotteryData.eventStartDate, - endDate: lotteryData.eventEndDate, - activePeriod: lotteryData.activePeriod, - }; - - return { - rush: rushEventDetails, - lottery: lotteryEventDetails, - }; -}; - function Notice() { const { - data: eventDateDetails, - isSuccess: isSuccessRushAndLottery, - fetchData: getRushAndLotteryEventData, - } = useFetch<{ - rush: EventDateDetails; - lottery: EventDateDetails; - }>(getEventsDateDetails); + data: rushEventDetails, + isSuccess: isSuccessRush, + fetchData: getRushEventData, + } = useFetch(() => RushAPI.getRush().then(mapToEventDateDetails)); + + const { + data: lotteryEventDetails, + isSuccess: isSuccessLottery, + fetchData: getLotteryEventData, + } = useFetch(() => LotteryAPI.getLottery().then(mapToEventDateDetails)); useEffect(() => { - getRushAndLotteryEventData(); + getRushEventData(); + getLotteryEventData(); }, []); + const eventDateData: EventDateData = useMemo(() => { + const eventData: EventDateData = {}; + + if (rushEventDetails) eventData.rush = rushEventDetails; + if (lotteryEventDetails) eventData.lottery = lotteryEventDetails; + + return eventData; + }, [rushEventDetails, lotteryEventDetails]); + + const isValidData = + isSuccessRush && isSuccessLottery && rushEventDetails && lotteryEventDetails; + return (

유의사항

- {isSuccessRushAndLottery && eventDateDetails && ( + {isValidData && ( <>
{ const event = eventDateDetails[eventKey]; From 6db3ea472e7969a3f8b1ae398b53401189aadadc Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Fri, 16 Aug 2024 17:02:17 +0900 Subject: [PATCH 109/111] =?UTF-8?q?fix:=20EventDateData=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Notice/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/Notice/index.tsx b/client/src/components/Notice/index.tsx index 57047504..b3f13e90 100644 --- a/client/src/components/Notice/index.tsx +++ b/client/src/components/Notice/index.tsx @@ -15,7 +15,8 @@ interface EventDateDetails { export type EventType = "rush" | "lottery"; export interface EventDateData { - [key: EventType]: EventDateDetails; + rush?: EventDateDetails; + lottery?: EventDateDetails; } const mapToEventDateDetails = ( From 508e696059b83493c31da3d471566925f5f04892 Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 18 Aug 2024 16:02:22 +0900 Subject: [PATCH 110/111] =?UTF-8?q?refactor:=20PR=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/rushAPI.ts | 4 +- client/src/constants/Rush/rushCard.ts | 24 ++++++--- client/src/contexts/rushGameContext.tsx | 34 ++++++------ client/src/features/Main/Headline.tsx | 29 ++++------- client/src/features/Main/Lottery.tsx | 17 ++---- client/src/features/Main/Rush.tsx | 34 ++++++------ .../RushGame/RushGameComponents/RushBar.tsx | 37 +++++++++++++ .../RushCardCurrentRatio.tsx | 48 ++++------------- .../RushGameComponents/RushCountdown.tsx | 3 +- .../RushCurrentOptionDisplay.tsx | 25 +++++++++ .../RushGameComponents/RushProgressBar.tsx | 52 +++++-------------- .../RushResultOptionDisplay.tsx | 27 ++++++++++ .../RushGame/RushGameSections/CardOptions.tsx | 2 +- .../RushGame/RushGameSections/Countdown.tsx | 3 +- .../RushGame/RushGameSections/FinalResult.tsx | 38 +++----------- .../RushGameSections/SelectedCard.tsx | 2 +- client/src/hooks/useAuth.ts | 4 +- client/src/hooks/useToggleContents.ts | 16 ++++-- client/src/types/rushGame.ts | 3 +- client/src/utils/formatTime.ts | 3 ++ 20 files changed, 211 insertions(+), 194 deletions(-) create mode 100644 client/src/features/RushGame/RushGameComponents/RushBar.tsx create mode 100644 client/src/features/RushGame/RushGameComponents/RushCurrentOptionDisplay.tsx create mode 100644 client/src/features/RushGame/RushGameComponents/RushResultOptionDisplay.tsx create mode 100644 client/src/utils/formatTime.ts diff --git a/client/src/apis/rushAPI.ts b/client/src/apis/rushAPI.ts index a2bf00d6..1989ddc7 100644 --- a/client/src/apis/rushAPI.ts +++ b/client/src/apis/rushAPI.ts @@ -112,11 +112,11 @@ export const RushAPI = { throw error; } }, - async getRushTodayEventTest(token: string): Promise { + async getRushTodayEventTest(): Promise { try { const response = await fetchWithTimeout(`${baseURL}/today/test`, { method: "GET", - headers: { ...headers, Authorization: `Bearer ${token}` }, + headers: headers, }); if (response.status === 204 || response.status === 404) { return response.status; diff --git a/client/src/constants/Rush/rushCard.ts b/client/src/constants/Rush/rushCard.ts index d28f0474..33b466bb 100644 --- a/client/src/constants/Rush/rushCard.ts +++ b/client/src/constants/Rush/rushCard.ts @@ -4,7 +4,7 @@ export const CARD_PHASE = { NOT_STARTED: "NOT_STARTED", IN_PROGRESS: "IN_PROGRESS", COMPLETED: "COMPLETED", -}; +} as const; export const CARD_COLOR = { BLUE: "blue", @@ -18,6 +18,12 @@ export const CARD_OPTION = { RIGHT_OPTIONS: 2, } as const; +export const WIN_STATUS = { + WIN: "Win", + LOSE: "Lose", + TIE: "Tie", +} as const; + // TODO: 카드 색상 랜덤 기능 구현 후 불필요한 상수 데이터 삭제 (CARD_DAYS, CARD_COLORS) export const CARD_DAYS = { DAY1: 1, @@ -28,12 +34,16 @@ export const CARD_DAYS = { DAY6: 6, } as const; -export const CARD_COLORS: { - [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: { - [CARD_OPTION.LEFT_OPTIONS]: CardColor; - [CARD_OPTION.RIGHT_OPTIONS]: CardColor; - }; -} = { +type CardColorOptions = { + [CARD_OPTION.LEFT_OPTIONS]: CardColor; + [CARD_OPTION.RIGHT_OPTIONS]: CardColor; +}; + +type CardColorType = { + [key in (typeof CARD_DAYS)[keyof typeof CARD_DAYS]]: CardColorOptions; +}; + +export const CARD_COLORS: CardColorType = { [CARD_DAYS.DAY1]: { [CARD_OPTION.LEFT_OPTIONS]: CARD_COLOR.GREEN, [CARD_OPTION.RIGHT_OPTIONS]: CARD_COLOR.BLUE, diff --git a/client/src/contexts/rushGameContext.tsx b/client/src/contexts/rushGameContext.tsx index 6a7cfe9f..fb11b9ae 100644 --- a/client/src/contexts/rushGameContext.tsx +++ b/client/src/contexts/rushGameContext.tsx @@ -153,22 +153,20 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { const startTime = getMsTime(currentEvent.startDateTime); const endTime = getMsTime(currentEvent.endDateTime); - switch (gameState.phase) { - case CARD_PHASE.NOT_STARTED: - if (rushData.serverTime && currentEvent?.startDateTime) { - const preCountdown = Math.max( - 0, - Math.floor((startTime - serverTime) / 1000) - ); - setInitialPreCountdown(preCountdown); - } - break; - case CARD_PHASE.IN_PROGRESS: - if (rushData.serverTime && currentEvent?.endDateTime) { - const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); - setInitialRunCountdown(runCountdown); - } - break; + if ( + gameState.phase === CARD_PHASE.NOT_STARTED && + rushData.serverTime && + currentEvent?.startDateTime + ) { + const preCountdown = Math.max(0, Math.floor((startTime - serverTime) / 1000)); + setInitialPreCountdown(preCountdown); + } else if ( + gameState.phase === CARD_PHASE.IN_PROGRESS && + rushData.serverTime && + currentEvent?.endDateTime + ) { + const runCountdown = Math.max(0, Math.floor((endTime - serverTime) / 1000)); + setInitialRunCountdown(runCountdown); } } }, [rushData, gameState.phase]); @@ -177,8 +175,8 @@ export const RushGameProvider = ({ children }: { children: ReactNode }) => { // const runCountdown = useCountdown(initialRunCountdown || 1); // TEST COUNTDOWN CODE - const preCountdown = useCountdown(3); - const runCountdown = useCountdown(10); + const preCountdown = useCountdown(5); + const runCountdown = useCountdown(20); useEffect(() => { if (preCountdown <= 0 && gameState.phase === CARD_PHASE.NOT_STARTED) { diff --git a/client/src/features/Main/Headline.tsx b/client/src/features/Main/Headline.tsx index d7c44a68..031b61fb 100644 --- a/client/src/features/Main/Headline.tsx +++ b/client/src/features/Main/Headline.tsx @@ -1,12 +1,10 @@ -import { memo, useEffect, useState } from "react"; +import { memo, useEffect } from "react"; import { motion } from "framer-motion"; -import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; import { TotalAPI } from "@/apis/totalAPI.ts"; import Keyword from "@/components/Keyword"; import Scroll from "@/components/Scroll"; import { ASCEND, ASCEND_DESCEND, SCROLL_MOTION } from "@/constants/animation.ts"; -import { COOKIE_KEY } from "@/constants/cookie.ts"; import useFetch from "@/hooks/useFetch.ts"; import { RushEventStatusCodeResponse } from "@/types/rushApi.ts"; import { SectionKeyProps } from "@/types/sections.ts"; @@ -14,13 +12,9 @@ import { GetTotalEventDateResponse } from "@/types/totalApi.ts"; import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; function Headline({ id }: SectionKeyProps) { - const [cookies] = useCookies([COOKIE_KEY.ACCESS_TOKEN]); - const [startDateTime, setStartDateTime] = useState(""); - const [endDateTime, setEndDateTime] = useState(""); - // DATA RESET TEST API - const { fetchData: getRushTodayEventTest } = useFetch( - (token) => RushAPI.getRushTodayEventTest(token) + const { fetchData: getRushTodayEventTest } = useFetch(() => + RushAPI.getRushTodayEventTest() ); const { @@ -30,16 +24,12 @@ function Headline({ id }: SectionKeyProps) { } = useFetch(() => TotalAPI.getTotal()); useEffect(() => { - getRushTodayEventTest(cookies[COOKIE_KEY.ACCESS_TOKEN]); + getRushTodayEventTest(); getTotal(); }, []); - useEffect(() => { - if (isSuccessTotalData && totalData) { - setStartDateTime(totalData.totalEventStartDate); - setEndDateTime(totalData.totalEventEndDate); - } - }, [isSuccessTotalData, totalData]); + const { totalEventStartDate, totalEventEndDate }: GetTotalEventDateResponse = + totalData || ({} as GetTotalEventDateResponse); return (

- {startDateTime && - endDateTime && - formatEventDateRangeWithDot(startDateTime, endDateTime)} + {isSuccessTotalData && + totalEventStartDate && + totalEventEndDate && + formatEventDateRangeWithDot(totalEventStartDate, totalEventEndDate)}

diff --git a/client/src/features/Main/Lottery.tsx b/client/src/features/Main/Lottery.tsx index 4bafdecc..34e5cd91 100644 --- a/client/src/features/Main/Lottery.tsx +++ b/client/src/features/Main/Lottery.tsx @@ -1,4 +1,4 @@ -import { memo, useEffect, useState } from "react"; +import { memo, useEffect } from "react"; import { Link } from "react-router-dom"; import { LotteryAPI } from "@/apis/lotteryAPI.ts"; import LotteryEvent from "@/components/LotteryEvent"; @@ -11,9 +11,6 @@ import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; import ArrowRightIcon from "/public/assets/icons/arrow-line-right.svg?react"; function Lottery({ id }: SectionKeyProps) { - const [startDateTime, setStartDateTime] = useState(""); - const [endDateTime, setEndDateTime] = useState(""); - const { data: lotteryData, isSuccess: isSuccessLottery, @@ -24,12 +21,8 @@ function Lottery({ id }: SectionKeyProps) { getLottery(); }, []); - useEffect(() => { - if (isSuccessLottery && lotteryData) { - setStartDateTime(lotteryData.eventStartDate); - setEndDateTime(lotteryData.eventEndDate); - } - }, [isSuccessLottery, lotteryData]); + const { eventStartDate, eventEndDate }: GetLotteryResponse = + lotteryData || ({} as GetLotteryResponse); return (

이벤트 기간

- {startDateTime && endDateTime - ? formatEventDateRangeWithDot(startDateTime, endDateTime) + {isSuccessLottery && eventStartDate && eventEndDate + ? formatEventDateRangeWithDot(eventStartDate, eventEndDate) : ""}

diff --git a/client/src/features/Main/Rush.tsx b/client/src/features/Main/Rush.tsx index 4ed49d19..fc61c6e0 100644 --- a/client/src/features/Main/Rush.tsx +++ b/client/src/features/Main/Rush.tsx @@ -1,4 +1,4 @@ -import { memo, useEffect, useState } from "react"; +import { memo, useEffect, useMemo } from "react"; import { RushAPI } from "@/apis/rushAPI.ts"; import RushEvent, { TotalRushEventsProps } from "@/components/RushEvent"; import { RUSH_EVENT_DATA } from "@/constants/Main/rushEventData.ts"; @@ -10,10 +10,6 @@ import { formatEventDateRangeWithDot } from "@/utils/formatDate.ts"; import { getMsTime } from "@/utils/getMsTime.ts"; function Rush({ id }: SectionKeyProps) { - const [rushEvents, setRushEvents] = useState([]); - const [startDateTime, setStartDateTime] = useState(""); - const [endDateTime, setEndDateTime] = useState(""); - const { data: rushData, isSuccess: isSuccessRush, @@ -24,14 +20,19 @@ function Rush({ id }: SectionKeyProps) { getRush(); }, []); - useEffect(() => { - if (isSuccessRush && rushData) { - const serverDateTime = getMsTime(rushData.serverTime); + const { + serverTime, + todayEventId, + eventStartDate, + eventEndDate, + events = [], + }: GetTotalRushEventsResponse = rushData || ({} as GetTotalRushEventsResponse); - setStartDateTime(rushData.eventStartDate); - setEndDateTime(rushData.eventEndDate); + const rushEvents: TotalRushEventsProps[] = useMemo(() => { + if (isSuccessRush && rushData) { + const serverDateTime = getMsTime(serverTime); - const events = rushData.events.map((event, idx) => { + return events.map((event, idx) => { const rushEvent = RUSH_EVENT_DATA[idx]; const eventEndTime = getMsTime(event.endDateTime); @@ -42,13 +43,12 @@ function Rush({ id }: SectionKeyProps) { prizeName: rushEvent?.prizeName || "", isPastEvent: serverDateTime > eventEndTime, isTodayEvent: - event.rushEventId === rushData.todayEventId && - serverDateTime <= eventEndTime, + event.rushEventId === todayEventId && serverDateTime <= eventEndTime, }; }); - setRushEvents(events); } - }, [isSuccessRush, rushData]); + return []; + }, [isSuccessRush, rushData, serverTime, todayEventId, events]); return (
이벤트 기간

- {startDateTime && endDateTime - ? formatEventDateRangeWithDot(startDateTime, endDateTime) + {isSuccessRush && eventStartDate && eventEndDate + ? formatEventDateRangeWithDot(eventStartDate, eventEndDate) : ""}

매일 오후 10시!

diff --git a/client/src/features/RushGame/RushGameComponents/RushBar.tsx b/client/src/features/RushGame/RushGameComponents/RushBar.tsx new file mode 100644 index 00000000..d2e10d0b --- /dev/null +++ b/client/src/features/RushGame/RushGameComponents/RushBar.tsx @@ -0,0 +1,37 @@ +import { VariantProps, cva } from "class-variance-authority"; + +const barVariants = cva(`flex items-center`, { + variants: { + color: { + green: "bg-gradient-green", + red: "bg-gradient-red", + blue: "bg-gradient-blue", + yellow: "bg-gradient-yellow", + }, + status: { + winning: "text-n-neutral-950", + losing: "text-n-neutral-500", + }, + textAlign: { + left: "justify-start", + right: "justify-end", + }, + }, + defaultVariants: { + status: "winning", + }, +}); + +type BarVariantsProps = VariantProps; + +interface BarProps extends BarVariantsProps { + ratio: number; +} + +export default function RushBar({ ratio, color, status, textAlign }: BarProps) { + return ( + +

{ratio}%

+
+ ); +} diff --git a/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx b/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx index 80b17a9b..832b5443 100644 --- a/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCardCurrentRatio.tsx @@ -1,19 +1,12 @@ -import Category from "@/components/Category"; import Tooltip from "@/components/Tooltip"; import { CARD_OPTION } from "@/constants/Rush/rushCard.ts"; +import RushCurrentOptionDisplay from "@/features/RushGame/RushGameComponents/RushCurrentOptionDisplay.tsx"; import RushProgressBar from "@/features/RushGame/RushGameComponents/RushProgressBar.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import useToggleContents from "@/hooks/useToggleContents.ts"; import { CardOption } from "@/types/rushGame.ts"; import Reload from "/public/assets/icons/reload.svg?react"; -interface OptionDisplayProps { - mainText: string; - userSelectedOptionRatio: number; - oppositeOptionRatio: number; - isUserSelected: boolean; -} - const TOOLTIP_CONTENT = () => ( <> 새로고침을 눌러 @@ -44,35 +37,10 @@ function getMessage(leftRatio: number, rightRatio: number, userSelectedOption: C } } -function ReloadButton({ onClick }: { onClick: () => void }) { - return ( - - ); -} - -function OptionDisplay({ - mainText, - userSelectedOptionRatio, - oppositeOptionRatio, - isUserSelected, -}: OptionDisplayProps) { - return ( -
-

{mainText}

- {userSelectedOptionRatio > oppositeOptionRatio && ( - 우세해요! - )} - {isUserSelected && 당신의 선택} -
- ); -} - export default function RushCardCurrentRatio() { const { gameState, getOptionRatio, fetchRushBalance, getSelectedCardInfo } = useRushGameContext(); - const { toggleContents } = useToggleContents(true, 5000); + const { toggleContents } = useToggleContents(); const leftOptionRatio = getOptionRatio(CARD_OPTION.LEFT_OPTIONS); const rightOptionRatio = getOptionRatio(CARD_OPTION.RIGHT_OPTIONS); @@ -90,13 +58,13 @@ export default function RushCardCurrentRatio() {
- - {toggleContents ? ( - + ) : ( - + )}
diff --git a/client/src/features/RushGame/RushGameComponents/RushCountdown.tsx b/client/src/features/RushGame/RushGameComponents/RushCountdown.tsx index ff062e1d..5fcb173b 100644 --- a/client/src/features/RushGame/RushGameComponents/RushCountdown.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushCountdown.tsx @@ -1,4 +1,5 @@ import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; +import { formatTime } from "@/utils/formatTime.ts"; function TimeDisplay({ label, value }: { label: string; value: string }) { return ( @@ -14,8 +15,6 @@ export default function RushCountdown() { const minutes = Math.floor((runCountdown % 3600) / 60); const seconds = runCountdown % 60; - const formatTime = (time: number) => time.toString().padStart(2, "0"); - return (

diff --git a/client/src/features/RushGame/RushGameComponents/RushCurrentOptionDisplay.tsx b/client/src/features/RushGame/RushGameComponents/RushCurrentOptionDisplay.tsx new file mode 100644 index 00000000..ff190da4 --- /dev/null +++ b/client/src/features/RushGame/RushGameComponents/RushCurrentOptionDisplay.tsx @@ -0,0 +1,25 @@ +import Category from "@/components/Category"; + +interface RushCurrentOptionDisplayProps { + mainText: string; + userSelectedOptionRatio: number; + oppositeOptionRatio: number; + isUserSelected: boolean; +} + +export default function RushCurrentOptionDisplay({ + mainText, + userSelectedOptionRatio, + oppositeOptionRatio, + isUserSelected, +}: RushCurrentOptionDisplayProps) { + return ( +

+

{mainText}

+ {userSelectedOptionRatio > oppositeOptionRatio && ( + 우세해요! + )} + {isUserSelected && 당신의 선택} +
+ ); +} diff --git a/client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx b/client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx index 33fce37d..0f7a35cb 100644 --- a/client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx +++ b/client/src/features/RushGame/RushGameComponents/RushProgressBar.tsx @@ -1,5 +1,5 @@ -import { VariantProps, cva } from "class-variance-authority"; -import { CARD_PHASE } from "@/constants/Rush/rushCard.ts"; +import { CARD_COLOR, CARD_PHASE } from "@/constants/Rush/rushCard.ts"; +import RushBar from "@/features/RushGame/RushGameComponents/RushBar.tsx"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; interface RushProgressBarProps { @@ -7,40 +7,6 @@ interface RushProgressBarProps { rightOptionRatio: number; } -const barVariants = cva(`flex items-center`, { - variants: { - color: { - green: "bg-gradient-green", - red: "bg-gradient-red", - }, - status: { - winning: "text-n-neutral-950", - losing: "text-n-neutral-500", - }, - textAlign: { - left: "justify-start", - right: "justify-end", - }, - }, - defaultVariants: { - status: "winning", - }, -}); - -type BarVariantsProps = VariantProps; - -interface BarProps extends BarVariantsProps { - ratio: number; -} - -function Bar({ ratio, color, status, textAlign }: BarProps) { - return ( - -

{ratio}%

-
- ); -} - export default function RushProgressBar({ leftOptionRatio, rightOptionRatio, @@ -52,8 +18,18 @@ export default function RushProgressBar({ return (
- - + +
); } diff --git a/client/src/features/RushGame/RushGameComponents/RushResultOptionDisplay.tsx b/client/src/features/RushGame/RushGameComponents/RushResultOptionDisplay.tsx new file mode 100644 index 00000000..b33c8aaf --- /dev/null +++ b/client/src/features/RushGame/RushGameComponents/RushResultOptionDisplay.tsx @@ -0,0 +1,27 @@ +import Category from "@/components/Category"; +import { WinStatus } from "@/types/rushGame.ts"; + +interface RushResultOptionDisplayProps { + mainText: string; + winStatus: WinStatus; + isUserSelected: boolean; +} + +export default function RushResultOptionDisplay({ + mainText, + winStatus, + isUserSelected, +}: RushResultOptionDisplayProps) { + const categoryType = winStatus === "Win" ? "limited" : "basic"; + return ( +
+

+ {mainText} +

+ {winStatus} + {isUserSelected && 당신의 선택} +
+ ); +} diff --git a/client/src/features/RushGame/RushGameSections/CardOptions.tsx b/client/src/features/RushGame/RushGameSections/CardOptions.tsx index 3e60479a..e6d573ae 100644 --- a/client/src/features/RushGame/RushGameSections/CardOptions.tsx +++ b/client/src/features/RushGame/RushGameSections/CardOptions.tsx @@ -5,7 +5,7 @@ import RushCountdown from "@/features/RushGame/RushGameComponents/RushCountdown. import useToggleContents from "@/hooks/useToggleContents.ts"; export default function CardOptions() { - const { toggleContents } = useToggleContents(true, 5000); + const { toggleContents } = useToggleContents(); return ( time.toString().padStart(2, "0"); - return (

diff --git a/client/src/features/RushGame/RushGameSections/FinalResult.tsx b/client/src/features/RushGame/RushGameSections/FinalResult.tsx index 7a187e67..8d196f37 100644 --- a/client/src/features/RushGame/RushGameSections/FinalResult.tsx +++ b/client/src/features/RushGame/RushGameSections/FinalResult.tsx @@ -2,48 +2,24 @@ import { useEffect } from "react"; import { motion } from "framer-motion"; import { useCookies } from "react-cookie"; import { RushAPI } from "@/apis/rushAPI.ts"; -import Category from "@/components/Category"; -import { CARD_OPTION } from "@/constants/Rush/rushCard.ts"; +import { CARD_OPTION, WIN_STATUS } from "@/constants/Rush/rushCard.ts"; import { ASCEND, SCROLL_MOTION } from "@/constants/animation.ts"; import { COOKIE_KEY } from "@/constants/cookie.ts"; import RushProgressBar from "@/features/RushGame/RushGameComponents/RushProgressBar.tsx"; +import RushResultOptionDisplay from "@/features/RushGame/RushGameComponents/RushResultOptionDisplay.tsx"; import useFetch from "@/hooks/useFetch.ts"; import { useRushGameContext } from "@/hooks/useRushGameContext.ts"; import { GetRushResultResponse } from "@/types/rushApi.ts"; +import { WinStatus } from "@/types/rushGame.ts"; const MESSAGES = { WINNING: "축하해요! 선착순 경품 당첨이에요.", LOSING: "아쉽네요, 다음 기회를 다시 노려봐요.", }; -type WinStatus = "Win" | "Lose" | "Tie"; - function getWinStatus(ratio: number, oppositeRatio: number): WinStatus { - if (ratio === oppositeRatio) return "Tie"; - return ratio > oppositeRatio ? "Win" : "Lose"; -} - -function OptionDisplay({ - mainText, - winStatus, - isUserSelected, -}: { - mainText: string; - winStatus: WinStatus; - isUserSelected: boolean; -}) { - const categoryType = winStatus === "Win" ? "limited" : "basic"; - return ( -

-

- {mainText} -

- {winStatus} - {isUserSelected && 당신의 선택} -
- ); + if (ratio === oppositeRatio) return WIN_STATUS.TIE; + return ratio > oppositeRatio ? WIN_STATUS.WIN : WIN_STATUS.LOSE; } export default function FinalResult() { @@ -114,14 +90,14 @@ export default function FinalResult() {

최종 밸런스 게임 결과

- - { diff --git a/client/src/hooks/useAuth.ts b/client/src/hooks/useAuth.ts index 2a7b274d..d9ada041 100644 --- a/client/src/hooks/useAuth.ts +++ b/client/src/hooks/useAuth.ts @@ -32,13 +32,13 @@ export function useAuth(redirectUrl: string) { useEffect(() => { if (inviteUser) { - setCookie(COOKIE_KEY.INVITE_USER, inviteUser); + setCookie(COOKIE_KEY.INVITE_USER, inviteUser, { path: "/" }); } }, [inviteUser]); useEffect(() => { if (authToken && isSuccessGetAuthToken) { - setCookie(COOKIE_KEY.ACCESS_TOKEN, authToken.accessToken); + setCookie(COOKIE_KEY.ACCESS_TOKEN, authToken.accessToken, { path: "/" }); dispatch({ type: PHONE_NUMBER_ACTION.SET_PHONE_NUMBER, payload: phoneNumberState }); navigate(redirectUrl); } diff --git a/client/src/hooks/useToggleContents.ts b/client/src/hooks/useToggleContents.ts index 12050af7..583910f8 100644 --- a/client/src/hooks/useToggleContents.ts +++ b/client/src/hooks/useToggleContents.ts @@ -1,6 +1,16 @@ import { useCallback, useEffect, useState } from "react"; -export default function useToggleContents(initialStatus: boolean = true, duration?: number) { +interface UseToggleContentsProps { + initialStatus?: boolean; + duration?: number; + useDuration?: boolean; +} + +export default function useToggleContents({ + initialStatus = true, + duration = 5000, + useDuration = true, +}: UseToggleContentsProps = {}) { const [toggleContents, setToggleContents] = useState(initialStatus); const toggle = useCallback(() => { @@ -8,14 +18,14 @@ export default function useToggleContents(initialStatus: boolean = true, duratio }, []); useEffect(() => { - if (duration !== undefined && duration > 0) { + if (useDuration && duration && duration > 0) { const timer = setTimeout(() => { toggle(); }, duration); return () => clearTimeout(timer); } - }, [duration, toggle]); + }, [useDuration, duration, toggle]); return { toggleContents, toggle }; } diff --git a/client/src/types/rushGame.ts b/client/src/types/rushGame.ts index 18cc990e..b8d0b06f 100644 --- a/client/src/types/rushGame.ts +++ b/client/src/types/rushGame.ts @@ -1,8 +1,9 @@ -import { CARD_COLOR, CARD_OPTION, CARD_PHASE } from "@/constants/Rush/rushCard.ts"; +import { CARD_COLOR, CARD_OPTION, CARD_PHASE, WIN_STATUS } from "@/constants/Rush/rushCard.ts"; export type GamePhase = (typeof CARD_PHASE)[keyof typeof CARD_PHASE]; export type CardColor = (typeof CARD_COLOR)[keyof typeof CARD_COLOR]; export type CardOption = (typeof CARD_OPTION)[keyof typeof CARD_OPTION]; +export type WinStatus = (typeof WIN_STATUS)[keyof typeof WIN_STATUS]; export interface CardOptionState { mainText: string; diff --git a/client/src/utils/formatTime.ts b/client/src/utils/formatTime.ts new file mode 100644 index 00000000..b3775d28 --- /dev/null +++ b/client/src/utils/formatTime.ts @@ -0,0 +1,3 @@ +export function formatTime(time: number, length: number = 2, padChar: string = "0") { + return time.toString().padStart(length, padChar); +} From fdad43658aa863e5520152dd01f5db294e94362e Mon Sep 17 00:00:00 2001 From: sooyeoniya Date: Sun, 18 Aug 2024 16:58:12 +0900 Subject: [PATCH 111/111] =?UTF-8?q?refactor:=20useToggleContents=20?= =?UTF-8?q?=ED=9B=85=20=EA=B4=80=EB=A0=A8=20PR=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useToggleContents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/hooks/useToggleContents.ts b/client/src/hooks/useToggleContents.ts index 583910f8..23f02802 100644 --- a/client/src/hooks/useToggleContents.ts +++ b/client/src/hooks/useToggleContents.ts @@ -18,7 +18,7 @@ export default function useToggleContents({ }, []); useEffect(() => { - if (useDuration && duration && duration > 0) { + if (useDuration) { const timer = setTimeout(() => { toggle(); }, duration);