From 72e24202146ab0696b987850e7465065207dc761 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 13:20:18 +0900
Subject: [PATCH 01/19] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?=
=?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=A1=B0=ED=9A=8C=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
---
admin/src/apis/rushAPI.ts | 47 +++++++++++++++++++++++++++
admin/src/features/Rush/EventList.tsx | 43 ++----------------------
admin/src/pages/Rush/index.tsx | 35 +++-----------------
admin/src/router.tsx | 2 ++
admin/src/types/rush.ts | 1 +
admin/src/types/rushApi.ts | 4 ++-
6 files changed, 60 insertions(+), 72 deletions(-)
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index 34466536..34a5ebc4 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -1,4 +1,5 @@
import {
+ GetRushEventResponse,
GetRushOptionsParams,
GetRushOptionsResponse,
GetRushParticipantListParams,
@@ -13,6 +14,52 @@ const headers = {
};
export const RushAPI = {
+ async getRush(): Promise {
+ try {
+ return new Promise((resolve) =>
+ resolve([
+ {
+ rushEventId: 1,
+ eventDate: "2024-07-25",
+ openTime: "20:00:00",
+ closeTime: "20:10:00",
+ winnerCount: 315,
+ prizeImageUrl: "prize1.png",
+ prizeDescription: "스타벅스 1만원 기프트카드",
+ isActivated: true,
+ },
+ {
+ rushEventId: 2,
+ eventDate: "2024-07-26",
+ openTime: "20:00:00",
+ closeTime: "20:10:00",
+ winnerCount: 315,
+ prizeImageUrl: "prize2.png",
+ prizeDescription: "올리브영 1만원 기프트카드",
+ isActivated: true,
+ },
+ {
+ rushEventId: 3,
+ eventDate: "2024-07-27",
+ openTime: "20:00:00",
+ closeTime: "20:10:00",
+ winnerCount: 315,
+ prizeImageUrl: "prize3.png",
+ prizeDescription: "배달의 민족 1만원 기프트카드",
+ isActivated: true,
+ },
+ ])
+ );
+ const response = await fetchWithTimeout(`${baseURL}`, {
+ method: "GET",
+ headers: headers,
+ });
+ return response.json();
+ } catch (error) {
+ console.error("Error:", error);
+ throw error;
+ }
+ },
async getRushParticipantList({
id,
phoneNumber,
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index c1baf367..a85697af 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -1,4 +1,3 @@
-import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import Button from "@/components/Button";
import DatePicker from "@/components/DatePicker";
@@ -16,42 +15,6 @@ export default function EventList() {
const { rushList } = useRushEventStateContext();
const dispatch = useRushEventDispatchContext();
- useEffect(() => {
- // TODO: 데이터 패칭 로직 구현
- dispatch({
- type: RUSH_ACTION.SET_EVENT_LIST,
- payload: [
- {
- rushEventId: 1,
- eventDate: "2024-07-25",
- openTime: "20:00:00",
- closeTime: "20:10:00",
- winnerCount: 315,
- prizeImageUrl: "prize1.png",
- prizeDescription: "스타벅스 1만원 기프트카드",
- },
- {
- rushEventId: 2,
- eventDate: "2024-07-26",
- openTime: "20:00:00",
- closeTime: "20:10:00",
- winnerCount: 315,
- prizeImageUrl: "prize2.png",
- prizeDescription: "올리브영 1만원 기프트카드",
- },
- {
- rushEventId: 2,
- eventDate: "2024-07-27",
- openTime: "20:00:00",
- closeTime: "20:10:00",
- winnerCount: 315,
- prizeImageUrl: "prize3.png",
- prizeDescription: "배달의 민족 1만원 기프트카드",
- },
- ],
- });
- }, []);
-
const handleChangeItem = (key: string, changeIdx: number, text: string | number) => {
const updatedTableItemList = rushList.map((item, idx) => {
if (idx === changeIdx) {
@@ -120,12 +83,10 @@ export default function EventList() {
return (
-
-
+
-
-
);
diff --git a/admin/src/pages/Rush/index.tsx b/admin/src/pages/Rush/index.tsx
index 5f200e1d..79c8effb 100644
--- a/admin/src/pages/Rush/index.tsx
+++ b/admin/src/pages/Rush/index.tsx
@@ -1,45 +1,20 @@
import { useEffect } from "react";
+import { useLoaderData } from "react-router-dom";
import TabHeader from "@/components/TabHeader";
import EventList from "@/features/Rush/EventList";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import { RUSH_ACTION } from "@/types/rush";
+import { GetRushEventResponse } from "@/types/rushApi";
export default function Rush() {
const dispatch = useRushEventDispatchContext();
+ const rushEvent = useLoaderData() as GetRushEventResponse;
+
useEffect(() => {
- // TODO: 데이터 패칭 로직 구현
dispatch({
type: RUSH_ACTION.SET_EVENT_LIST,
- payload: [
- {
- rushEventId: 1,
- eventDate: "2024-07-25",
- openTime: "20:00:00",
- closeTime: "20:10:00",
- winnerCount: 315,
- prizeImageUrl: "prize1.png",
- prizeDescription: "스타벅스 1만원 기프트카드",
- },
- {
- rushEventId: 2,
- eventDate: "2024-07-26",
- openTime: "20:00:00",
- closeTime: "20:10:00",
- winnerCount: 315,
- prizeImageUrl: "prize2.png",
- prizeDescription: "올리브영 1만원 기프트카드",
- },
- {
- rushEventId: 2,
- eventDate: "2024-07-27",
- openTime: "20:00:00",
- closeTime: "20:10:00",
- winnerCount: 315,
- prizeImageUrl: "prize3.png",
- prizeDescription: "배달의 민족 1만원 기프트카드",
- },
- ],
+ payload: rushEvent,
});
}, []);
diff --git a/admin/src/router.tsx b/admin/src/router.tsx
index 1c9291dc..0464a577 100644
--- a/admin/src/router.tsx
+++ b/admin/src/router.tsx
@@ -1,5 +1,6 @@
import { createBrowserRouter } from "react-router-dom";
import { LotteryAPI } from "./apis/lotteryAPI";
+import { RushAPI } from "./apis/rushAPI";
import Layout from "./components/Layout";
import { ProtectedRoute, UnProtectedRoute } from "./components/Route";
import RushLayout from "./features/Rush/Layout";
@@ -36,6 +37,7 @@ export const router = createBrowserRouter([
{
index: true,
element:
,
+ loader: RushAPI.getRush,
},
{
path: "select-form",
diff --git a/admin/src/types/rush.ts b/admin/src/types/rush.ts
index f8eaeb53..76add925 100644
--- a/admin/src/types/rush.ts
+++ b/admin/src/types/rush.ts
@@ -8,6 +8,7 @@ export interface RushEventType {
winnerCount: number;
prizeImageUrl: string;
prizeDescription: string;
+ isActivated: boolean;
}
export interface RushOptionType {
diff --git a/admin/src/types/rushApi.ts b/admin/src/types/rushApi.ts
index a9a32e25..4987a01a 100644
--- a/admin/src/types/rushApi.ts
+++ b/admin/src/types/rushApi.ts
@@ -1,5 +1,5 @@
import { InfiniteListData } from "./common";
-import { RushOptionType, RushParticipantType } from "./rush";
+import { RushEventType, RushOptionType, RushParticipantType } from "./rush";
export interface GetRushParticipantListParams {
id: number;
@@ -9,6 +9,8 @@ export interface GetRushParticipantListParams {
phoneNumber?: string;
}
+export type GetRushEventResponse = RushEventType[];
+
export type GetRushOptionsResponse = RushOptionType[];
export type GetRushParticipantListResponse = InfiniteListData
;
From 3ef8b0e35eec6ede3cbcb6471aedc343f994528c Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 14:30:28 +0900
Subject: [PATCH 02/19] =?UTF-8?q?refactor:=20infinite=20data=20=ED=8B=80?=
=?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
---
admin/src/apis/lotteryAPI.ts | 2 +-
admin/src/apis/rushAPI.ts | 10 +++++-----
admin/src/hooks/useInfiniteFetch.ts | 6 +++---
admin/src/pages/LotteryWinner/index.tsx | 25 ++++++++++---------------
admin/src/types/common.ts | 4 ++--
admin/src/types/lotteryApi.ts | 4 ++--
admin/src/types/rush.ts | 2 +-
admin/src/types/rushApi.ts | 6 +++---
8 files changed, 27 insertions(+), 32 deletions(-)
diff --git a/admin/src/apis/lotteryAPI.ts b/admin/src/apis/lotteryAPI.ts
index c716da82..2cb5e7e0 100644
--- a/admin/src/apis/lotteryAPI.ts
+++ b/admin/src/apis/lotteryAPI.ts
@@ -61,7 +61,7 @@ export const LotteryAPI = {
try {
return new Promise((resolve) =>
resolve({
- data: [
+ participants: [
{
id: 1,
phoneNumber: "010-1111-2222",
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index 34a5ebc4..e2df5e5f 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -26,7 +26,7 @@ export const RushAPI = {
winnerCount: 315,
prizeImageUrl: "prize1.png",
prizeDescription: "스타벅스 1만원 기프트카드",
- isActivated: true,
+ status: true,
},
{
rushEventId: 2,
@@ -36,7 +36,7 @@ export const RushAPI = {
winnerCount: 315,
prizeImageUrl: "prize2.png",
prizeDescription: "올리브영 1만원 기프트카드",
- isActivated: true,
+ status: true,
},
{
rushEventId: 3,
@@ -46,7 +46,7 @@ export const RushAPI = {
winnerCount: 315,
prizeImageUrl: "prize3.png",
prizeDescription: "배달의 민족 1만원 기프트카드",
- isActivated: true,
+ status: true,
},
])
);
@@ -70,7 +70,7 @@ export const RushAPI = {
try {
return new Promise((resolve) =>
resolve({
- data: [
+ participants: [
{
id: 1,
phoneNumber: "010-1111-2222",
@@ -119,7 +119,7 @@ export const RushAPI = {
try {
return new Promise((resolve) =>
resolve({
- data: [
+ participants: [
{
id: 1,
phoneNumber: "010-3843-6999",
diff --git a/admin/src/hooks/useInfiniteFetch.ts b/admin/src/hooks/useInfiniteFetch.ts
index 57b86809..d9d57c5c 100644
--- a/admin/src/hooks/useInfiniteFetch.ts
+++ b/admin/src/hooks/useInfiniteFetch.ts
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useState } from "react";
-import { InfiniteListData } from "@/types/common";
+import { InfiniteParticipantListData } from "@/types/common";
interface UseInfiniteFetchProps {
fetch: (pageParam: number) => Promise;
@@ -23,7 +23,7 @@ export default function useInfiniteFetch({
initialPageParam,
getNextPageParam,
startFetching = true,
-}: UseInfiniteFetchProps>): InfiniteScrollData {
+}: UseInfiniteFetchProps>): InfiniteScrollData {
const [data, setData] = useState([]);
const [currentPageParam, setCurrentPageParam] = useState(initialPageParam);
const [isLoading, setIsLoading] = useState(false);
@@ -40,7 +40,7 @@ export default function useInfiniteFetch({
const lastPage = await fetch(currentPageParam);
const nextPageParam = getNextPageParam(currentPageParam, lastPage);
- setData([...data, ...lastPage.data]);
+ setData([...data, ...lastPage.participants]);
setCurrentPageParam(nextPageParam);
setHasNextPage(nextPageParam !== undefined);
setTotalLength(lastPage.totalParticipants);
diff --git a/admin/src/pages/LotteryWinner/index.tsx b/admin/src/pages/LotteryWinner/index.tsx
index 82b9d972..cbc1b246 100644
--- a/admin/src/pages/LotteryWinner/index.tsx
+++ b/admin/src/pages/LotteryWinner/index.tsx
@@ -1,9 +1,10 @@
-import { ChangeEvent, useEffect, useState } from "react";
+import { useEffect, useState } from "react";
import { useLoaderData, useNavigate } from "react-router-dom";
import { LotteryAPI } from "@/apis/lotteryAPI";
import Button from "@/components/Button";
import TabHeader from "@/components/TabHeader";
import useFetch from "@/hooks/useFetch";
+import { LotteryEventType } from "@/types/lottery";
import { GetLotteryResponse, PostLotteryWinnerResponse } from "@/types/lotteryApi";
export default function LotteryWinner() {
@@ -12,17 +13,14 @@ export default function LotteryWinner() {
const navigate = useNavigate();
- const [totalCount, setTotalCount] = useState(0);
- const [giftCount, setGiftCount] = useState(0);
+ const [currentLottery, setCurrentLottery] = useState({} as LotteryEventType);
const { isSuccess: isSuccessPostLottery, fetchData: postLottery } =
useFetch(() => LotteryAPI.postLotteryWinner());
useEffect(() => {
if (lottery.length !== 0) {
- const currentLotttery = lottery[0];
- setGiftCount(currentLotttery.winnerCount);
- setTotalCount(currentLotttery.appliedCount);
+ setCurrentLottery(lottery[0]);
}
}, [lottery]);
useEffect(() => {
@@ -31,11 +29,6 @@ export default function LotteryWinner() {
}
}, [isSuccessPostLottery]);
- const handleChangeInput = (e: ChangeEvent) => {
- const count = parseInt(e.target.value);
- setGiftCount(count || 0);
- };
-
const handleLottery = () => {
postLottery();
};
@@ -47,11 +40,13 @@ export default function LotteryWinner() {
전체 참여자 수
-
{totalCount}
+
+ {currentLottery.appliedCount}
+
당첨자 수
-
-
-
+
+ {currentLottery.winnerCount}
+
,
- "오픈 전",
+ RUSH_STATUS_MAP[item.status],
,
- ,
];
});
};
diff --git a/admin/src/types/rush.ts b/admin/src/types/rush.ts
index d27f4c9d..20d356eb 100644
--- a/admin/src/types/rush.ts
+++ b/admin/src/types/rush.ts
@@ -1,5 +1,7 @@
import { Dispatch } from "react";
+import { RUSH_STATUS } from "@/constants/rush";
+export type RushEventStatusType = (typeof RUSH_STATUS)[keyof typeof RUSH_STATUS];
export interface RushEventType {
rushEventId: number;
eventDate: string;
@@ -8,7 +10,7 @@ export interface RushEventType {
winnerCount: number;
prizeImageUrl: string;
prizeDescription: string;
- status: boolean;
+ status: RushEventStatusType;
}
export interface RushOptionType {
From cd2715b49ab6d3f083888a9a3525e271d8479886 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 15:01:30 +0900
Subject: [PATCH 04/19] =?UTF-8?q?feat:=20=ED=99=9C=EC=84=B1=ED=99=94=20?=
=?UTF-8?q?=EC=83=81=ED=83=9C=20=EB=B0=8F=20=EA=B8=B0=EA=B0=84=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
---
admin/src/apis/lotteryAPI.ts | 8 ++----
admin/src/constants/common.ts | 11 +++++++
admin/src/constants/rush.ts | 12 --------
admin/src/features/Rush/EventList.tsx | 5 ++--
admin/src/pages/Lottery/index.tsx | 32 +++++++--------------
admin/src/pages/LotteryWinner/index.tsx | 3 +-
admin/src/pages/LotteryWinnerList/index.tsx | 9 ++----
admin/src/router.tsx | 1 +
admin/src/types/lottery.ts | 5 +++-
admin/src/types/lotteryApi.ts | 2 --
admin/src/types/rush.ts | 4 +--
admin/src/utils/getDateDifference.ts | 15 ++++++++++
12 files changed, 52 insertions(+), 55 deletions(-)
create mode 100644 admin/src/constants/common.ts
create mode 100644 admin/src/utils/getDateDifference.ts
diff --git a/admin/src/apis/lotteryAPI.ts b/admin/src/apis/lotteryAPI.ts
index 2cb5e7e0..e6fcec53 100644
--- a/admin/src/apis/lotteryAPI.ts
+++ b/admin/src/apis/lotteryAPI.ts
@@ -19,13 +19,13 @@ export const LotteryAPI = {
return new Promise((resolve) =>
resolve([
{
- lotteryEventId: 1,
startDate: "2024-07-26",
startTime: "00:00",
endDate: "2024-08-25",
endTime: "23:59",
appliedCount: 1000000,
winnerCount: 363,
+ status: "BEFORE",
},
])
);
@@ -53,7 +53,6 @@ export const LotteryAPI = {
}
},
async getLotteryWinner({
- id,
size,
page,
phoneNumber,
@@ -89,7 +88,7 @@ export const LotteryAPI = {
})
);
const response = await fetchWithTimeout(
- `${baseURL}/${id}/winner?size=${size}&page=${page}&number=${phoneNumber}`,
+ `${baseURL}/winner?size=${size}&page=${page}&number=${phoneNumber}`,
{
method: "GET",
headers: headers,
@@ -102,7 +101,6 @@ export const LotteryAPI = {
}
},
async getLotteryExpectations({
- lotteryId,
participantId,
}: GetLotteryExpectationsParams): Promise {
try {
@@ -123,7 +121,7 @@ export const LotteryAPI = {
])
);
const response = await fetchWithTimeout(
- `${baseURL}/${lotteryId}/participants/${participantId}/expectations`,
+ `${baseURL}/participants/${participantId}/expectations`,
{
method: "GET",
headers: headers,
diff --git a/admin/src/constants/common.ts b/admin/src/constants/common.ts
new file mode 100644
index 00000000..72066f83
--- /dev/null
+++ b/admin/src/constants/common.ts
@@ -0,0 +1,11 @@
+export const EVENT_STATUS = {
+ BEFORE: "BEFORE",
+ DURING: "DURING",
+ AFTER: "AFTER",
+} as const;
+
+export const STATUS_MAP = {
+ [EVENT_STATUS.BEFORE]: "오픈 전",
+ [EVENT_STATUS.DURING]: "활성화",
+ [EVENT_STATUS.AFTER]: "종료",
+};
diff --git a/admin/src/constants/rush.ts b/admin/src/constants/rush.ts
index a5ccda94..5876eb88 100644
--- a/admin/src/constants/rush.ts
+++ b/admin/src/constants/rush.ts
@@ -10,15 +10,3 @@ export const EVENT_LIST_HEADER = [
"진행 상태",
"참여자 리스트 보기",
];
-
-export const RUSH_STATUS = {
- BEFORE: "BEFORE",
- DURING: "DURING",
- AFTER: "AFTER",
-} as const;
-
-export const RUSH_STATUS_MAP = {
- [RUSH_STATUS.BEFORE]: "오픈 전",
- [RUSH_STATUS.DURING]: "활성화",
- [RUSH_STATUS.AFTER]: "종료",
-};
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index 5f769406..e3c4bd48 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -3,7 +3,8 @@ import Button from "@/components/Button";
import DatePicker from "@/components/DatePicker";
import Table from "@/components/Table";
import TimePicker from "@/components/TimePicker";
-import { EVENT_LIST_HEADER, RUSH_STATUS_MAP } from "@/constants/rush";
+import { STATUS_MAP } from "@/constants/common";
+import { EVENT_LIST_HEADER } from "@/constants/rush";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import useRushEventStateContext from "@/hooks/useRushEventStateContext";
import { RUSH_ACTION } from "@/types/rush";
@@ -67,7 +68,7 @@ export default function EventList() {
}
/>
,
- RUSH_STATUS_MAP[item.status],
+ STATUS_MAP[item.status],
당첨자 수
-
+
{currentLottery.winnerCount}
From 240ec0a5e2262dc113bebf5d47344b202f80a5d6 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 16:22:38 +0900
Subject: [PATCH 07/19] =?UTF-8?q?refactor:=20Rush=20=EC=9D=B4=EB=B2=A4?=
=?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/apis/rushAPI.ts | 48 +++++++
admin/src/constants/rush.ts | 5 +
admin/src/contexts/rushEventContext.tsx | 7 -
admin/src/features/Rush/EventList.tsx | 10 +-
admin/src/features/Rush/RushPrizeForm.tsx | 75 +++++++++++
admin/src/features/Rush/RushSelectForm.tsx | 128 ++++++++++++++++++
admin/src/pages/Rush/index.tsx | 22 +++-
admin/src/pages/RushPrizeForm/index.tsx | 73 -----------
admin/src/pages/RushSelectForm/index.tsx | 143 ---------------------
admin/src/router.tsx | 10 --
admin/src/types/rush.ts | 23 +---
11 files changed, 284 insertions(+), 260 deletions(-)
create mode 100644 admin/src/features/Rush/RushPrizeForm.tsx
create mode 100644 admin/src/features/Rush/RushSelectForm.tsx
delete mode 100644 admin/src/pages/RushPrizeForm/index.tsx
delete mode 100644 admin/src/pages/RushSelectForm/index.tsx
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index afbd4e6b..bd614967 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -27,6 +27,22 @@ export const RushAPI = {
prizeImageUrl: "prize1.png",
prizeDescription: "스타벅스 1만원 기프트카드",
status: "BEFORE",
+ leftOption: {
+ rushOptionId: 1,
+ mainText: "첫 차로 저렴한 차 사기",
+ subText: "첫 차는 가성비가 짱이지!",
+ resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
+ resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
+ imageUrl: "left_image.png",
+ },
+ rightOption: {
+ rushOptionId: 2,
+ mainText: "첫 차로 성능 좋은 차 사기",
+ subText: "차는 당연히 성능이지!",
+ resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
+ resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
+ imageUrl: "left_image.png",
+ },
},
{
rushEventId: 2,
@@ -37,6 +53,22 @@ export const RushAPI = {
prizeImageUrl: "prize2.png",
prizeDescription: "올리브영 1만원 기프트카드",
status: "DURING",
+ leftOption: {
+ rushOptionId: 1,
+ mainText: "첫 차로 저렴한 차 사기",
+ subText: "첫 차는 가성비가 짱이지!",
+ resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
+ resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
+ imageUrl: "left_image.png",
+ },
+ rightOption: {
+ rushOptionId: 2,
+ mainText: "첫 차로 성능 좋은 차 사기",
+ subText: "차는 당연히 성능이지!",
+ resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
+ resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
+ imageUrl: "left_image.png",
+ },
},
{
rushEventId: 3,
@@ -47,6 +79,22 @@ export const RushAPI = {
prizeImageUrl: "prize3.png",
prizeDescription: "배달의 민족 1만원 기프트카드",
status: "AFTER",
+ leftOption: {
+ rushOptionId: 1,
+ mainText: "첫 차로 저렴한 차 사기",
+ subText: "첫 차는 가성비가 짱이지!",
+ resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
+ resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
+ imageUrl: "left_image.png",
+ },
+ rightOption: {
+ rushOptionId: 2,
+ mainText: "첫 차로 성능 좋은 차 사기",
+ subText: "차는 당연히 성능이지!",
+ resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
+ resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
+ imageUrl: "left_image.png",
+ },
},
])
);
diff --git a/admin/src/constants/rush.ts b/admin/src/constants/rush.ts
index 5876eb88..ef34c41e 100644
--- a/admin/src/constants/rush.ts
+++ b/admin/src/constants/rush.ts
@@ -10,3 +10,8 @@ export const EVENT_LIST_HEADER = [
"진행 상태",
"참여자 리스트 보기",
];
+
+export const QUERY_OPTION = {
+ OPTION: "option",
+ PRIZE: "prize",
+} as const;
diff --git a/admin/src/contexts/rushEventContext.tsx b/admin/src/contexts/rushEventContext.tsx
index b223d474..22ca288a 100644
--- a/admin/src/contexts/rushEventContext.tsx
+++ b/admin/src/contexts/rushEventContext.tsx
@@ -4,7 +4,6 @@ import {
RushEventAction,
RushEventDispatchType,
RushEventStateType,
- RushPrizeType,
} from "@/types/rush";
export const RushEventStateContext = createContext(null);
@@ -12,8 +11,6 @@ export const RushEventDispatchContext = createContext
- navigate("/rush/select-form", { state: { id: item.rushEventId } })
- }
+ onClick={() => navigate(`/rush?q=${QUERY_OPTION.OPTION}`, { state: { idx } })}
>
선택지 관리
,
- navigate("/rush/prize-form", { state: { id: item.rushEventId } })
- }
+ onClick={() => navigate(`/rush?q=${QUERY_OPTION.PRIZE}`, { state: { idx } })}
>
경품 관리
,
diff --git a/admin/src/features/Rush/RushPrizeForm.tsx b/admin/src/features/Rush/RushPrizeForm.tsx
new file mode 100644
index 00000000..f749a57a
--- /dev/null
+++ b/admin/src/features/Rush/RushPrizeForm.tsx
@@ -0,0 +1,75 @@
+import { useEffect, useState } from "react";
+import { useLocation, useNavigate } from "react-router-dom";
+import Button from "@/components/Button";
+import SelectForm from "@/components/SelectForm";
+import TabHeader from "@/components/TabHeader";
+import TextField from "@/components/TextField";
+import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
+import useRushEventStateContext from "@/hooks/useRushEventStateContext";
+import { RUSH_ACTION, RushPrizeType } from "@/types/rush";
+
+export default function RushPrizeForm() {
+ const location = useLocation();
+ const navigate = useNavigate();
+
+ const rushIdx = location.state.idx;
+
+ const { rushList } = useRushEventStateContext();
+ const dispatch = useRushEventDispatchContext();
+
+ const [prizeState, setPrizeState] = useState({} as RushPrizeType);
+
+ useEffect(() => {
+ if (rushIdx !== undefined) {
+ setPrizeState({
+ prizeImageUrl: rushList[rushIdx].prizeImageUrl,
+ prizeDescription: rushList[rushIdx].prizeDescription,
+ });
+ }
+ }, [rushList]);
+
+ const handleUpdate = () => {
+ const updatedTableItemList = rushList.map((item, idx) => {
+ if (idx === rushIdx) {
+ return { ...item, ...prizeState };
+ }
+ return { ...item };
+ });
+
+ dispatch({
+ type: RUSH_ACTION.SET_EVENT_LIST,
+ payload: updatedTableItemList,
+ });
+ };
+
+ const option = [
+ ["이미지", ],
+ [
+ "경품 이름 (20자 이내)",
+ setPrizeState({ ...prizeState, prizeDescription: e.target.value })}
+ />,
+ ],
+ ];
+
+ return (
+
+
+
navigate(-1)}
+ />
+
밸런스 게임 경품 관리
+
+
+
+
+
+ 임시 저장
+
+
+ );
+}
diff --git a/admin/src/features/Rush/RushSelectForm.tsx b/admin/src/features/Rush/RushSelectForm.tsx
new file mode 100644
index 00000000..cb8ca0ad
--- /dev/null
+++ b/admin/src/features/Rush/RushSelectForm.tsx
@@ -0,0 +1,128 @@
+import { useEffect, useState } from "react";
+import { useLocation, useNavigate } from "react-router-dom";
+import Button from "@/components/Button";
+import SelectForm from "@/components/SelectForm";
+import TextField from "@/components/TextField";
+import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
+import useRushEventStateContext from "@/hooks/useRushEventStateContext";
+import { RUSH_ACTION, RushOptionType } from "@/types/rush";
+
+export default function RushSelectForm() {
+ const location = useLocation();
+ const navigate = useNavigate();
+
+ const rushIdx = location.state.idx;
+
+ const { rushList } = useRushEventStateContext();
+ const dispatch = useRushEventDispatchContext();
+
+ const [selectOptionState, setSelectOptionState] = useState([]);
+
+ useEffect(() => {
+ if (rushIdx !== undefined) {
+ setSelectOptionState([rushList[rushIdx].leftOption, rushList[rushIdx].rightOption]);
+ }
+ }, [rushList]);
+
+ const handleUpdate = () => {
+ const updatedTableItemList = rushList.map((item, idx) => {
+ if (idx === rushIdx) {
+ return {
+ ...item,
+ leftOption: selectOptionState[0],
+ rightOption: selectOptionState[1],
+ };
+ }
+ return { ...item };
+ });
+
+ dispatch({
+ type: RUSH_ACTION.SET_EVENT_LIST,
+ payload: updatedTableItemList,
+ });
+ };
+
+ const handleChangeItem = (key: string, changeIdx: number, text: string) => {
+ const updatedItem = selectOptionState.map((item, idx) => {
+ if (idx === changeIdx) {
+ return { ...item, [key]: text };
+ }
+ return { ...item };
+ });
+
+ setSelectOptionState(updatedItem);
+ };
+
+ const getSelectOption = (idx: number) => {
+ if (selectOptionState.length >= 2) {
+ return [
+ [
+ "메인 문구 (15자 이내)",
+ handleChangeItem("mainText", idx, e.target.value)}
+ />,
+ ],
+ [
+ "서브 문구 (40자 이내)",
+ handleChangeItem("subText", idx, e.target.value)}
+ />,
+ ],
+ ];
+ }
+ return [];
+ };
+ const getSelectOptionResult = (idx: number) => {
+ if (selectOptionState.length >= 2) {
+ return [
+ ["이미지", ],
+ [
+ "메인 문구 (20자 이내)",
+ handleChangeItem("resultMainText", idx, e.target.value)}
+ />,
+ ],
+ [
+ "서브 문구 (45자 이내)",
+ handleChangeItem("resultSubText", idx, e.target.value)}
+ />,
+ ],
+ ];
+ }
+ return [];
+ };
+
+ return (
+
+
+
navigate(-1)}
+ />
+
밸런스 게임 선택지 관리
+
+
+
+
+
+ 임시 저장
+
+
+ );
+}
diff --git a/admin/src/pages/Rush/index.tsx b/admin/src/pages/Rush/index.tsx
index 79c8effb..724b3506 100644
--- a/admin/src/pages/Rush/index.tsx
+++ b/admin/src/pages/Rush/index.tsx
@@ -1,16 +1,22 @@
-import { useEffect } from "react";
-import { useLoaderData } from "react-router-dom";
+import { useCallback, useEffect } from "react";
+import { useLoaderData, useSearchParams } from "react-router-dom";
import TabHeader from "@/components/TabHeader";
+import { QUERY_OPTION } from "@/constants/rush";
import EventList from "@/features/Rush/EventList";
+import RushPrizeForm from "@/features/Rush/RushPrizeForm";
+import RushSelectForm from "@/features/Rush/RushSelectForm";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import { RUSH_ACTION } from "@/types/rush";
import { GetRushEventResponse } from "@/types/rushApi";
export default function Rush() {
+ const [searchParams] = useSearchParams();
const dispatch = useRushEventDispatchContext();
const rushEvent = useLoaderData() as GetRushEventResponse;
+ const query = searchParams.get("q");
+
useEffect(() => {
dispatch({
type: RUSH_ACTION.SET_EVENT_LIST,
@@ -18,11 +24,21 @@ export default function Rush() {
});
}, []);
+ const renderElement = useCallback(() => {
+ if (query === QUERY_OPTION.OPTION) {
+ return ;
+ } else if (query === QUERY_OPTION.PRIZE) {
+ return ;
+ }
+
+ return ;
+ }, [query, rushEvent]);
+
return (
-
+ {renderElement()}
);
}
diff --git a/admin/src/pages/RushPrizeForm/index.tsx b/admin/src/pages/RushPrizeForm/index.tsx
deleted file mode 100644
index eb3ea086..00000000
--- a/admin/src/pages/RushPrizeForm/index.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import Button from "@/components/Button";
-import SelectForm from "@/components/SelectForm";
-import TabHeader from "@/components/TabHeader";
-import TextField from "@/components/TextField";
-import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
-import useRushEventStateContext from "@/hooks/useRushEventStateContext";
-import { RUSH_ACTION, RushPrizeType } from "@/types/rush";
-
-export default function RushPrizeForm() {
- const navigate = useNavigate();
-
- const { prize } = useRushEventStateContext();
- const dispatch = useRushEventDispatchContext();
-
- const [prizeState, setPrizeState] = useState({} as RushPrizeType);
-
- useEffect(() => {
- setPrizeState(prize);
- }, [prize]);
- useEffect(() => {
- dispatch({
- type: RUSH_ACTION.SET_PRIZE,
- payload: {
- prizeImageUrl: "prize.png",
- prizeDescription: "메가박스 영화 예매권",
- },
- });
- }, []);
-
- const handleUpdate = () => {
- dispatch({
- type: RUSH_ACTION.SET_PRIZE,
- payload: prizeState,
- });
- };
-
- const option = [
- ["이미지", ],
- [
- "경품 이름 (20자 이내)",
- setPrizeState({ ...prizeState, prizeDescription: e.target.value })}
- />,
- ],
- ];
-
- return (
-
-
-
-
-
-
navigate(-1)}
- />
-
밸런스 게임 경품 관리
-
-
-
-
-
- 임시 저장
-
-
-
- );
-}
diff --git a/admin/src/pages/RushSelectForm/index.tsx b/admin/src/pages/RushSelectForm/index.tsx
deleted file mode 100644
index 06839707..00000000
--- a/admin/src/pages/RushSelectForm/index.tsx
+++ /dev/null
@@ -1,143 +0,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import Button from "@/components/Button";
-import SelectForm from "@/components/SelectForm";
-import TabHeader from "@/components/TabHeader";
-import TextField from "@/components/TextField";
-import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
-import useRushEventStateContext from "@/hooks/useRushEventStateContext";
-import { RUSH_ACTION, RushOptionType } from "@/types/rush";
-
-export default function RushSelectForm() {
- const navigate = useNavigate();
-
- const { selectOptions } = useRushEventStateContext();
- const dispatch = useRushEventDispatchContext();
-
- const [selectOptionState, setSelectOptionState] = useState([]);
-
- useEffect(() => {
- setSelectOptionState(selectOptions);
- }, [selectOptions]);
- useEffect(() => {
- dispatch({
- type: RUSH_ACTION.SET_OPTION,
- payload: [
- {
- rushOptionId: 1,
- mainText: "첫 차로 저렴한 차 사기",
- subText: "첫 차는 가성비가 짱이지!",
- resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
- resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
- },
- {
- rushOptionId: 2,
- mainText: "첫 차로 성능 좋은 차 사기",
- subText: "차는 당연히 성능이지!",
- resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
- resultSubText: "전기차 평균보다 훨씨니 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
- },
- ],
- });
- }, []);
-
- const handleUpdate = () => {
- dispatch({ type: RUSH_ACTION.SET_OPTION, payload: selectOptionState });
- };
-
- const handleChangeItem = (key: string, changeIdx: number, text: string) => {
- const updatedItem = selectOptionState.map((item, idx) => {
- if (idx === changeIdx) {
- return { ...item, [key]: text };
- }
- return { ...item };
- });
-
- setSelectOptionState(updatedItem);
- };
-
- const getSelectOption = (idx: number) => {
- if (selectOptionState.length >= 2) {
- return [
- [
- "메인 문구 (15자 이내)",
- handleChangeItem("mainText", idx, e.target.value)}
- />,
- ],
- [
- "서브 문구 (40자 이내)",
- handleChangeItem("subText", idx, e.target.value)}
- />,
- ],
- ];
- }
- return [];
- };
- const getSelectOptionResult = (idx: number) => {
- if (selectOptionState.length >= 2) {
- return [
- ["이미지", ],
- [
- "메인 문구 (20자 이내)",
- handleChangeItem("resultMainText", idx, e.target.value)}
- />,
- ],
- [
- "서브 문구 (45자 이내)",
- handleChangeItem("resultSubText", idx, e.target.value)}
- />,
- ],
- ];
- }
- return [];
- };
-
- return (
-
-
-
-
-
-
navigate(-1)}
- />
-
밸런스 게임 선택지 관리
-
-
-
-
-
- 임시 저장
-
-
-
- );
-}
diff --git a/admin/src/router.tsx b/admin/src/router.tsx
index ed5fecb8..5b81312c 100644
--- a/admin/src/router.tsx
+++ b/admin/src/router.tsx
@@ -9,8 +9,6 @@ import Lottery from "./pages/Lottery";
import LotteryWinner from "./pages/LotteryWinner";
import LotteryWinnerList from "./pages/LotteryWinnerList";
import Rush from "./pages/Rush";
-import RushPrizeForm from "./pages/RushPrizeForm";
-import RushSelectForm from "./pages/RushSelectForm";
import RushWinnerList from "./pages/RushWinnerList";
export const router = createBrowserRouter([
@@ -39,14 +37,6 @@ export const router = createBrowserRouter([
element: ,
loader: RushAPI.getRush,
},
- {
- path: "select-form",
- element: ,
- },
- {
- path: "prize-form",
- element: ,
- },
{
path: "winner-list",
element: ,
diff --git a/admin/src/types/rush.ts b/admin/src/types/rush.ts
index ae0dedc2..31b38d41 100644
--- a/admin/src/types/rush.ts
+++ b/admin/src/types/rush.ts
@@ -11,6 +11,8 @@ export interface RushEventType {
prizeImageUrl: string;
prizeDescription: string;
status: RushEventStatusType;
+ leftOption: RushOptionType;
+ rightOption: RushOptionType;
}
export interface RushOptionType {
@@ -29,29 +31,16 @@ export interface RushPrizeType {
export interface RushEventStateType {
rushList: RushEventType[];
- selectOptions: RushOptionType[];
- prize: RushPrizeType;
}
export const RUSH_ACTION = {
SET_EVENT_LIST: "SET_EVENT_LIST",
- SET_OPTION: "SET_OPTION",
- SET_PRIZE: "SET_PRIZE",
} as const;
-export type RushEventAction =
- | {
- type: typeof RUSH_ACTION.SET_EVENT_LIST;
- payload: RushEventType[];
- }
- | {
- type: typeof RUSH_ACTION.SET_OPTION;
- payload: RushOptionType[];
- }
- | {
- type: typeof RUSH_ACTION.SET_PRIZE;
- payload: RushPrizeType;
- };
+export type RushEventAction = {
+ type: typeof RUSH_ACTION.SET_EVENT_LIST;
+ payload: RushEventType[];
+};
export type RushEventDispatchType = Dispatch;
From d1f52e869e57815860c95ec6fb33b5045b713bd9 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 16:38:32 +0900
Subject: [PATCH 08/19] =?UTF-8?q?feat:=20=EC=84=A0=EC=B0=A9=EC=88=9C=20?=
=?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=88=98=EC=A0=95=20API?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/apis/lotteryAPI.ts | 8 ++++----
admin/src/apis/rushAPI.ts | 17 +++++++++++++++++
admin/src/features/Rush/EventList.tsx | 13 +++++++++++++
admin/src/pages/Lottery/index.tsx | 6 +++---
admin/src/types/lotteryApi.ts | 4 ++--
admin/src/types/rushApi.ts | 4 ++++
6 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/admin/src/apis/lotteryAPI.ts b/admin/src/apis/lotteryAPI.ts
index 98c9cece..5da50304 100644
--- a/admin/src/apis/lotteryAPI.ts
+++ b/admin/src/apis/lotteryAPI.ts
@@ -4,9 +4,9 @@ import {
GetLotteryResponse,
GetLotteryWinnerParams,
GetLotteryWinnerResponse,
- PostLotteryParams,
- PostLotteryResponse,
PostLotteryWinnerResponse,
+ PutLotteryParams,
+ PutLotteryResponse,
} from "@/types/lotteryApi";
import { fetchWithTimeout } from "@/utils/fetchWithTimeout";
@@ -41,7 +41,7 @@ export const LotteryAPI = {
throw error;
}
},
- async postLottery(body: PostLotteryParams): Promise {
+ async putLottery(body: PutLotteryParams): Promise {
try {
return new Promise((resolve) =>
resolve({
@@ -53,7 +53,7 @@ export const LotteryAPI = {
})
);
const response = await fetchWithTimeout(`${baseURL}`, {
- method: "POST",
+ method: "PUT",
headers: headers,
body: JSON.stringify(body),
});
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index bd614967..d5de368c 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -1,3 +1,4 @@
+import { RushEventType } from "@/types/rush";
import {
GetRushEventResponse,
GetRushOptionsParams,
@@ -5,6 +6,8 @@ import {
GetRushParticipantListParams,
GetRushParticipantListResponse,
GetRushWinnerListParams,
+ PutRushEventParams,
+ PutRushEventResponse,
} from "@/types/rushApi";
import { fetchWithTimeout } from "@/utils/fetchWithTimeout";
@@ -108,6 +111,20 @@ export const RushAPI = {
throw error;
}
},
+ async putRush(body: PutRushEventParams): Promise {
+ try {
+ return new Promise((resolve) => resolve([]));
+ const response = await fetchWithTimeout(`${baseURL}`, {
+ method: "PUT",
+ headers: headers,
+ body: JSON.stringify(body),
+ });
+ return response.json();
+ } catch (error) {
+ console.error("Error:", error);
+ throw error;
+ }
+ },
async getRushParticipantList({
id,
phoneNumber,
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index 9ceb7607..e7e65d67 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -1,13 +1,17 @@
+import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
+import { RushAPI } from "@/apis/rushAPI";
import Button from "@/components/Button";
import DatePicker from "@/components/DatePicker";
import Table from "@/components/Table";
import TimePicker from "@/components/TimePicker";
import { STATUS_MAP } from "@/constants/common";
import { EVENT_LIST_HEADER, QUERY_OPTION } from "@/constants/rush";
+import useFetch from "@/hooks/useFetch";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import useRushEventStateContext from "@/hooks/useRushEventStateContext";
import { RUSH_ACTION } from "@/types/rush";
+import { PutRushEventResponse } from "@/types/rushApi";
import { getTimeDifference } from "@/utils/getTimeDifference";
export default function EventList() {
@@ -16,6 +20,15 @@ export default function EventList() {
const { rushList } = useRushEventStateContext();
const dispatch = useRushEventDispatchContext();
+ const { isSuccess: isSuccessPutRush } = useFetch(() =>
+ RushAPI.putRush(rushList)
+ );
+
+ useEffect(() => {
+ if (isSuccessPutRush) {
+ }
+ }, [isSuccessPutRush]);
+
const handleChangeItem = (key: string, changeIdx: number, text: string | number) => {
const updatedTableItemList = rushList.map((item, idx) => {
if (idx === changeIdx) {
diff --git a/admin/src/pages/Lottery/index.tsx b/admin/src/pages/Lottery/index.tsx
index 5929c131..f129f82d 100644
--- a/admin/src/pages/Lottery/index.tsx
+++ b/admin/src/pages/Lottery/index.tsx
@@ -10,7 +10,7 @@ import { STATUS_MAP } from "@/constants/common";
import { LOTTERY_HEADER } from "@/constants/lottery";
import useFetch from "@/hooks/useFetch";
import { LotteryEventType } from "@/types/lottery";
-import { PostLotteryResponse } from "@/types/lotteryApi";
+import { PutLotteryResponse } from "@/types/lotteryApi";
import { getDateDifference } from "@/utils/getDateDifference";
export default function Lottery() {
@@ -20,8 +20,8 @@ export default function Lottery() {
const [lottery, setLottery] = useState({} as LotteryEventType);
const { isSuccess: isSuccessPostLottery, fetchData: postLottery } =
- useFetch(() =>
- LotteryAPI.postLottery({
+ useFetch(() =>
+ LotteryAPI.putLottery({
startDateTime: `${lottery.startDate} ${lottery.startTime}`,
endDateTime: `${lottery.endDate} ${lottery.endTime}`,
winnerCount: lottery.winnerCount,
diff --git a/admin/src/types/lotteryApi.ts b/admin/src/types/lotteryApi.ts
index 638f3ee6..9183c002 100644
--- a/admin/src/types/lotteryApi.ts
+++ b/admin/src/types/lotteryApi.ts
@@ -3,13 +3,13 @@ import { LotteryEventType, LotteryExpectationsType, LotteryWinnerType } from "./
export type GetLotteryResponse = LotteryEventType[];
-export interface PostLotteryParams {
+export interface PutLotteryParams {
startDateTime: string;
endDateTime: string;
winnerCount: number;
}
-export interface PostLotteryResponse {
+export interface PutLotteryResponse {
startDate: string;
startTime: string;
endDate: string;
diff --git a/admin/src/types/rushApi.ts b/admin/src/types/rushApi.ts
index 8d515e0f..02b808eb 100644
--- a/admin/src/types/rushApi.ts
+++ b/admin/src/types/rushApi.ts
@@ -26,3 +26,7 @@ export type GetRushWinnerListResponse = InfiniteParticipantListData
Date: Mon, 12 Aug 2024 16:47:19 +0900
Subject: [PATCH 09/19] =?UTF-8?q?feat:=20=ED=99=9C=EC=84=B1=ED=99=94=20?=
=?UTF-8?q?=EC=A0=84=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A7=8C=20=ED=8E=B8?=
=?UTF-8?q?=EC=A7=91=20=EA=B0=80=EB=8A=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/components/DatePicker/index.tsx | 4 +++-
admin/src/components/TimePicker/index.tsx | 4 +++-
admin/src/features/Rush/EventList.tsx | 9 ++++++++-
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/admin/src/components/DatePicker/index.tsx b/admin/src/components/DatePicker/index.tsx
index b35fe66f..f02e9cb9 100644
--- a/admin/src/components/DatePicker/index.tsx
+++ b/admin/src/components/DatePicker/index.tsx
@@ -2,10 +2,11 @@ import { ChangeEvent } from "react";
interface DatePickerProps {
date: string;
+ disabled?: boolean;
onChangeDate: (date: string) => void;
}
-export default function DatePicker({ date, onChangeDate }: DatePickerProps) {
+export default function DatePicker({ date, disabled = false, onChangeDate }: DatePickerProps) {
const handleChange = (e: ChangeEvent) => {
onChangeDate(e.target.value);
};
@@ -17,6 +18,7 @@ export default function DatePicker({ date, onChangeDate }: DatePickerProps) {
void;
}
-export default function TimePicker({ time, onChangeTime }: TimePickerProps) {
+export default function TimePicker({ time, disabled = false, onChangeTime }: TimePickerProps) {
const handleChange = (e: ChangeEvent) => {
onChangeTime(e.target.value);
};
@@ -31,6 +32,7 @@ export default function TimePicker({ time, onChangeTime }: TimePickerProps) {
{
return rushList.map((item, idx) => {
+ const canEdit = item.status !== EVENT_STATUS.BEFORE;
return [
item.rushEventId,
handleChangeItem("eventDate", idx, date)}
/>,
handleChangeItem("openTime", idx, time)}
/>,
handleChangeItem("closeTime", idx, time)}
/>,
getTimeDifference(item.openTime, item.closeTime),
navigate(`/rush?q=${QUERY_OPTION.OPTION}`, { state: { idx } })}
>
선택지 관리
,
navigate(`/rush?q=${QUERY_OPTION.PRIZE}`, { state: { idx } })}
>
@@ -71,6 +77,7 @@ export default function EventList() {
,
handleChangeItem("winnerCount", idx, parseInt(e.target.value) || 0)
From 08938eea0a7b65c9b573861ab343f917ca8a6089 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 16:57:09 +0900
Subject: [PATCH 10/19] =?UTF-8?q?feat:=20post=20=ED=9B=84=20toast=20?=
=?UTF-8?q?=EB=A9=94=EC=8B=9C=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
---
admin/src/components/Toast/index.tsx | 16 ++++++++++++++++
admin/src/hooks/useFetch.ts | 3 +++
admin/src/hooks/useInfiniteFetch.ts | 2 ++
admin/src/hooks/useToast.tsx | 24 ++++++++++++++++++++++++
admin/src/pages/Lottery/index.tsx | 7 ++++++-
5 files changed, 51 insertions(+), 1 deletion(-)
create mode 100644 admin/src/components/Toast/index.tsx
create mode 100644 admin/src/hooks/useToast.tsx
diff --git a/admin/src/components/Toast/index.tsx b/admin/src/components/Toast/index.tsx
new file mode 100644
index 00000000..2921a452
--- /dev/null
+++ b/admin/src/components/Toast/index.tsx
@@ -0,0 +1,16 @@
+interface ToastProps {
+ message: string;
+ isVisible: boolean;
+}
+
+export default function Toast({ message, isVisible }: ToastProps) {
+ return (
+
+ {message}
+
+ );
+}
diff --git a/admin/src/hooks/useFetch.ts b/admin/src/hooks/useFetch.ts
index db697c6a..7ba15c33 100644
--- a/admin/src/hooks/useFetch.ts
+++ b/admin/src/hooks/useFetch.ts
@@ -6,6 +6,9 @@ export default function useFetch(fetch: (params: P) => Promise)
const [isError, setIsError] = useState(false);
const fetchData = async (params?: P) => {
+ setIsError(false);
+ setIsSuccess(false);
+
try {
const data = await fetch(params as P);
setData(data);
diff --git a/admin/src/hooks/useInfiniteFetch.ts b/admin/src/hooks/useInfiniteFetch.ts
index d9d57c5c..89394f2b 100644
--- a/admin/src/hooks/useInfiniteFetch.ts
+++ b/admin/src/hooks/useInfiniteFetch.ts
@@ -36,6 +36,8 @@ export default function useInfiniteFetch({
if (!hasNextPage || isLoading || currentPageParam === undefined) return;
setIsLoading(true);
+ setIsError(false);
+ setIsSuccess(false);
try {
const lastPage = await fetch(currentPageParam);
const nextPageParam = getNextPageParam(currentPageParam, lastPage);
diff --git a/admin/src/hooks/useToast.tsx b/admin/src/hooks/useToast.tsx
new file mode 100644
index 00000000..dabd5c10
--- /dev/null
+++ b/admin/src/hooks/useToast.tsx
@@ -0,0 +1,24 @@
+import { useCallback, useEffect, useState } from "react";
+import Toast from "../components/Toast";
+
+export default function useToast(message: string, duration: number = 3000) {
+ const [visible, setVisible] = useState(false);
+
+ const showToast = useCallback(() => {
+ setVisible(true);
+ }, []);
+
+ useEffect(() => {
+ if (visible) {
+ const timer = setTimeout(() => {
+ setVisible(false);
+ }, duration);
+
+ return () => clearTimeout(timer);
+ }
+ }, [visible, duration]);
+
+ const ToastComponent = ;
+
+ return { showToast, ToastComponent };
+}
diff --git a/admin/src/pages/Lottery/index.tsx b/admin/src/pages/Lottery/index.tsx
index f129f82d..d5d23332 100644
--- a/admin/src/pages/Lottery/index.tsx
+++ b/admin/src/pages/Lottery/index.tsx
@@ -9,6 +9,7 @@ import TimePicker from "@/components/TimePicker";
import { STATUS_MAP } from "@/constants/common";
import { LOTTERY_HEADER } from "@/constants/lottery";
import useFetch from "@/hooks/useFetch";
+import useToast from "@/hooks/useToast";
import { LotteryEventType } from "@/types/lottery";
import { PutLotteryResponse } from "@/types/lotteryApi";
import { getDateDifference } from "@/utils/getDateDifference";
@@ -16,6 +17,8 @@ import { getDateDifference } from "@/utils/getDateDifference";
export default function Lottery() {
const navigate = useNavigate();
+ const { showToast, ToastComponent } = useToast("수정 사항이 반영되었습니다!");
+
const lotteryData = useLoaderData() as LotteryEventType[];
const [lottery, setLottery] = useState({} as LotteryEventType);
@@ -35,7 +38,7 @@ export default function Lottery() {
}, []);
useEffect(() => {
if (isSuccessPostLottery) {
- // TODO: toast 메시지
+ showToast();
}
}, [isSuccessPostLottery]);
@@ -103,6 +106,8 @@ export default function Lottery() {
수정사항 업데이트
+
+ {ToastComponent}
);
}
From 3235ebde19d8fec0f65ac84c23ff4d3ac59666ac Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 17:07:00 +0900
Subject: [PATCH 11/19] =?UTF-8?q?feat:=20put/=EC=9E=84=EC=8B=9C=20?=
=?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EC=8B=9C=20toast=20=EB=A9=94=EC=8B=9C?=
=?UTF-8?q?=EC=A7=80=20=EB=9D=84=EC=9A=B0=EA=B8=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/features/Rush/EventList.tsx | 16 ++++++++++++++--
admin/src/features/Rush/RushPrizeForm.tsx | 8 +++++++-
admin/src/features/Rush/RushSelectForm.tsx | 7 +++++++
3 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index 3a4b47ff..244a0822 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -10,6 +10,7 @@ import { EVENT_LIST_HEADER, QUERY_OPTION } from "@/constants/rush";
import useFetch from "@/hooks/useFetch";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import useRushEventStateContext from "@/hooks/useRushEventStateContext";
+import useToast from "@/hooks/useToast";
import { RUSH_ACTION } from "@/types/rush";
import { PutRushEventResponse } from "@/types/rushApi";
import { getTimeDifference } from "@/utils/getTimeDifference";
@@ -17,15 +18,18 @@ import { getTimeDifference } from "@/utils/getTimeDifference";
export default function EventList() {
const navigate = useNavigate();
+ const { showToast, ToastComponent } = useToast("수정 사항이 반영되었습니다!");
+
const { rushList } = useRushEventStateContext();
const dispatch = useRushEventDispatchContext();
- const { isSuccess: isSuccessPutRush } = useFetch(() =>
+ const { isSuccess: isSuccessPutRush, fetchData: putRush } = useFetch(() =>
RushAPI.putRush(rushList)
);
useEffect(() => {
if (isSuccessPutRush) {
+ showToast();
}
}, [isSuccessPutRush]);
@@ -40,6 +44,10 @@ export default function EventList() {
dispatch({ type: RUSH_ACTION.SET_EVENT_LIST, payload: updatedTableItemList });
};
+ const handleUpdate = () => {
+ putRush();
+ };
+
const getTableData = () => {
return rushList.map((item, idx) => {
const canEdit = item.status !== EVENT_STATUS.BEFORE;
@@ -103,7 +111,11 @@ export default function EventList() {
- 수정사항 업데이트
+
+ 수정사항 업데이트
+
+
+ {ToastComponent}
);
}
diff --git a/admin/src/features/Rush/RushPrizeForm.tsx b/admin/src/features/Rush/RushPrizeForm.tsx
index f749a57a..d5500b64 100644
--- a/admin/src/features/Rush/RushPrizeForm.tsx
+++ b/admin/src/features/Rush/RushPrizeForm.tsx
@@ -2,10 +2,10 @@ import { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import Button from "@/components/Button";
import SelectForm from "@/components/SelectForm";
-import TabHeader from "@/components/TabHeader";
import TextField from "@/components/TextField";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import useRushEventStateContext from "@/hooks/useRushEventStateContext";
+import useToast from "@/hooks/useToast";
import { RUSH_ACTION, RushPrizeType } from "@/types/rush";
export default function RushPrizeForm() {
@@ -17,6 +17,8 @@ export default function RushPrizeForm() {
const { rushList } = useRushEventStateContext();
const dispatch = useRushEventDispatchContext();
+ const { showToast, ToastComponent } = useToast("입력한 내용이 임시 저장되었습니다!");
+
const [prizeState, setPrizeState] = useState({} as RushPrizeType);
useEffect(() => {
@@ -40,6 +42,8 @@ export default function RushPrizeForm() {
type: RUSH_ACTION.SET_EVENT_LIST,
payload: updatedTableItemList,
});
+
+ showToast();
};
const option = [
@@ -70,6 +74,8 @@ export default function RushPrizeForm() {
임시 저장
+
+ {ToastComponent}
);
}
diff --git a/admin/src/features/Rush/RushSelectForm.tsx b/admin/src/features/Rush/RushSelectForm.tsx
index cb8ca0ad..8f76ab87 100644
--- a/admin/src/features/Rush/RushSelectForm.tsx
+++ b/admin/src/features/Rush/RushSelectForm.tsx
@@ -5,6 +5,7 @@ import SelectForm from "@/components/SelectForm";
import TextField from "@/components/TextField";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
import useRushEventStateContext from "@/hooks/useRushEventStateContext";
+import useToast from "@/hooks/useToast";
import { RUSH_ACTION, RushOptionType } from "@/types/rush";
export default function RushSelectForm() {
@@ -16,6 +17,8 @@ export default function RushSelectForm() {
const { rushList } = useRushEventStateContext();
const dispatch = useRushEventDispatchContext();
+ const { showToast, ToastComponent } = useToast("입력한 내용이 임시 저장되었습니다!");
+
const [selectOptionState, setSelectOptionState] = useState([]);
useEffect(() => {
@@ -40,6 +43,8 @@ export default function RushSelectForm() {
type: RUSH_ACTION.SET_EVENT_LIST,
payload: updatedTableItemList,
});
+
+ showToast();
};
const handleChangeItem = (key: string, changeIdx: number, text: string) => {
@@ -123,6 +128,8 @@ export default function RushSelectForm() {
임시 저장
+
+ {ToastComponent}
);
}
From bfe3a13b9371452daafb5e9ffd7b295258f86b4a Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 17:14:07 +0900
Subject: [PATCH 12/19] =?UTF-8?q?fix:=20=EC=8B=9C=EA=B0=84=20=EB=94=94?=
=?UTF-8?q?=ED=8F=B4=ED=8A=B8=20=EC=B4=88=20=EC=84=A4=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/apis/lotteryAPI.ts | 8 ++++----
admin/src/apis/rushAPI.ts | 1 -
admin/src/components/TimePicker/index.tsx | 7 ++++++-
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/admin/src/apis/lotteryAPI.ts b/admin/src/apis/lotteryAPI.ts
index 5da50304..61d4d7fd 100644
--- a/admin/src/apis/lotteryAPI.ts
+++ b/admin/src/apis/lotteryAPI.ts
@@ -22,9 +22,9 @@ export const LotteryAPI = {
resolve([
{
startDate: "2024-07-26",
- startTime: "00:00",
+ startTime: "00:00:00",
endDate: "2024-08-25",
- endTime: "23:59",
+ endTime: "23:59:00",
appliedCount: 1000000,
winnerCount: 363,
status: "BEFORE",
@@ -46,9 +46,9 @@ export const LotteryAPI = {
return new Promise((resolve) =>
resolve({
startDate: "2024-08-26",
- startTime: "00:00:000",
+ startTime: "00:00:00",
endDate: "2024-09-25 23:59",
- endTime: "00:00:000",
+ endTime: "00:00:00",
winnerCount: 363,
})
);
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index d5de368c..9d82d88d 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -1,4 +1,3 @@
-import { RushEventType } from "@/types/rush";
import {
GetRushEventResponse,
GetRushOptionsParams,
diff --git a/admin/src/components/TimePicker/index.tsx b/admin/src/components/TimePicker/index.tsx
index 48cd2f2a..e5f793ae 100644
--- a/admin/src/components/TimePicker/index.tsx
+++ b/admin/src/components/TimePicker/index.tsx
@@ -8,7 +8,12 @@ interface TimePickerProps {
export default function TimePicker({ time, disabled = false, onChangeTime }: TimePickerProps) {
const handleChange = (e: ChangeEvent) => {
- onChangeTime(e.target.value);
+ /**
+ * 시간-분 까지만 선택 가능
+ * 초는 0초를 디폴트로 넣는다
+ */
+ const time = `${e.target.value}:00`;
+ onChangeTime(time);
};
return (
From 14a3f0a61d7891463e76a3ce734aa3ea33e11da9 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 18:02:40 +0900
Subject: [PATCH 13/19] =?UTF-8?q?fix:=20=EB=B9=8C=EB=93=9C=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
---
admin/src/apis/lotteryAPI.ts | 5 ++---
admin/src/pages/Lottery/index.tsx | 9 +--------
admin/src/pages/LotteryParticipantList/index.tsx | 9 ++-------
3 files changed, 5 insertions(+), 18 deletions(-)
diff --git a/admin/src/apis/lotteryAPI.ts b/admin/src/apis/lotteryAPI.ts
index 743fee8f..3ad2573c 100644
--- a/admin/src/apis/lotteryAPI.ts
+++ b/admin/src/apis/lotteryAPI.ts
@@ -78,7 +78,6 @@ export const LotteryAPI = {
}
},
async getLotteryParticipant({
- id,
size,
page,
phoneNumber,
@@ -86,7 +85,7 @@ export const LotteryAPI = {
try {
return new Promise((resolve) =>
resolve({
- data: [
+ participants: [
{
id: 1,
phoneNumber: "010-1111-2222",
@@ -120,7 +119,7 @@ export const LotteryAPI = {
})
);
const response = await fetchWithTimeout(
- `${baseURL}/${id}/participants?size=${size}&page=${page}&number=${phoneNumber}`,
+ `${baseURL}/participants?size=${size}&page=${page}&number=${phoneNumber}`,
{
method: "GET",
headers: headers,
diff --git a/admin/src/pages/Lottery/index.tsx b/admin/src/pages/Lottery/index.tsx
index 9d9b024b..d5d23332 100644
--- a/admin/src/pages/Lottery/index.tsx
+++ b/admin/src/pages/Lottery/index.tsx
@@ -91,14 +91,7 @@ export default function Lottery() {
-
- navigate("/lottery/participant-list", {
- state: { id: lottery.lotteryEventId },
- })
- }
- >
+ navigate("/lottery/participant-list")}>
참여자 리스트 보러가기
navigate("/lottery/winner")}>
diff --git a/admin/src/pages/LotteryParticipantList/index.tsx b/admin/src/pages/LotteryParticipantList/index.tsx
index 8daf293f..4de92da9 100644
--- a/admin/src/pages/LotteryParticipantList/index.tsx
+++ b/admin/src/pages/LotteryParticipantList/index.tsx
@@ -1,5 +1,5 @@
import { useMemo, useRef, useState } from "react";
-import { useLocation, useNavigate } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
import { LotteryAPI } from "@/apis/lotteryAPI";
import Button from "@/components/Button";
import TabHeader from "@/components/TabHeader";
@@ -12,11 +12,8 @@ import { LotteryExpectationsType } from "@/types/lottery";
import { GetLotteryParticipantResponse } from "@/types/lotteryApi";
export default function LotteryParticipantList() {
- const location = useLocation();
const navigate = useNavigate();
- const lotteryId = location.state.id;
-
const { handleOpenModal, ModalComponent } = useModal();
const [selectedParticipant, setSelectedParticipant] = useState([]);
const phoneNumberRef = useRef("");
@@ -31,7 +28,6 @@ export default function LotteryParticipantList() {
} = useInfiniteFetch({
fetch: (pageParam: number) =>
LotteryAPI.getLotteryParticipant({
- id: lotteryId,
size: 10,
page: pageParam,
phoneNumber: phoneNumberRef.current,
@@ -54,14 +50,13 @@ export default function LotteryParticipantList() {
};
const handleLotteryWinner = () => {
- navigate("/lottery/winner-list", { state: { id: lotteryId } });
+ navigate("/lottery/winner-list");
};
const handleClickExpectation = async (participantId: number) => {
handleOpenModal();
const data = await LotteryAPI.getLotteryExpectations({
- lotteryId,
participantId: participantId,
});
setSelectedParticipant(data);
From 5b8c4f601e2e4a128a67576a9f1ac1fa48886cc6 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 18:42:00 +0900
Subject: [PATCH 14/19] =?UTF-8?q?feat:=20file=20input=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/apis/rushAPI.ts | 17 +++++----
admin/src/components/FileInput/index.tsx | 42 ++++++++++++++++++++++
admin/src/components/Layout/index.tsx | 2 +-
admin/src/features/Rush/EventList.tsx | 9 ++++-
admin/src/features/Rush/RushSelectForm.tsx | 24 ++++++++++++-
5 files changed, 82 insertions(+), 12 deletions(-)
create mode 100644 admin/src/components/FileInput/index.tsx
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index 9d82d88d..df35e0bb 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -35,7 +35,7 @@ export const RushAPI = {
subText: "첫 차는 가성비가 짱이지!",
resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/660/660026.png",
},
rightOption: {
rushOptionId: 2,
@@ -43,7 +43,7 @@ export const RushAPI = {
subText: "차는 당연히 성능이지!",
resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/846/846551.png",
},
},
{
@@ -61,7 +61,7 @@ export const RushAPI = {
subText: "첫 차는 가성비가 짱이지!",
resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/660/660026.png",
},
rightOption: {
rushOptionId: 2,
@@ -69,7 +69,7 @@ export const RushAPI = {
subText: "차는 당연히 성능이지!",
resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/846/846551.png",
},
},
{
@@ -87,7 +87,7 @@ export const RushAPI = {
subText: "첫 차는 가성비가 짱이지!",
resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/660/660026.png",
},
rightOption: {
rushOptionId: 2,
@@ -95,7 +95,7 @@ export const RushAPI = {
subText: "차는 당연히 성능이지!",
resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/846/846551.png",
},
},
])
@@ -115,7 +115,6 @@ export const RushAPI = {
return new Promise((resolve) => resolve([]));
const response = await fetchWithTimeout(`${baseURL}`, {
method: "PUT",
- headers: headers,
body: JSON.stringify(body),
});
return response.json();
@@ -233,7 +232,7 @@ export const RushAPI = {
subText: " 첫 차는 가성비가 짱이지!",
resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/660/660026.png",
},
{
rushOptionId: 2,
@@ -241,7 +240,7 @@ export const RushAPI = {
subText: " 차는 당연히 성능이지!",
resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씨니 저렴한 캐스퍼 일렉트릭!",
- imageUrl: "left_image.png",
+ imageUrl: "https://cdn-icons-png.flaticon.com/512/660/660026.png",
},
])
);
diff --git a/admin/src/components/FileInput/index.tsx b/admin/src/components/FileInput/index.tsx
new file mode 100644
index 00000000..82cba5ed
--- /dev/null
+++ b/admin/src/components/FileInput/index.tsx
@@ -0,0 +1,42 @@
+import { useEffect, useState } from "react";
+
+interface FileInputProps {
+ selectedFile: File | string | null;
+ setSelectedFile: (file: File | null) => void;
+}
+
+export default function FileInput({ selectedFile, setSelectedFile }: FileInputProps) {
+ const [previewUrl, setPreviewUrl] = useState(null);
+
+ useEffect(() => {
+ if (!selectedFile) {
+ setPreviewUrl(null);
+ return;
+ }
+ if (typeof selectedFile === "string") {
+ setPreviewUrl(selectedFile);
+ return;
+ }
+
+ const objectUrl = URL.createObjectURL(selectedFile);
+ setPreviewUrl(objectUrl);
+
+ return () => URL.revokeObjectURL(objectUrl);
+ }, [selectedFile]);
+
+ const handleFileChange = (event: React.ChangeEvent) => {
+ const file = event.target.files?.[0];
+ if (file) {
+ setSelectedFile(file);
+ }
+ };
+
+ return (
+
+ {previewUrl && (
+
+ )}
+
+
+ );
+}
diff --git a/admin/src/components/Layout/index.tsx b/admin/src/components/Layout/index.tsx
index 5a180cf9..d28600a8 100644
--- a/admin/src/components/Layout/index.tsx
+++ b/admin/src/components/Layout/index.tsx
@@ -8,7 +8,7 @@ export default function Layout() {
return (
}>
-
+
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index 244a0822..9bc81c3f 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -24,7 +24,7 @@ export default function EventList() {
const dispatch = useRushEventDispatchContext();
const { isSuccess: isSuccessPutRush, fetchData: putRush } = useFetch
(() =>
- RushAPI.putRush(rushList)
+ RushAPI.putRush([])
);
useEffect(() => {
@@ -33,6 +33,13 @@ export default function EventList() {
}
}, [isSuccessPutRush]);
+ const getFormData = () => {
+ return rushList.map((rush) => {
+ const formData = new FormData();
+ // formData.append("image", selectedFile);
+ });
+ };
+
const handleChangeItem = (key: string, changeIdx: number, text: string | number) => {
const updatedTableItemList = rushList.map((item, idx) => {
if (idx === changeIdx) {
diff --git a/admin/src/features/Rush/RushSelectForm.tsx b/admin/src/features/Rush/RushSelectForm.tsx
index 8f76ab87..cde97732 100644
--- a/admin/src/features/Rush/RushSelectForm.tsx
+++ b/admin/src/features/Rush/RushSelectForm.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import Button from "@/components/Button";
+import FileInput from "@/components/FileInput";
import SelectForm from "@/components/SelectForm";
import TextField from "@/components/TextField";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
@@ -20,10 +21,15 @@ export default function RushSelectForm() {
const { showToast, ToastComponent } = useToast("입력한 내용이 임시 저장되었습니다!");
const [selectOptionState, setSelectOptionState] = useState([]);
+ const [selectedFile, setSelectedFile] = useState<(File | string | null)[]>([]);
useEffect(() => {
if (rushIdx !== undefined) {
setSelectOptionState([rushList[rushIdx].leftOption, rushList[rushIdx].rightOption]);
+ setSelectedFile([
+ rushList[rushIdx].leftOption.imageUrl,
+ rushList[rushIdx].rightOption.imageUrl,
+ ]);
}
}, [rushList]);
@@ -58,6 +64,16 @@ export default function RushSelectForm() {
setSelectOptionState(updatedItem);
};
+ const handleSelectFile = (idx: number, file: File | null) => {
+ const updatedSelectedFile = selectedFile.map((selected, selectedIdx) => {
+ if (selectedIdx === idx) {
+ return file;
+ }
+ return selected;
+ });
+ setSelectedFile(updatedSelectedFile);
+ };
+
const getSelectOption = (idx: number) => {
if (selectOptionState.length >= 2) {
return [
@@ -82,7 +98,13 @@ export default function RushSelectForm() {
const getSelectOptionResult = (idx: number) => {
if (selectOptionState.length >= 2) {
return [
- ["이미지", ],
+ [
+ "이미지",
+ handleSelectFile(idx, file)}
+ />,
+ ],
[
"메인 문구 (20자 이내)",
Date: Mon, 12 Aug 2024 20:28:17 +0900
Subject: [PATCH 15/19] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?=
=?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20=EB=A1=9C=EC=A7=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin/src/apis/rushAPI.ts | 3 +--
admin/src/components/FileInput/index.tsx | 2 +-
admin/src/features/Rush/EventList.tsx | 31 ++++++++++++++++++++--
admin/src/features/Rush/RushPrizeForm.tsx | 9 ++++++-
admin/src/features/Rush/RushSelectForm.tsx | 21 +++------------
admin/src/types/rush.ts | 15 +++--------
6 files changed, 45 insertions(+), 36 deletions(-)
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index df35e0bb..1cae7fb5 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -5,7 +5,6 @@ import {
GetRushParticipantListParams,
GetRushParticipantListResponse,
GetRushWinnerListParams,
- PutRushEventParams,
PutRushEventResponse,
} from "@/types/rushApi";
import { fetchWithTimeout } from "@/utils/fetchWithTimeout";
@@ -110,7 +109,7 @@ export const RushAPI = {
throw error;
}
},
- async putRush(body: PutRushEventParams): Promise {
+ async putRush(body: FormData[]): Promise {
try {
return new Promise((resolve) => resolve([]));
const response = await fetchWithTimeout(`${baseURL}`, {
diff --git a/admin/src/components/FileInput/index.tsx b/admin/src/components/FileInput/index.tsx
index 82cba5ed..a9f652b3 100644
--- a/admin/src/components/FileInput/index.tsx
+++ b/admin/src/components/FileInput/index.tsx
@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
interface FileInputProps {
selectedFile: File | string | null;
- setSelectedFile: (file: File | null) => void;
+ setSelectedFile: (file: File) => void;
}
export default function FileInput({ selectedFile, setSelectedFile }: FileInputProps) {
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index 9bc81c3f..4f3affb9 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -24,7 +24,7 @@ export default function EventList() {
const dispatch = useRushEventDispatchContext();
const { isSuccess: isSuccessPutRush, fetchData: putRush } = useFetch(() =>
- RushAPI.putRush([])
+ RushAPI.putRush(getFormData())
);
useEffect(() => {
@@ -36,7 +36,34 @@ export default function EventList() {
const getFormData = () => {
return rushList.map((rush) => {
const formData = new FormData();
- // formData.append("image", selectedFile);
+
+ formData.append("rushEventId", rush.rushEventId.toString());
+ formData.append("eventDate", rush.eventDate);
+ formData.append("openTime", rush.openTime);
+ formData.append("closeTime", rush.closeTime);
+ formData.append("winnerCount", rush.winnerCount.toString());
+ formData.append("prizeDescription", rush.prizeDescription);
+ formData.append("status", rush.status);
+
+ formData.append("prizeImageUrl", rush.prizeImageUrl);
+
+ formData.append("leftOption[rushOptionId]", rush.leftOption.rushOptionId.toString());
+ formData.append("leftOption[mainText]", rush.leftOption.mainText);
+ formData.append("leftOption[subText]", rush.leftOption.subText);
+ formData.append("leftOption[resultMainText]", rush.leftOption.resultMainText);
+ formData.append("leftOption[resultSubText]", rush.leftOption.resultSubText);
+
+ formData.append("leftOption[imageUrl]", rush.leftOption.imageUrl);
+
+ formData.append("rightOption[rushOptionId]", rush.rightOption.rushOptionId.toString());
+ formData.append("rightOption[mainText]", rush.rightOption.mainText);
+ formData.append("rightOption[subText]", rush.rightOption.subText);
+ formData.append("rightOption[resultMainText]", rush.rightOption.resultMainText);
+ formData.append("rightOption[resultSubText]", rush.rightOption.resultSubText);
+
+ formData.append("rightOption[imageUrl]", rush.rightOption.imageUrl);
+
+ return formData;
});
};
diff --git a/admin/src/features/Rush/RushPrizeForm.tsx b/admin/src/features/Rush/RushPrizeForm.tsx
index d5500b64..04d678d6 100644
--- a/admin/src/features/Rush/RushPrizeForm.tsx
+++ b/admin/src/features/Rush/RushPrizeForm.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import Button from "@/components/Button";
+import FileInput from "@/components/FileInput";
import SelectForm from "@/components/SelectForm";
import TextField from "@/components/TextField";
import useRushEventDispatchContext from "@/hooks/useRushEventDispatchContext";
@@ -47,7 +48,13 @@ export default function RushPrizeForm() {
};
const option = [
- ["이미지", ],
+ [
+ "이미지",
+ setPrizeState({ ...prizeState, prizeImageUrl: file })}
+ />,
+ ],
[
"경품 이름 (20자 이내)",
([]);
- const [selectedFile, setSelectedFile] = useState<(File | string | null)[]>([]);
useEffect(() => {
if (rushIdx !== undefined) {
setSelectOptionState([rushList[rushIdx].leftOption, rushList[rushIdx].rightOption]);
- setSelectedFile([
- rushList[rushIdx].leftOption.imageUrl,
- rushList[rushIdx].rightOption.imageUrl,
- ]);
}
}, [rushList]);
@@ -53,7 +48,7 @@ export default function RushSelectForm() {
showToast();
};
- const handleChangeItem = (key: string, changeIdx: number, text: string) => {
+ const handleChangeItem = (key: string, changeIdx: number, text: string | File) => {
const updatedItem = selectOptionState.map((item, idx) => {
if (idx === changeIdx) {
return { ...item, [key]: text };
@@ -64,16 +59,6 @@ export default function RushSelectForm() {
setSelectOptionState(updatedItem);
};
- const handleSelectFile = (idx: number, file: File | null) => {
- const updatedSelectedFile = selectedFile.map((selected, selectedIdx) => {
- if (selectedIdx === idx) {
- return file;
- }
- return selected;
- });
- setSelectedFile(updatedSelectedFile);
- };
-
const getSelectOption = (idx: number) => {
if (selectOptionState.length >= 2) {
return [
@@ -101,8 +86,8 @@ export default function RushSelectForm() {
[
"이미지",
handleSelectFile(idx, file)}
+ selectedFile={selectOptionState[idx].imageUrl}
+ setSelectedFile={(file) => handleChangeItem("imageUrl", idx, file)}
/>,
],
[
diff --git a/admin/src/types/rush.ts b/admin/src/types/rush.ts
index 31b38d41..93493e6d 100644
--- a/admin/src/types/rush.ts
+++ b/admin/src/types/rush.ts
@@ -8,7 +8,7 @@ export interface RushEventType {
openTime: string;
closeTime: string;
winnerCount: number;
- prizeImageUrl: string;
+ prizeImageUrl: File | string;
prizeDescription: string;
status: RushEventStatusType;
leftOption: RushOptionType;
@@ -21,11 +21,11 @@ export interface RushOptionType {
subText: string;
resultMainText: string;
resultSubText: string;
- imageUrl: string;
+ imageUrl: File | string;
}
export interface RushPrizeType {
- prizeImageUrl: string;
+ prizeImageUrl: File | string;
prizeDescription: string;
}
@@ -57,12 +57,3 @@ export interface RushParticipantType {
createdAt: string;
rank: number;
}
-
-export interface RushOptionType {
- rushOptionId: number;
- mainText: string;
- subText: string;
- resultMainText: string;
- resultSubText: string;
- imageUrl: string;
-}
From 533053a8d03cefdff6d02c18b8225eaffd05285d Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Mon, 12 Aug 2024 20:56:33 +0900
Subject: [PATCH 16/19] =?UTF-8?q?feat:=20=EB=AA=A9=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
---
admin/src/components/Layout/index.tsx | 2 +-
admin/src/pages/LotteryParticipantList/index.tsx | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/admin/src/components/Layout/index.tsx b/admin/src/components/Layout/index.tsx
index d28600a8..5a180cf9 100644
--- a/admin/src/components/Layout/index.tsx
+++ b/admin/src/components/Layout/index.tsx
@@ -8,7 +8,7 @@ export default function Layout() {
return (
}>
-
+
diff --git a/admin/src/pages/LotteryParticipantList/index.tsx b/admin/src/pages/LotteryParticipantList/index.tsx
index 4de92da9..1352ff21 100644
--- a/admin/src/pages/LotteryParticipantList/index.tsx
+++ b/admin/src/pages/LotteryParticipantList/index.tsx
@@ -15,7 +15,7 @@ export default function LotteryParticipantList() {
const navigate = useNavigate();
const { handleOpenModal, ModalComponent } = useModal();
- const [selectedParticipant, setSelectedParticipant] = useState
([]);
+ const [selectedExpectation, setSelectedExpectation] = useState([]);
const phoneNumberRef = useRef("");
const phoneNumberInputRef = useRef(null);
@@ -59,10 +59,10 @@ export default function LotteryParticipantList() {
const data = await LotteryAPI.getLotteryExpectations({
participantId: participantId,
});
- setSelectedParticipant(data);
+ setSelectedExpectation(data);
};
- const expectations = selectedParticipant.map((participant) => [
+ const expectations = selectedExpectation.map((participant) => [
participant.casperId,
participant.expectation,
]);
From 2d0b37b0f7e71ac997f9202c03a45d8fafef9789 Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Tue, 13 Aug 2024 10:03:16 +0900
Subject: [PATCH 17/19] =?UTF-8?q?refactor:=20useFetch=EB=A1=9Cfetch=20?=
=?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../pages/LotteryParticipantList/index.tsx | 27 ++++++++++++++-----
admin/src/pages/LotteryWinnerList/index.tsx | 27 ++++++++++++++-----
2 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/admin/src/pages/LotteryParticipantList/index.tsx b/admin/src/pages/LotteryParticipantList/index.tsx
index 1352ff21..36b012bd 100644
--- a/admin/src/pages/LotteryParticipantList/index.tsx
+++ b/admin/src/pages/LotteryParticipantList/index.tsx
@@ -1,15 +1,16 @@
-import { useMemo, useRef, useState } from "react";
+import { useEffect, useMemo, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { LotteryAPI } from "@/apis/lotteryAPI";
import Button from "@/components/Button";
import TabHeader from "@/components/TabHeader";
import Table from "@/components/Table";
import { LOTTERY_EXPECTATIONS_HEADER, LOTTERY_PARTICIPANT_HEADER } from "@/constants/lottery";
+import useFetch from "@/hooks/useFetch";
import useInfiniteFetch from "@/hooks/useInfiniteFetch";
import useIntersectionObserver from "@/hooks/useIntersectionObserver";
import useModal from "@/hooks/useModal";
import { LotteryExpectationsType } from "@/types/lottery";
-import { GetLotteryParticipantResponse } from "@/types/lotteryApi";
+import { GetLotteryExpectationsResponse, GetLotteryParticipantResponse } from "@/types/lotteryApi";
export default function LotteryParticipantList() {
const navigate = useNavigate();
@@ -38,12 +39,28 @@ export default function LotteryParticipantList() {
},
});
+ const {
+ data: expectation,
+ isSuccess: isSuccessGetLotteryExpectation,
+ fetchData: getLotteryExpectation,
+ } = useFetch((participantId: number) =>
+ LotteryAPI.getLotteryExpectations({
+ participantId: participantId,
+ })
+ );
+
const tableContainerRef = useRef(null);
const { targetRef } = useIntersectionObserver({
onIntersect: getParticipantInfo,
enabled: isSuccessGetParticipant,
});
+ useEffect(() => {
+ if (expectation && isSuccessGetLotteryExpectation) {
+ setSelectedExpectation(expectation);
+ }
+ }, [expectation, isSuccessGetLotteryExpectation]);
+
const handleRefetch = () => {
phoneNumberRef.current = phoneNumberInputRef.current?.value || "";
refetchParticipantInfo();
@@ -55,11 +72,7 @@ export default function LotteryParticipantList() {
const handleClickExpectation = async (participantId: number) => {
handleOpenModal();
-
- const data = await LotteryAPI.getLotteryExpectations({
- participantId: participantId,
- });
- setSelectedExpectation(data);
+ getLotteryExpectation(participantId);
};
const expectations = selectedExpectation.map((participant) => [
diff --git a/admin/src/pages/LotteryWinnerList/index.tsx b/admin/src/pages/LotteryWinnerList/index.tsx
index 5695bac2..7e96d4b3 100644
--- a/admin/src/pages/LotteryWinnerList/index.tsx
+++ b/admin/src/pages/LotteryWinnerList/index.tsx
@@ -1,15 +1,16 @@
-import { useMemo, useRef, useState } from "react";
+import { useEffect, useMemo, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { LotteryAPI } from "@/apis/lotteryAPI";
import Button from "@/components/Button";
import TabHeader from "@/components/TabHeader";
import Table from "@/components/Table";
import { LOTTERY_EXPECTATIONS_HEADER, LOTTERY_WINNER_HEADER } from "@/constants/lottery";
+import useFetch from "@/hooks/useFetch";
import useInfiniteFetch from "@/hooks/useInfiniteFetch";
import useIntersectionObserver from "@/hooks/useIntersectionObserver";
import useModal from "@/hooks/useModal";
import { LotteryExpectationsType } from "@/types/lottery";
-import { GetLotteryWinnerResponse } from "@/types/lotteryApi";
+import { GetLotteryExpectationsResponse, GetLotteryWinnerResponse } from "@/types/lotteryApi";
export default function LotteryWinnerList() {
const navigate = useNavigate();
@@ -37,12 +38,28 @@ export default function LotteryWinnerList() {
},
});
+ const {
+ data: expectation,
+ isSuccess: isSuccessGetLotteryExpectation,
+ fetchData: getLotteryExpectation,
+ } = useFetch((winnerId: number) =>
+ LotteryAPI.getLotteryExpectations({
+ participantId: winnerId,
+ })
+ );
+
const tableContainerRef = useRef(null);
const { targetRef } = useIntersectionObserver({
onIntersect: getWinnerInfo,
enabled: isSuccessGetLotteryWinner,
});
+ useEffect(() => {
+ if (expectation && isSuccessGetLotteryExpectation) {
+ setSelectedWinner(expectation);
+ }
+ }, [expectation, isSuccessGetLotteryExpectation]);
+
const handleRefetch = () => {
phoneNumberRef.current = phoneNumberInputRef.current?.value || "";
refetchWinnerInfo();
@@ -54,11 +71,7 @@ export default function LotteryWinnerList() {
const handleClickExpectation = async (winnerId: number) => {
handleOpenModal();
-
- const data = await LotteryAPI.getLotteryExpectations({
- participantId: winnerId,
- });
- setSelectedWinner(data);
+ getLotteryExpectation(winnerId);
};
const expectations = selectedWinner.map((winner) => [winner.casperId, winner.expectation]);
From d8b500931a4bff851b8eccb3c920af5c147285af Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Tue, 13 Aug 2024 10:15:28 +0900
Subject: [PATCH 18/19] =?UTF-8?q?chore:=20formdata=20content=20type=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
---
admin/src/apis/rushAPI.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index 1cae7fb5..c10c45f3 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -114,6 +114,7 @@ export const RushAPI = {
return new Promise((resolve) => resolve([]));
const response = await fetchWithTimeout(`${baseURL}`, {
method: "PUT",
+ headers: { "Content-Type": "multipart/form-data" },
body: JSON.stringify(body),
});
return response.json();
From c44c0dd17fd012d0122a22988fae22ff8ff56b0f Mon Sep 17 00:00:00 2001
From: jhj2713
Date: Tue, 13 Aug 2024 10:29:32 +0900
Subject: [PATCH 19/19] =?UTF-8?q?refactor:=20formdata=20=EC=B6=94=EA=B0=80?=
=?UTF-8?q?=20=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
---
admin/src/apis/rushAPI.ts | 5 ++++
admin/src/features/Rush/EventList.tsx | 36 +++++++--------------------
2 files changed, 14 insertions(+), 27 deletions(-)
diff --git a/admin/src/apis/rushAPI.ts b/admin/src/apis/rushAPI.ts
index c10c45f3..e2dc4d28 100644
--- a/admin/src/apis/rushAPI.ts
+++ b/admin/src/apis/rushAPI.ts
@@ -111,6 +111,11 @@ export const RushAPI = {
},
async putRush(body: FormData[]): Promise {
try {
+ body.forEach((b) => {
+ for (let pair of b.entries()) {
+ console.log(pair[0] + ": " + pair[1]);
+ }
+ });
return new Promise((resolve) => resolve([]));
const response = await fetchWithTimeout(`${baseURL}`, {
method: "PUT",
diff --git a/admin/src/features/Rush/EventList.tsx b/admin/src/features/Rush/EventList.tsx
index 4f3affb9..aaea04b5 100644
--- a/admin/src/features/Rush/EventList.tsx
+++ b/admin/src/features/Rush/EventList.tsx
@@ -36,33 +36,15 @@ export default function EventList() {
const getFormData = () => {
return rushList.map((rush) => {
const formData = new FormData();
-
- formData.append("rushEventId", rush.rushEventId.toString());
- formData.append("eventDate", rush.eventDate);
- formData.append("openTime", rush.openTime);
- formData.append("closeTime", rush.closeTime);
- formData.append("winnerCount", rush.winnerCount.toString());
- formData.append("prizeDescription", rush.prizeDescription);
- formData.append("status", rush.status);
-
- formData.append("prizeImageUrl", rush.prizeImageUrl);
-
- formData.append("leftOption[rushOptionId]", rush.leftOption.rushOptionId.toString());
- formData.append("leftOption[mainText]", rush.leftOption.mainText);
- formData.append("leftOption[subText]", rush.leftOption.subText);
- formData.append("leftOption[resultMainText]", rush.leftOption.resultMainText);
- formData.append("leftOption[resultSubText]", rush.leftOption.resultSubText);
-
- formData.append("leftOption[imageUrl]", rush.leftOption.imageUrl);
-
- formData.append("rightOption[rushOptionId]", rush.rightOption.rushOptionId.toString());
- formData.append("rightOption[mainText]", rush.rightOption.mainText);
- formData.append("rightOption[subText]", rush.rightOption.subText);
- formData.append("rightOption[resultMainText]", rush.rightOption.resultMainText);
- formData.append("rightOption[resultSubText]", rush.rightOption.resultSubText);
-
- formData.append("rightOption[imageUrl]", rush.rightOption.imageUrl);
-
+ Object.entries(rush).forEach(([key, value]) => {
+ if (typeof value === "object") {
+ Object.entries(value).forEach(([subKey, subValue]) => {
+ formData.append(`${key}[${subKey}]`, subValue as Blob);
+ });
+ } else {
+ formData.append(key, value.toString());
+ }
+ });
return formData;
});
};