Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix] 어드민 관련 버그 수정 #125

Merged
merged 9 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="소프티어 부트캠프 4기-팀 어썸 오렌지의 IONIQ 5 어드민 페이지입니다." />
<link rel="preload" href="/font/HyundaiSansTextKROTFBold.otf" as="font" type="font/otf" crossorigin="anonymous">
<link rel="preload" href="/font/HyundaiSansTextKROTFMedium.otf" as="font" type="font/otf" crossorigin="anonymous">
<link rel="preload" href="/font/HyundaiSansTextKROTFRegular.otf" as="font" type="font/otf" crossorigin="anonymous">
<title>Awesome Orange - Admin</title>
</head>
<body>
Expand Down
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="HI. Five. The new IONIQ 5. 소프티어 부트캠프 4기-팀 어썸 오렌지의 IONIQ 5 이벤트 페이지입니다." />
<link rel="preload" href="/font/DS-DIGI.TTF" as="font" type="font/ttf" crossorigin="anonymous">
<link rel="preload" href="/font/HyundaiSansTextKROTFBold.otf" as="font" type="font/otf" crossorigin="anonymous">
<link rel="preload" href="/font/HyundaiSansTextKROTFMedium.otf" as="font" type="font/otf" crossorigin="anonymous">
<link rel="preload" href="/font/HyundaiSansTextKROTFRegular.otf" as="font" type="font/otf" crossorigin="anonymous">
<title>Awesome Orange FE</title>
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion src/adminPage/features/eventDetail/EventDetailFetcher.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useQuery } from "@common/dataFetch/getQuery.js";
import { fetchServer } from "@common/dataFetch/fetchServer.js";

