From 11e99735904487baf6b4832bff2a69c44dc93521 Mon Sep 17 00:00:00 2001 From: lybell-art <futireflugel@gmail.com> Date: Fri, 23 Aug 2024 11:56:54 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[fix]=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=98=A4=EB=A5=98=20=EC=8B=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=AA=A8=EB=8B=AC=EC=9D=84=20=EB=9D=84=EC=9A=B0?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/adminPage/build.js | 2 +- .../src/features/eventList/DeleteButton.jsx | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/adminPage/build.js b/packages/adminPage/build.js index 806d1130..ba07dbb8 100644 --- a/packages/adminPage/build.js +++ b/packages/adminPage/build.js @@ -17,7 +17,7 @@ const buildUrl = [ "events/[id]", "comments", "comments/[id]", - "users" + "users", ]; async function copyFolder(src, dest) { diff --git a/packages/adminPage/src/features/eventList/DeleteButton.jsx b/packages/adminPage/src/features/eventList/DeleteButton.jsx index 7b4fca1a..8c35224c 100644 --- a/packages/adminPage/src/features/eventList/DeleteButton.jsx +++ b/packages/adminPage/src/features/eventList/DeleteButton.jsx @@ -1,4 +1,4 @@ -import { fetchServer } from "@common/dataFetch/fetchServer.js"; +import { fetchServer, HTTPError } from "@common/dataFetch/fetchServer.js"; import { useMutation } from "@common/dataFetch/getQuery.js"; import ConfirmModal from "@admin/modals/ConfirmModal.jsx"; import AlertModal from "@admin/modals/AlertModal.jsx"; @@ -17,9 +17,23 @@ function DeleteButton({ selected, reset }) { }), { onSuccess: () => { - openModal(<AlertModal title="삭제" description="기대평이 삭제되었습니다." />); + openModal(<AlertModal title="삭제" description="이벤트가 삭제되었습니다." />); reset(); }, + onError: async (e) => { + if (e instanceof HTTPError && e.status === 400) { + return openModal( + <AlertModal + title="오류" + description="진행 중이거나 삭제된 이벤트는 삭제가 불가능합니다." + />, + ); + } + if (e instanceof HTTPError && e.status === 404) { + return openModal(<AlertModal title="오류" description="존재하지 않는 이벤트입니다." />); + } + return openModal(<AlertModal title="오류" description="이벤트를 삭제할 수 없습니다." />); + }, }, ); const deleteConfirmModal = ( From 4556958d689440ab3449321e019feec43db5ad02 Mon Sep 17 00:00:00 2001 From: lybell-art <futireflugel@gmail.com> Date: Fri, 23 Aug 2024 12:21:46 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[fix]=20=EC=A7=84=ED=96=89=20=EC=A4=91?= =?UTF-8?q?=EC=9D=B4=EA=B1=B0=EB=82=98=20=EC=A2=85=EB=A3=8C=EB=90=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A5=BC=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B6=88=EA=B0=80=EB=8A=A5=ED=95=98=EA=B2=8C=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 --- packages/adminPage/src/features/eventList/mock.js | 9 +++++++++ .../src/features/eventList/table/SearchResultItem.jsx | 8 +++++--- .../adminPage/src/features/eventList/table/index.jsx | 7 ++++++- packages/adminPage/src/shared/serverTime/EventStatus.js | 7 ++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/adminPage/src/features/eventList/mock.js b/packages/adminPage/src/features/eventList/mock.js index e51ba264..caecd856 100644 --- a/packages/adminPage/src/features/eventList/mock.js +++ b/packages/adminPage/src/features/eventList/mock.js @@ -91,6 +91,15 @@ const handlers = [ size, }); }), + http.delete("/api/v1/admin/events/:id", async ({ params }) => { + const { id } = params; + + const index = dummyData.findIndex(({ eventId }) => eventId === id); + if (index === -1) return HttpResponse.json(false); + dummyData.splice(index, 1); + + return HttpResponse.json(true); + }), http.delete("/api/v1/admin/events", async ({ request }) => { const { eventIds } = await request.json(); diff --git a/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx b/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx index 0e39e7e3..044e6f59 100644 --- a/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx +++ b/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx @@ -1,16 +1,18 @@ import { Link } from "react-router-dom"; import tableTemplateCol from "./tableStyle.js"; -import EventStatus from "@admin/serverTime/EventStatus.js"; +import { useEventStatus } from "@admin/serverTime/EventStatus.js"; import Button from "@common/components/Button.jsx"; import Checkbox from "@common/components/Checkbox.jsx"; import { formatDate } from "@common/utils.js"; function SearchResultItem({ eventId, name, startTime, endTime, eventType, checked, setCheck }) { + const eventStatus = useEventStatus(startTime, endTime); + return ( <label className={`${tableTemplateCol} h-8 text-body-s bg-white hover:bg-blue-100`}> <div className="flex justify-center items-center"> - <Checkbox checked={checked} onChange={setCheck} /> + <Checkbox checked={checked} onChange={setCheck} disabled={eventStatus !== "예정"} /> </div> <div className="flex justify-center items-center font-medium">{eventId}</div> <div className="flex justify-center items-center overflow-hidden"> @@ -28,7 +30,7 @@ function SearchResultItem({ eventId, name, startTime, endTime, eventType, checke {eventType === "fcfs" ? "선착순" : eventType === "draw" ? "추첨" : "???"} </div> <div className="flex justify-center items-center"> - <EventStatus startTime={startTime} endTime={endTime} /> + {eventStatus} </div> <div className="flex justify-center items-center"> <Link to={`./${eventId}`}> diff --git a/packages/adminPage/src/features/eventList/table/index.jsx b/packages/adminPage/src/features/eventList/table/index.jsx index a02bcc95..01904a6e 100644 --- a/packages/adminPage/src/features/eventList/table/index.jsx +++ b/packages/adminPage/src/features/eventList/table/index.jsx @@ -4,6 +4,7 @@ import Pagination from "@admin/components/Pagination.jsx"; import { useQuery } from "@common/dataFetch/getQuery.js"; import { fetchServer } from "@common/dataFetch/fetchServer.js"; +import serverTimeStore from "@admin/serverTime/store.js"; function SearchResult({ query, queryState, queryDispatch, checkState, checkDispatch }) { const { contents, totalPages } = useQuery(`admin-event-list@${query}`, () => fetchServer(query), { @@ -11,7 +12,11 @@ function SearchResult({ query, queryState, queryDispatch, checkState, checkDispa }); const checkSelect = () => { - const keys = contents.map(({ eventId }) => eventId); + const keys = contents + .filter(({ startTime }) => { + return new Date(startTime) > serverTimeStore.getState().serverTime; + }) + .map(({ eventId }) => eventId); checkDispatch({ type: "toggle_keys", keys }); }; diff --git a/packages/adminPage/src/shared/serverTime/EventStatus.js b/packages/adminPage/src/shared/serverTime/EventStatus.js index 4cc900a8..284ea34f 100644 --- a/packages/adminPage/src/shared/serverTime/EventStatus.js +++ b/packages/adminPage/src/shared/serverTime/EventStatus.js @@ -1,6 +1,6 @@ import useServerTime from "./store.js"; -function EventStatus({ startTime: _startTime, endTime: _endTime }) { +export function useEventStatus(_startTime, _endTime) { const serverTime = useServerTime((store) => store.serverTime); const startTime = _startTime instanceof Date ? _startTime : new Date(_startTime); const endTime = _endTime instanceof Date ? _endTime : new Date(_endTime); @@ -10,4 +10,9 @@ function EventStatus({ startTime: _startTime, endTime: _endTime }) { return "종료"; } +function EventStatus({ startTime: _startTime, endTime: _endTime }) { + const status = useEventStatus(_startTime, _endTime); + return status; +} + export default EventStatus; From 2b96245c323e8922ca7a42f74e1b4489b1c72197 Mon Sep 17 00:00:00 2001 From: lybell-art <futireflugel@gmail.com> Date: Fri, 23 Aug 2024 12:36:09 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[fix]=20=EB=8D=B0=EB=B8=8C=EC=84=9C?= =?UTF-8?q?=EB=B2=84=EC=97=90=EC=84=9C=20=EC=9D=BC=EB=B6=80=20=ED=8F=B0?= =?UTF-8?q?=ED=8A=B8=EA=B0=80=20=EC=95=88=EB=9C=A8=EB=8A=94=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/sharedAssetRouter.js | 6 ++++-- packages/common/src/components/Checkbox.jsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/common/sharedAssetRouter.js b/packages/common/sharedAssetRouter.js index 042a4ebc..ac5815c3 100644 --- a/packages/common/sharedAssetRouter.js +++ b/packages/common/sharedAssetRouter.js @@ -1,6 +1,6 @@ import { fileURLToPath } from "node:url"; import { join } from "node:path"; -import { createReadStream } from "node:fs"; +import { createReadStream, existsSync } from "node:fs"; import { lookup } from "mime-types"; const __dirname = fileURLToPath(new URL("../../", import.meta.url)); @@ -24,11 +24,13 @@ export default function sharedAssetRouter(paths) { if (originPath === null) return next(); const filePath = join(__dirname, originPath); + if(!existsSync(filePath)) return next(); + const stream = createReadStream(filePath); stream.on("error", (err) => { if (err.code === "ENOENT") { res.statusCode = 404; - res.end("File not found"); + res.end("Send Fallback"); } else { res.statusCode = 500; res.end("Server error"); diff --git a/packages/common/src/components/Checkbox.jsx b/packages/common/src/components/Checkbox.jsx index d29c2e16..bbd8ef7b 100644 --- a/packages/common/src/components/Checkbox.jsx +++ b/packages/common/src/components/Checkbox.jsx @@ -1,7 +1,7 @@ function Checkbox({ className, checked, onChange: userOnChange, defaultChecked, ...otherProps }) { const checkboxStyle = `${className} size-4 appearance-none border border-neutral-300 checked:bg-blue-400 checked:border-0 - checked:bg-checked bg-center bg-cover`; + checked:bg-checked bg-center bg-cover disabled:bg-neutral-100`; function onChange({ target }) { userOnChange(target.checked); From 4ec5078d4a66cda05e8ea04191e29a3a55c33c59 Mon Sep 17 00:00:00 2001 From: lybell-art <futireflugel@gmail.com> Date: Fri, 23 Aug 2024 13:42:54 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[modify]=20=EC=8A=A4=EC=99=80=EC=9D=B4?= =?UTF-8?q?=ED=8D=BC=20=EC=9E=90=EC=B2=B4=EC=97=90=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=A1=9C=EB=94=A9=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/src/constants.js | 2 +- .../mainPage/src/features/detailInformation/DetailSwiper.jsx | 2 +- packages/mainPage/src/features/interactions/index.jsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/common/src/constants.js b/packages/common/src/constants.js index a060a0fc..de80503c 100644 --- a/packages/common/src/constants.js +++ b/packages/common/src/constants.js @@ -1,7 +1,7 @@ export const EVENT_FCFS_ID = "HD_240821_001"; export const EVENT_DRAW_ID = "HD_240808_001"; export const EVENT_ID = "the-new-ioniq5"; -export const EVENT_START_DATE = new Date(2024, 7, 20); +export const EVENT_START_DATE = new Date(2024, 7, 19); export const SERVICE_TOKEN_ID = "AWESOME_ORANGE_ACCESS_TOKEN"; export const ADMIN_TOKEN_ID = "AWESOME_ORANGE_ADMIN_ACCESS_TOKEN"; diff --git a/packages/mainPage/src/features/detailInformation/DetailSwiper.jsx b/packages/mainPage/src/features/detailInformation/DetailSwiper.jsx index 081cb440..5279e344 100644 --- a/packages/mainPage/src/features/detailInformation/DetailSwiper.jsx +++ b/packages/mainPage/src/features/detailInformation/DetailSwiper.jsx @@ -25,7 +25,7 @@ function DetailSwiper({ content }) { ref={swiperElRef} > {content.map((item) => ( - <swiper-slide class={slideClass} key={item.title}> + <swiper-slide class={slideClass} key={item.title} lazy="true"> <DetailItem {...item} /> </swiper-slide> ))} diff --git a/packages/mainPage/src/features/interactions/index.jsx b/packages/mainPage/src/features/interactions/index.jsx index a9960e64..a1c1dadc 100644 --- a/packages/mainPage/src/features/interactions/index.jsx +++ b/packages/mainPage/src/features/interactions/index.jsx @@ -34,7 +34,7 @@ export default function InteractionPage() { ref={swiperRef} > {JSONData.interaction.map((interactionDesc, index) => ( - <swiper-slide key={index} class="w-5/6 sm:w-[566px] h-[456px]"> + <swiper-slide key={index} class="w-5/6 sm:w-[566px] h-[456px]" lazy="true"> <InteractionSlide interactionDesc={interactionDesc} index={index} From ef64cfcb7de6a7009e72a35386b4b777e60c6408 Mon Sep 17 00:00:00 2001 From: lybell-art <futireflugel@gmail.com> Date: Fri, 23 Aug 2024 17:12:05 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[feat]=20=EC=88=8F=20=ED=92=80=EB=A7=81?= =?UTF-8?q?=EC=9D=84=20=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=B6=94?= =?UTF-8?q?=EC=B2=A8=20=EB=B2=84=ED=8A=BC=20=EB=B0=8F=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eventDetail/drawButton/DrawButton.jsx | 122 ++++++++++++------ .../features/eventDetail/drawButton/mock.js | 6 + 2 files changed, 86 insertions(+), 42 deletions(-) diff --git a/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx b/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx index bb11692e..e6a9c358 100644 --- a/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx +++ b/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx @@ -1,9 +1,9 @@ +import { useState, useEffect, useRef } from "react"; import { useParams } from "react-router-dom"; import { fetchServer } from "@common/dataFetch/fetchServer.js"; -import { useQuery, useMutation } from "@common/dataFetch/getQuery.js"; + import Button from "@common/components/Button.jsx"; import openModal from "@common/modal/openModal.js"; - import AlertModal from "@admin/modals/AlertModal.jsx"; import DrawResultModal from "./DrawResultModal.jsx"; @@ -12,55 +12,93 @@ import Suspense from "@common/components/Suspense.jsx"; import Spinner from "@common/components/Spinner.jsx"; import DelaySkeleton from "@common/components/DelaySkeleton.jsx"; +function ResultModalContainer({eventId}) +{ + return <div className="w-[calc(100vw-8rem)] h-[calc(100vh-8rem)] p-8 bg-white relative"> + <ErrorBoundary fallback={<div>에러남</div>}> + <Suspense + fallback={ + <div className="w-full h-full flex justify-center items-center"> + <DelaySkeleton> + <Spinner /> + </DelaySkeleton> + </div> + } + > + <DrawResultModal eventId={eventId} /> + </Suspense> + </ErrorBoundary> + </div> +} + function DrawButton() { const { eventId } = useParams(); - const drawResultData = useQuery( - `event-detail-draw-result-${eventId}`, - () => { - return fetchServer(`/api/v1/admin/draw/${eventId}/winners`); - }, - { deferred: true }, - ); + const [drawState, setDrawState] = useState("BEFORE_END"); + const interval = useRef(null); + const timeout = useRef(null); - const resultModal = ( - <div className="w-[calc(100vw-8rem)] h-[calc(100vh-8rem)] p-8 bg-white relative"> - <ErrorBoundary fallback={<div>에러남</div>}> - <Suspense - fallback={ - <div className="w-full h-full flex justify-center items-center"> - <DelaySkeleton> - <Spinner /> - </DelaySkeleton> - </div> - } - > - <DrawResultModal eventId={eventId} /> - </Suspense> - </ErrorBoundary> - </div> - ); + useEffect( ()=>{ + fetchServer(`/api/v1/admin/draw/${eventId}/status`) + .then( ({status})=>setDrawState(status) ) + .catch( (e)=>{ + setDrawState("ERROR"); + } ); + }, [] ); - const mutate = useMutation( - `event-detail-draw-result-${eventId}`, - () => fetchServer(`/api/v1/admin/draw/${eventId}/draw`, { method: "post" }), + useEffect( ()=>{ + return ()=>{ + clearInterval(interval.current); + clearTimeout(timeout.current); + } + }, [] ); + + async function onSubmit() + { + function shortPooling() { - onSuccess: () => openModal(resultModal), - onFail: () => - openModal(<AlertModal title="오류" description="추첨에 오류가 발생했습니다." />), - }, - ); + fetchServer(`/api/v1/admin/draw/${eventId}/status`) + .then( ({status})=>{ + setDrawState(status); + if(status !== "IS_DRAWING") { + clearInterval(interval.current); + } + } ) + .catch( (e)=>{ + setDrawState("ERROR"); + clearInterval(interval.current); + } ); + } + + try { + await fetchServer(`/api/v1/admin/draw/${eventId}/draw`, { method: "post" }); + setDrawState("IS_DRAWING"); + openModal(<AlertModal title="성공" description="성공적으로 추첨 요청이 전송되었습니다." />); + timeout.current = setTimeout( ()=>{ + shortPooling(); + interval.current = setInterval( shortPooling, 5000 ); + }, 500 ); + } + catch { + openModal(<AlertModal title="오류" description="추첨에 오류가 발생했습니다." />); + } + } - if (drawResultData.length === 0) - return ( - <Button className="w-32 h-8 px-4 py-1" onClick={mutate}> + switch(drawState) + { + case "BEFORE_END": return null; + case "AVAILABLE": return ( + <Button className="w-32 h-8 px-4 py-1" onClick={onSubmit}> 추첨하기 </Button> ); - return ( - <Button className="w-32 h-8 px-4 py-1" onClick={() => openModal(resultModal)}> - 결과 보기 - </Button> - ); + case "IS_DRAWING": return <div className="w-32 h-8 px-4 py-1 bg-neutral-600 text-neutral-400">추첨 진행중...</div>; + case "COMPLETE": return ( + <Button className="w-32 h-8 px-4 py-1" onClick={() => openModal(<ResultModalContainer eventId={eventId} />)}> + 결과 보기 + </Button> + ); + default: return <div className="w-32 h-8 px-4 py-1 bg-neutral-600 text-neutral-400">에러</div>; + } } export default DrawButton; diff --git a/packages/adminPage/src/features/eventDetail/drawButton/mock.js b/packages/adminPage/src/features/eventDetail/drawButton/mock.js index 7051ea75..b322b862 100644 --- a/packages/adminPage/src/features/eventDetail/drawButton/mock.js +++ b/packages/adminPage/src/features/eventDetail/drawButton/mock.js @@ -2,6 +2,7 @@ import { http, HttpResponse } from "msw"; import getRandomString from "@common/mock/getRandomString.js"; let result = []; +let status = "AVAILABLE"; function makeDrawComplete() { const newResult = []; @@ -24,11 +25,16 @@ function makeDrawComplete() { const handlers = [ http.post("/api/v1/admin/draw/:eventId/draw", () => { result = makeDrawComplete(); + status = "IS_DRAWING"; + setTimeout( ()=>status = "COMPLETE", 3000 ); return new HttpResponse(null, { status: 201 }); }), http.get("/api/v1/admin/draw/:eventId/winners", () => { return HttpResponse.json(result); }), + http.get("/api/v1/admin/draw/:eventId/status", () => { + return HttpResponse.json({status}); + }), ]; export default handlers; From a74a92fbc4da5422d8b41917da0bf81a5e2ccb70 Mon Sep 17 00:00:00 2001 From: lybell-art <futireflugel@gmail.com> Date: Fri, 23 Aug 2024 17:15:54 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[chore]=20=EB=A6=B0=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=ED=94=84=EB=A6=AC=ED=8B=B0=EC=96=B4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eventDetail/drawButton/DrawButton.jsx | 119 +++++++++--------- .../features/eventDetail/drawButton/mock.js | 4 +- .../eventList/table/SearchResultItem.jsx | 4 +- packages/common/sharedAssetRouter.js | 2 +- 4 files changed, 67 insertions(+), 62 deletions(-) diff --git a/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx b/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx index e6a9c358..90061937 100644 --- a/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx +++ b/packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect, useRef } from "react"; import { useParams } from "react-router-dom"; import { fetchServer } from "@common/dataFetch/fetchServer.js"; @@ -12,23 +12,24 @@ import Suspense from "@common/components/Suspense.jsx"; import Spinner from "@common/components/Spinner.jsx"; import DelaySkeleton from "@common/components/DelaySkeleton.jsx"; -function ResultModalContainer({eventId}) -{ - return <div className="w-[calc(100vw-8rem)] h-[calc(100vh-8rem)] p-8 bg-white relative"> - <ErrorBoundary fallback={<div>에러남</div>}> - <Suspense - fallback={ - <div className="w-full h-full flex justify-center items-center"> - <DelaySkeleton> - <Spinner /> - </DelaySkeleton> - </div> - } - > - <DrawResultModal eventId={eventId} /> - </Suspense> - </ErrorBoundary> - </div> +function ResultModalContainer({ eventId }) { + return ( + <div className="w-[calc(100vw-8rem)] h-[calc(100vh-8rem)] p-8 bg-white relative"> + <ErrorBoundary fallback={<div>에러남</div>}> + <Suspense + fallback={ + <div className="w-full h-full flex justify-center items-center"> + <DelaySkeleton> + <Spinner /> + </DelaySkeleton> + </div> + } + > + <DrawResultModal eventId={eventId} /> + </Suspense> + </ErrorBoundary> + </div> + ); } function DrawButton() { @@ -37,67 +38,73 @@ function DrawButton() { const interval = useRef(null); const timeout = useRef(null); - useEffect( ()=>{ + useEffect(() => { fetchServer(`/api/v1/admin/draw/${eventId}/status`) - .then( ({status})=>setDrawState(status) ) - .catch( (e)=>{ + .then(({ status }) => setDrawState(status)) + .catch(() => { setDrawState("ERROR"); - } ); - }, [] ); + }); + }, [eventId]); - useEffect( ()=>{ - return ()=>{ + useEffect(() => { + return () => { clearInterval(interval.current); clearTimeout(timeout.current); - } - }, [] ); + }; + }, []); - async function onSubmit() - { - function shortPooling() - { + async function onSubmit() { + function shortPooling() { fetchServer(`/api/v1/admin/draw/${eventId}/status`) - .then( ({status})=>{ + .then(({ status }) => { setDrawState(status); - if(status !== "IS_DRAWING") { + if (status !== "IS_DRAWING") { clearInterval(interval.current); } - } ) - .catch( (e)=>{ + }) + .catch(() => { setDrawState("ERROR"); clearInterval(interval.current); - } ); + }); } try { await fetchServer(`/api/v1/admin/draw/${eventId}/draw`, { method: "post" }); setDrawState("IS_DRAWING"); openModal(<AlertModal title="성공" description="성공적으로 추첨 요청이 전송되었습니다." />); - timeout.current = setTimeout( ()=>{ + timeout.current = setTimeout(() => { shortPooling(); - interval.current = setInterval( shortPooling, 5000 ); - }, 500 ); - } - catch { + interval.current = setInterval(shortPooling, 5000); + }, 500); + } catch { openModal(<AlertModal title="오류" description="추첨에 오류가 발생했습니다." />); } } - switch(drawState) - { - case "BEFORE_END": return null; - case "AVAILABLE": return ( - <Button className="w-32 h-8 px-4 py-1" onClick={onSubmit}> - 추첨하기 - </Button> - ); - case "IS_DRAWING": return <div className="w-32 h-8 px-4 py-1 bg-neutral-600 text-neutral-400">추첨 진행중...</div>; - case "COMPLETE": return ( - <Button className="w-32 h-8 px-4 py-1" onClick={() => openModal(<ResultModalContainer eventId={eventId} />)}> - 결과 보기 - </Button> - ); - default: return <div className="w-32 h-8 px-4 py-1 bg-neutral-600 text-neutral-400">에러</div>; + switch (drawState) { + case "BEFORE_END": + return null; + case "AVAILABLE": + return ( + <Button className="w-32 h-8 px-4 py-1" onClick={onSubmit}> + 추첨하기 + </Button> + ); + case "IS_DRAWING": + return ( + <div className="w-32 h-8 px-4 py-1 bg-neutral-600 text-neutral-400">추첨 진행중...</div> + ); + case "COMPLETE": + return ( + <Button + className="w-32 h-8 px-4 py-1" + onClick={() => openModal(<ResultModalContainer eventId={eventId} />)} + > + 결과 보기 + </Button> + ); + default: + return <div className="w-32 h-8 px-4 py-1 bg-neutral-600 text-neutral-400">에러</div>; } } diff --git a/packages/adminPage/src/features/eventDetail/drawButton/mock.js b/packages/adminPage/src/features/eventDetail/drawButton/mock.js index b322b862..6b12b6a2 100644 --- a/packages/adminPage/src/features/eventDetail/drawButton/mock.js +++ b/packages/adminPage/src/features/eventDetail/drawButton/mock.js @@ -26,14 +26,14 @@ const handlers = [ http.post("/api/v1/admin/draw/:eventId/draw", () => { result = makeDrawComplete(); status = "IS_DRAWING"; - setTimeout( ()=>status = "COMPLETE", 3000 ); + setTimeout(() => (status = "COMPLETE"), 3000); return new HttpResponse(null, { status: 201 }); }), http.get("/api/v1/admin/draw/:eventId/winners", () => { return HttpResponse.json(result); }), http.get("/api/v1/admin/draw/:eventId/status", () => { - return HttpResponse.json({status}); + return HttpResponse.json({ status }); }), ]; diff --git a/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx b/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx index 044e6f59..b5c010b8 100644 --- a/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx +++ b/packages/adminPage/src/features/eventList/table/SearchResultItem.jsx @@ -29,9 +29,7 @@ function SearchResultItem({ eventId, name, startTime, endTime, eventType, checke <div className="flex justify-center items-center"> {eventType === "fcfs" ? "선착순" : eventType === "draw" ? "추첨" : "???"} </div> - <div className="flex justify-center items-center"> - {eventStatus} - </div> + <div className="flex justify-center items-center">{eventStatus}</div> <div className="flex justify-center items-center"> <Link to={`./${eventId}`}> <Button styleType="ghost" className="px-2 py-1 text-body-s"> diff --git a/packages/common/sharedAssetRouter.js b/packages/common/sharedAssetRouter.js index ac5815c3..65b9e6b2 100644 --- a/packages/common/sharedAssetRouter.js +++ b/packages/common/sharedAssetRouter.js @@ -24,7 +24,7 @@ export default function sharedAssetRouter(paths) { if (originPath === null) return next(); const filePath = join(__dirname, originPath); - if(!existsSync(filePath)) return next(); + if (!existsSync(filePath)) return next(); const stream = createReadStream(filePath); stream.on("error", (err) => {