Skip to content

Commit

Permalink
Merge pull request #137 from softeerbootcamp4th/fix/build-error
Browse files Browse the repository at this point in the history
[fix] 어드민 페이지 관련 일부 에러 수정
  • Loading branch information
darkdulgi authored Aug 23, 2024
2 parents 16095fa + a74a92f commit 7f2a9f1
Show file tree
Hide file tree
Showing 13 changed files with 135 additions and 49 deletions.
2 changes: 1 addition & 1 deletion packages/adminPage/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const buildUrl = [
"events/[id]",
"comments",
"comments/[id]",
"users"
"users",
];

async function copyFolder(src, dest) {
Expand Down
111 changes: 78 additions & 33 deletions packages/adminPage/src/features/eventDetail/drawButton/DrawButton.jsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -12,17 +12,8 @@ import Suspense from "@common/components/Suspense.jsx";
import Spinner from "@common/components/Spinner.jsx";
import DelaySkeleton from "@common/components/DelaySkeleton.jsx";

function DrawButton() {
const { eventId } = useParams();
const drawResultData = useQuery(
`event-detail-draw-result-${eventId}`,
() => {
return fetchServer(`/api/v1/admin/draw/${eventId}/winners`);
},
{ deferred: true },
);

const resultModal = (
function ResultModalContainer({ eventId }) {
return (
<div className="w-[calc(100vw-8rem)] h-[calc(100vh-8rem)] p-8 bg-white relative">
<ErrorBoundary fallback={<div>에러남</div>}>
<Suspense
Expand All @@ -39,28 +30,82 @@ function DrawButton() {
</ErrorBoundary>
</div>
);
}

const mutate = useMutation(
`event-detail-draw-result-${eventId}`,
() => fetchServer(`/api/v1/admin/draw/${eventId}/draw`, { method: "post" }),
{
onSuccess: () => openModal(resultModal),
onFail: () =>
openModal(<AlertModal title="오류" description="추첨에 오류가 발생했습니다." />),
},
);
function DrawButton() {
const { eventId } = useParams();
const [drawState, setDrawState] = useState("BEFORE_END");
const interval = useRef(null);
const timeout = useRef(null);

if (drawResultData.length === 0)
return (
<Button className="w-32 h-8 px-4 py-1" onClick={mutate}>
추첨하기
</Button>
);
return (
<Button className="w-32 h-8 px-4 py-1" onClick={() => openModal(resultModal)}>
결과 보기
</Button>
);
useEffect(() => {
fetchServer(`/api/v1/admin/draw/${eventId}/status`)
.then(({ status }) => setDrawState(status))
.catch(() => {
setDrawState("ERROR");
});
}, [eventId]);

useEffect(() => {
return () => {
clearInterval(interval.current);
clearTimeout(timeout.current);
};
}, []);

async function onSubmit() {
function shortPooling() {
fetchServer(`/api/v1/admin/draw/${eventId}/status`)
.then(({ status }) => {
setDrawState(status);
if (status !== "IS_DRAWING") {
clearInterval(interval.current);
}
})
.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(() => {
shortPooling();
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>;
}
}

export default DrawButton;
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand All @@ -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;
18 changes: 16 additions & 2 deletions packages/adminPage/src/features/eventList/DeleteButton.jsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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 = (
Expand Down
9 changes: 9 additions & 0 deletions packages/adminPage/src/features/eventList/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
@@ -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">
Expand All @@ -27,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 startTime={startTime} endTime={endTime} />
</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">
Expand Down
7 changes: 6 additions & 1 deletion packages/adminPage/src/features/eventList/table/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ 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), {
deferred: true,
});

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 });
};

Expand Down
7 changes: 6 additions & 1 deletion packages/adminPage/src/shared/serverTime/EventStatus.js
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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;
6 changes: 4 additions & 2 deletions packages/common/sharedAssetRouter.js
Original file line number Diff line number Diff line change
@@ -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));
Expand All @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/components/Checkbox.jsx
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/constants.js
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
))}
Expand Down
2 changes: 1 addition & 1 deletion packages/mainPage/src/features/interactions/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down

0 comments on commit 7f2a9f1

Please sign in to comment.