diff --git a/admin.html b/admin.html index ea275476..8dd53a8c 100644 --- a/admin.html +++ b/admin.html @@ -5,6 +5,9 @@ + + + Awesome Orange - Admin diff --git a/index.html b/index.html index 947bf910..a9383096 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,10 @@ + + + + Awesome Orange FE diff --git a/src/adminPage/features/eventDetail/EventDetailFetcher.jsx b/src/adminPage/features/eventDetail/EventDetailFetcher.jsx index a15d74d3..f7ddc04f 100644 --- a/src/adminPage/features/eventDetail/EventDetailFetcher.jsx +++ b/src/adminPage/features/eventDetail/EventDetailFetcher.jsx @@ -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 ; diff --git a/src/adminPage/features/eventEdit/EventBaseDataInput.jsx b/src/adminPage/features/eventEdit/EventBaseDataInput.jsx index aa914775..3514d758 100644 --- a/src/adminPage/features/eventEdit/EventBaseDataInput.jsx +++ b/src/adminPage/features/eventEdit/EventBaseDataInput.jsx @@ -71,7 +71,9 @@ function EventBaseDataInput() { /> diff --git a/src/adminPage/features/eventEdit/EventEditFetcher.jsx b/src/adminPage/features/eventEdit/EventEditFetcher.jsx index eb3f27ce..c79efd79 100644 --- a/src/adminPage/features/eventEdit/EventEditFetcher.jsx +++ b/src/adminPage/features/eventEdit/EventEditFetcher.jsx @@ -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 ; diff --git a/src/adminPage/features/eventEdit/businessLogic/DrawGradeData.js b/src/adminPage/features/eventEdit/businessLogic/DrawGradeData.js index ef4ad340..3f3707ef 100644 --- a/src/adminPage/features/eventEdit/businessLogic/DrawGradeData.js +++ b/src/adminPage/features/eventEdit/businessLogic/DrawGradeData.js @@ -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() { diff --git a/src/adminPage/features/eventEdit/businessLogic/reducer.js b/src/adminPage/features/eventEdit/businessLogic/reducer.js index ce9d2115..22b92893 100644 --- a/src/adminPage/features/eventEdit/businessLogic/reducer.js +++ b/src/adminPage/features/eventEdit/businessLogic/reducer.js @@ -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, @@ -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": diff --git a/src/adminPage/features/eventEdit/index.jsx b/src/adminPage/features/eventEdit/index.jsx index 79679fd9..eae8eba8 100644 --- a/src/adminPage/features/eventEdit/index.jsx +++ b/src/adminPage/features/eventEdit/index.jsx @@ -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( + + 사용자 입력이 잘못되었습니다. +
+ {JSON.stringify(value, null, 2)} + + } + />, + ); + }); + } else if (e.status === 401) { + openModal(); + } else if (e.status < 500) { + openModal( + + 클라이언트의 오류가 발생했습니다. +
+ 에러 코드 : {e.status} + + } + />, + ); + } else { + openModal( + + 서버의 오류가 발생했습니다. +
+ 에러 코드 : {e.status} + + } + />, + ); + } + } else { + openModal(); + } +} + 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( @@ -53,9 +95,7 @@ function EventEditor({ initialData = null } = {}) { />, ).then(() => navigate(mode === "create" ? "/events" : `/events/${state.eventId}`)); }, - onError: (e) => { - openModal(); - }, + onError: handleEventSubmitError, }, ); @@ -74,10 +114,10 @@ function EventEditor({ initialData = null } = {}) { await fetchServer("/api/v1/admin/events/temp", { method: "post", body: state, - }).catch(handleError(tempSubmitErrorHandler)); + }); openModal(); } catch (e) { - openModal(); + handleEventSubmitError(e); } } diff --git a/src/adminPage/features/eventEdit/mock.js b/src/adminPage/features/eventEdit/mock.js index 13852b34..3599633c 100644 --- a/src/adminPage/features/eventEdit/mock.js +++ b/src/adminPage/features/eventEdit/mock.js @@ -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 }); }), diff --git a/src/adminPage/features/eventList/Filter.jsx b/src/adminPage/features/eventList/Filter.jsx index 24f0620d..9bcb9bd6 100644 --- a/src/adminPage/features/eventList/Filter.jsx +++ b/src/adminPage/features/eventList/Filter.jsx @@ -9,8 +9,8 @@ function Filter({ state, dispatch }) { const labelStyle = "inline-flex items-center gap-1 text-body-s"; return ( -
-
+
+ {/*
상태
-
+
*/}
종류
diff --git a/src/adminPage/features/eventList/mock.js b/src/adminPage/features/eventList/mock.js index 4e05fec7..e51ba264 100644 --- a/src/adminPage/features/eventList/mock.js +++ b/src/adminPage/features/eventList/mock.js @@ -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; @@ -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, diff --git a/src/adminPage/features/eventList/queryReducer.js b/src/adminPage/features/eventList/queryReducer.js index 65eb3f67..4ab90687 100644 --- a/src/adminPage/features/eventList/queryReducer.js +++ b/src/adminPage/features/eventList/queryReducer.js @@ -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(","), diff --git a/src/adminPage/index.css b/src/adminPage/index.css index 1fb4351b..a44d84db 100644 --- a/src/adminPage/index.css +++ b/src/adminPage/index.css @@ -31,7 +31,7 @@ @layer base { body { - font-family: "hdsans"; + font-family: "hdsans", sans-serif; } body.scrollLocked { position: fixed; diff --git a/src/adminPage/shared/auth/LoginSection.jsx b/src/adminPage/shared/auth/LoginSection.jsx index 5c9829d3..4003359e 100644 --- a/src/adminPage/shared/auth/LoginSection.jsx +++ b/src/adminPage/shared/auth/LoginSection.jsx @@ -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}$" />
diff --git a/src/common/constants.js b/src/common/constants.js index dfcbbc7c..c4f3acf8 100644 --- a/src/common/constants.js +++ b/src/common/constants.js @@ -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); diff --git a/src/common/dataFetch/getQuery.js b/src/common/dataFetch/getQuery.js index 9b75d721..a08ebdb3 100644 --- a/src/common/dataFetch/getQuery.js +++ b/src/common/dataFetch/getQuery.js @@ -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) { diff --git a/src/mainPage/features/fcfs/cardGame/CardGame.jsx b/src/mainPage/features/fcfs/cardGame/CardGame.jsx index f7b0c1f6..9719ffb8 100644 --- a/src/mainPage/features/fcfs/cardGame/CardGame.jsx +++ b/src/mainPage/features/fcfs/cardGame/CardGame.jsx @@ -107,7 +107,7 @@ function CardGame({ offline }) { {[1, 2, 3, 4].map((index, i) => ( setFlipState((state) => { const newState = [...state]; diff --git a/src/mainPage/features/fcfs/cardGame/index.jsx b/src/mainPage/features/fcfs/cardGame/index.jsx index 90094abe..ef21bbc6 100644 --- a/src/mainPage/features/fcfs/cardGame/index.jsx +++ b/src/mainPage/features/fcfs/cardGame/index.jsx @@ -22,7 +22,7 @@ function CardGamePariticipatedInitializer() { function CardGameSection() { return ( - }> + 에러남
}> }> diff --git a/src/mainPage/index.css b/src/mainPage/index.css index 014b9561..6d06374c 100644 --- a/src/mainPage/index.css +++ b/src/mainPage/index.css @@ -31,7 +31,7 @@ @layer base { body { - font-family: "hdsans"; + font-family: "hdsans", sans-serif; } body.scrollLocked { position: fixed; diff --git a/src/mainPage/shared/drawEvent/store.js b/src/mainPage/shared/drawEvent/store.js index 1f60d271..5c17c6d7 100644 --- a/src/mainPage/shared/drawEvent/store.js +++ b/src/mainPage/shared/drawEvent/store.js @@ -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) => ({ diff --git a/src/mainPage/shared/realtimeEvent/store.js b/src/mainPage/shared/realtimeEvent/store.js index f2aa8741..c6fb68ab 100644 --- a/src/mainPage/shared/realtimeEvent/store.js +++ b/src/mainPage/shared/realtimeEvent/store.js @@ -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; } } diff --git a/vite.config.js b/vite.config.js index e4e4e440..26c29a06 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,7 +9,6 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url)); // https://vitejs.dev/config/ export default defineConfig({ - base: "./", plugins: [ devRouter([ ["/admin", "/admin.html"],