function EventDetailFetcher({ eventId }) {
const data = useQuery(`event-detail-${eventId}`, () =>
const data = useQuery(`admin-event-list/${eventId}`, () =>
fetchServer(`/api/v1/admin/events/${eventId}`),
);
return <EventDetail data={data} />;
Expand Down
10 changes: 8 additions & 2 deletions src/adminPage/features/eventEdit/EventBaseDataInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,17 @@ function EventBaseDataInput() {
/>
</label>
<label className="grid grid-cols-[6rem_1fr] items-start gap-2">
<span className="text-center font-bold">이벤트 요약</span>
<span className="text-center font-bold">
이벤트 요약<sup className="text-red-500">*</sup>
</span>
<div className="relative">
<TextBox
className="w-full"
text={description}
setText={(value) => dispatch({ type: "set_description", value })}
rows="4"
maxLength="100"
required
/>
<span
className={`absolute right-3 bottom-3 text-detail-l ${description.length >= DESCRIPTION_MAX_LENGTH ? "text-red-500" : "text-neutral-600"}`}
Expand All @@ -88,13 +91,16 @@ function EventBaseDataInput() {
</div>
</label>
<label className={columnsStyle}>
<span className="text-center font-bold">이벤트 URL</span>
<span className="text-center font-bold">
이벤트 URL<sup className="text-red-500">*</sup>
</span>
<Input
className="w-[25rem] h-8"
text={url}
setText={(value) => dispatch({ type: "set_url", value })}
type="url"
pattern="https?://.*"
required
/>
</label>
</>
Expand Down
2 changes: 1 addition & 1 deletion src/adminPage/features/eventEdit/EventEditFetcher.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useQuery } from "@common/dataFetch/getQuery.js";
import { fetchServer } from "@common/dataFetch/fetchServer.js";

function EventEditFetcher({ eventId }) {
const data = useQuery(`event-detail-${eventId}`, () =>
const data = useQuery(`admin-event-list/${eventId}`, () =>
fetchServer(`/api/v1/admin/events/${eventId}`),
);
return <EventEditor initialData={data} />;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class DrawGradeData {
constructor(rawData) {
if (rawData == null) this.data = [{ grade: 1, count: 0, prizeInfo: "" }];
if (rawData == null) this.data = [];
else this.data = [...rawData].sort((a, b) => a.grade - b.grade);
}
get size() {
Expand Down
9 changes: 8 additions & 1 deletion src/adminPage/features/eventEdit/businessLogic/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ function makeVoidDrawData() {
};
}

function makeDefaultDrawData() {
return {
metadata: new DrawGradeData([{ grade: 1, count: 0, prizeInfo: "" }]),
policies: new DrawPolicyData(),
};
}

function makeDrawData(rawData) {
return {
id: rawData.id,
Expand Down Expand Up @@ -80,7 +87,7 @@ export function eventEditReducer(state, action) {
return { ...state, url: action.value };
case "set_event_type":
if (action.value === "draw") {
return { ...state, eventType: "draw", fcfs: new FcfsData() };
return { ...state, eventType: "draw", draw: makeDefaultDrawData(), fcfs: new FcfsData() };
}
return { ...state, eventType: "fcfs", draw: makeVoidDrawData() };
case "set_event_frame":
Expand Down
76 changes: 58 additions & 18 deletions src/adminPage/features/eventEdit/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,76 @@ import AlertModal from "@admin/modals/AlertModal.jsx";
import ConfirmModal from "@admin/modals/ConfirmModal.jsx";

import { useMutation } from "@common/dataFetch/getQuery.js";
import { fetchServer, handleError } from "@common/dataFetch/fetchServer.js";

const submitErrorHandler = {
400: "잘못된 입력으로 이벤트 등록에 실패했습니다.",
401: "인증되지 않은 사용자입니다.",
};

const tempSubmitErrorHandler = {
400: "잘못된 입력으로 임시저장에 실패했습니다.",
401: "인증되지 않은 사용자입니다.",
};
import { fetchServer, handleError, HTTPError } from "@common/dataFetch/fetchServer.js";

const tempLoadErrorHandler = {
401: "인증되지 않은 사용자입니다.",
404: "임시저장된 데이터가 없습니다.",
};

function handleEventSubmitError(e) {
if (e instanceof HTTPError) {
if (e.status === 400) {
e.response.json().then((value) => {
console.log(value);
openModal(
<AlertModal
title="등록 실패"
description={
<>
사용자 입력이 잘못되었습니다.
<br />
<span className="whitespace-pre-wrap">{JSON.stringify(value, null, 2)}</span>
</>
}
/>,
);
});
} else if (e.status === 401) {
openModal(<AlertModal title="등록 실패" description="인증되지 않은 사용자입니다." />);
} else if (e.status < 500) {
openModal(
<AlertModal
title="등록 실패"
description={
<>
클라이언트의 오류가 발생했습니다.
<br />
에러 코드 : {e.status}
</>
}
/>,
);
} else {
openModal(
<AlertModal
title="등록 실패"
description={
<>
서버의 오류가 발생했습니다.
<br />
에러 코드 : {e.status}
</>
}
/>,
);
}
} else {
openModal(<AlertModal title="오류라니!" description="알 수 없는 오류가 발생했습니다." />);
}
}

function EventEditor({ initialData = null } = {}) {
const navigate = useNavigate();
const mode = useContext(EventEditModeContext);
const [state, dispatch] = useReducer(eventEditReducer, initialData, setDefaultState);
const submitMutate = useMutation(
mode === "create" ? "event-detail-created" : `event-detail-${state.eventId}`,
mode === "create" ? "admin-event-list" : `admin-event-list/${state.eventId}`,
() =>
fetchServer(mode === "create" ? "/api/v1/admin/events" : "/api/v1/admin/events/edit", {
method: "post",
body: state,
}).catch(handleError(submitErrorHandler)),
}),
{
onSuccess: () => {
openModal(
Expand All @@ -53,9 +95,7 @@ function EventEditor({ initialData = null } = {}) {
/>,
).then(() => navigate(mode === "create" ? "/events" : `/events/${state.eventId}`));
},
onError: (e) => {
openModal(<AlertModal title="등록 실패" description={e.message} />);
},
onError: handleEventSubmitError,
},
);

Expand All @@ -74,10 +114,10 @@ function EventEditor({ initialData = null } = {}) {
await fetchServer("/api/v1/admin/events/temp", {
method: "post",
body: state,
}).catch(handleError(tempSubmitErrorHandler));
});
openModal(<AlertModal title="완료" description="작성 중인 내용이 임시저장되었습니다." />);
} catch (e) {
openModal(<AlertModal title="저장 실패" description={e.message} />);
handleEventSubmitError(e);
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/adminPage/features/eventEdit/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ const dummyData = getEventsDetailMock();
let tempData = null;

const handlers = [
http.post("/api/v1/admin/events", () => {
http.post("/api/v1/admin/events", async ({ request }) => {
const data = await request.json();
if (data.description === "")
return HttpResponse.json({ description: "디스크립션이 없습니다." }, { status: 400 });
tempData = null;
return new HttpResponse(null, { status: 201 });
}),
Expand Down
6 changes: 3 additions & 3 deletions src/adminPage/features/eventList/Filter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ function Filter({ state, dispatch }) {
const labelStyle = "inline-flex items-center gap-1 text-body-s";

return (
<div className="grid grid-cols-2 gap-4">
<fieldset className={fieldsetStyle}>
<div className="grid grid-cols-1 gap-4">
{/* <fieldset className={fieldsetStyle}>
<legend className="px-2 text-body-l font-medium">상태</legend>
<div className="flex flex-wrap gap-2 px-2">
<label className={labelStyle}>
Expand All @@ -34,7 +34,7 @@ function Filter({ state, dispatch }) {
임시저장
</label>
</div>
</fieldset>
</fieldset>*/}
<fieldset className={fieldsetStyle}>
<legend className="px-2 text-body-l font-medium">종류</legend>
<div className="flex flex-wrap gap-2 px-2">
Expand Down
4 changes: 2 additions & 2 deletions src/adminPage/features/eventList/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const handlers = [
http.get("/api/v1/admin/events", async ({ request }) => {
const url = new URL(request.url);
const search = url.searchParams.get("search");
const filter = url.searchParams.get("filter");
const filter = url.searchParams.get("type");
const sort = url.searchParams.get("sort");
const page = +url.searchParams.get("page") ?? 1;
const size = +url.searchParams.get("size") ?? 5;
Expand All @@ -82,7 +82,7 @@ const handlers = [
.filter(filterData(filter))
.sort(sortData(sort));

const contents = filteredData.slice((page - 1) * size, page * size);
const contents = filteredData.slice(page * size, (page + 1) * size);

return HttpResponse.json({
contents,
Expand Down
2 changes: 1 addition & 1 deletion src/adminPage/features/eventList/queryReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function searchStateToQuery(state) {
const path = "/api/v1/admin/events";
const paramObj = {
search: state.query,
filter: Object.entries(state.filter)
type: Object.entries(state.filter)
.filter(([, value]) => value)
.map(([key]) => key)
.join(","),
Expand Down
2 changes: 1 addition & 1 deletion src/adminPage/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

@layer base {
body {
font-family: "hdsans";
font-family: "hdsans", sans-serif;
}
body.scrollLocked {
position: fixed;
Expand Down
4 changes: 1 addition & 3 deletions src/adminPage/shared/auth/LoginSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,9 @@ function LoginSection() {
text={password}
setText={setPassword}
type="password"
placeholder="비밀번호 입력하세요."
placeholder="비밀번호를 입력하세요."
required
minLength="8"
maxLength="16"
pattern="^(?=.*[a-zA-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,16}$"
/>
</label>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/common/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const EVENT_FCFS_ID = "HD_240808_001";
export const EVENT_DRAW_ID = "HD-19700101-01";
export const EVENT_FCFS_ID = "HD_240808_002";
export const EVENT_DRAW_ID = "HD_240808_001";
export const EVENT_ID = "the-new-ioniq5";
export const EVENT_START_DATE = new Date(2024, 8, 9);

Expand Down
6 changes: 5 additions & 1 deletion src/common/dataFetch/getQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ function updateSubscribedQuery(key) {
queryGroupMap.get(key).forEach((subKey) => queryMap.delete(subKey));
queryGroupMap.deleteKey(key);
}

if (queryObservers.has(key)) queryObservers.get(key).forEach((callback) => callback());

if (key.includes("/")) {
const parent = /^(.*?)(?=\/[^/]+$)/.exec(key)[1];
updateSubscribedQuery(parent);
}
}

function isSame(arr1, arr2) {
Expand Down
2 changes: 1 addition & 1 deletion src/mainPage/features/fcfs/cardGame/CardGame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function CardGame({ offline }) {
{[1, 2, 3, 4].map((index, i) => (
<Card
index={index}
isFlipped={flipState[i]}
isFlipped={isParticipated || flipState[i]}
setFlipped={(flipState) =>
setFlipState((state) => {
const newState = [...state];
Expand Down
2 changes: 1 addition & 1 deletion src/mainPage/features/fcfs/cardGame/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function CardGamePariticipatedInitializer() {

function CardGameSection() {
return (
<ErrorBoundary fallback={<CardGame offline />}>
<ErrorBoundary fallback={<div>에러남</div>}>
<Suspense fallback={<CardGameSkeleton />}>
<CardGameInitializer />
<CardGamePariticipatedInitializer />
Expand Down
2 changes: 1 addition & 1 deletion src/mainPage/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

@layer base {
body {
font-family: "hdsans";
font-family: "hdsans", sans-serif;
}
body.scrollLocked {
position: fixed;
Expand Down
22 changes: 14 additions & 8 deletions src/mainPage/shared/drawEvent/store.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { create } from "zustand";
import { fetchServer } from "@common/dataFetch/fetchServer.js";
import { fetchServer, handleError } from "@common/dataFetch/fetchServer.js";
import { getQuery, getQuerySuspense } from "@common/dataFetch/getQuery.js";
import { getServerPresiseTime, getDayDifference } from "@common/utils.js";
import { EVENT_DRAW_ID, EVENT_START_DATE, DAY_MILLISEC } from "@common/constants.js";

function getJoinDataEvent() {
return fetchServer(`/api/v1/event/draw/${EVENT_DRAW_ID}/participation`).then(({ dates }) => {
let newJoinedList = [false, false, false, false, false];
dates.forEach((date) => {
const day = getDayDifference(EVENT_START_DATE, new Date(date));
newJoinedList[day] = true;
return fetchServer(`/api/v1/event/draw/${EVENT_DRAW_ID}/participation`)
.then(({ dates }) => {
let newJoinedList = [false, false, false, false, false];
dates.forEach((date) => {
const day = getDayDifference(EVENT_START_DATE, new Date(date));
newJoinedList[day] = true;
});
return newJoinedList;
})
.catch(handleError({ 401: "unauthorized" }))
.catch((e) => {
if (e.message === "unauthorized") return [false, false, false, false, false];
throw e;
});
return newJoinedList;
});
}

const drawEventStore = create((set, get) => ({
Expand Down
5 changes: 2 additions & 3 deletions src/mainPage/shared/realtimeEvent/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ async function getFcfsParticipated() {
const eventData = await fetchServer(`/api/v1/event/fcfs/${EVENT_FCFS_ID}/participated`); // ???
return eventData;
} catch (e) {
if (e instanceof HTTPError && (e.status === 401 || e.status == 404))
return { answerResult: false, winner: false };
if (e instanceof ServerCloseError) return { answerResult: false, winner: false };
if (e instanceof HTTPError && (e.status === 401 || e.status == 404)) return false;
if (e instanceof ServerCloseError) return false;
throw e;
}
}
Expand Down
Loading