diff --git a/src/apis/primitives.ts b/src/apis/primitives.ts index 8a3858b7..e4bf1c13 100644 --- a/src/apis/primitives.ts +++ b/src/apis/primitives.ts @@ -42,10 +42,17 @@ export async function request( if (axios.isAxiosError(error)) { // If error is raised during API request, // pass it as an APIError + const responseData = error.response?.data; + const message = + typeof responseData === 'string' + ? responseData + : typeof responseData === 'object' && responseData !== null + ? JSON.stringify(responseData) + : error.message; const apiError = new APIError( - error.response?.data || error.message, + message, error.response?.status || 500, - error.response?.data, + responseData, ); throw apiError; } diff --git a/src/components/DialogModal/DialogModal.tsx b/src/components/DialogModal/DialogModal.tsx index eecb3175..f042d9ad 100644 --- a/src/components/DialogModal/DialogModal.tsx +++ b/src/components/DialogModal/DialogModal.tsx @@ -1,16 +1,14 @@ import { PropsWithChildren } from 'react'; +interface DialogButton { + text: string; + onClick: () => void; + isBold?: boolean; +} + interface DialogModalProps extends PropsWithChildren { - left: { - text: string; - onClick: () => void; - isBold?: boolean; - }; - right: { - text: string; - onClick: () => void; - isBold?: boolean; - }; + left?: DialogButton; + right?: DialogButton; } export default function DialogModal({ @@ -18,12 +16,11 @@ export default function DialogModal({ left, right, }: DialogModalProps) { - if (left.isBold === undefined || null) { - left.isBold = false; - } - if (right.isBold === undefined || null) { - right.isBold = false; - } + const leftIsBold = left?.isBold ?? false; + const rightIsBold = right?.isBold ?? false; + const hasButtons = Boolean(left || right); + const isSingleButton = Boolean(left && !right) || Boolean(right && !left); + const buttonWidthClass = isSingleButton ? 'w-full' : 'w-1/2'; return (
-
- {/** Left button */} - + {hasButtons && ( + <> +
+
+ {left && ( + + )} - {/** Right button */} - -
+ {right && ( + + )} +
+ + )}
); } diff --git a/src/page/DebateVotePage/DebateVotePage.tsx b/src/page/DebateVotePage/DebateVotePage.tsx index 70061bdc..90b27349 100644 --- a/src/page/DebateVotePage/DebateVotePage.tsx +++ b/src/page/DebateVotePage/DebateVotePage.tsx @@ -5,7 +5,8 @@ import DefaultLayout from '../../layout/defaultLayout/DefaultLayout'; import { useGetPollInfo } from '../../hooks/query/useGetPollInfo'; import ErrorIndicator from '../../components/ErrorIndicator/ErrorIndicator'; import useFetchEndPoll from '../../hooks/mutations/useFetchEndPoll'; -import GoToDebateEndButton from '../../components/GoToDebateEndButton/GoToDebateEndButton'; +import { useModal } from '../../hooks/useModal'; +import DialogModal from '../../components/DialogModal/DialogModal'; export default function DebateVotePage() { const navigate = useNavigate(); const baseUrl = @@ -37,7 +38,20 @@ export default function DebateVotePage() { refetch, isRefetchError, } = useGetPollInfo(pollId, { refetchInterval: 5000, enabled: isArgsValid }); + const { openModal, closeModal, ModalWrapper } = useModal(); const { mutate } = useFetchEndPoll(handleGoToResult); + const handleConfirmEnd = () => { + if (!isArgsValid) return; + mutate(pollId, { + onSuccess: () => { + closeModal(); + }, + onError: () => { + closeModal(); + alert('투표 종료에 실패했습니다.'); + }, + }); + }; const participants = data?.voterNames; const isLoading = isFetching || isRefetching; @@ -114,11 +128,10 @@ export default function DebateVotePage() { -
- +
+ + +
+

투표를 마감하시겠습니까?

+

+ 투표를 마감하면 더이상 표를 받을 수 없습니다! +

+
+
+
); } diff --git a/src/page/DebateVoteResultPage/DebateVoteResultPage.tsx b/src/page/DebateVoteResultPage/DebateVoteResultPage.tsx index 4c6cac66..3cf9110a 100644 --- a/src/page/DebateVoteResultPage/DebateVoteResultPage.tsx +++ b/src/page/DebateVoteResultPage/DebateVoteResultPage.tsx @@ -7,7 +7,7 @@ import VoteDetailResult from './components/VoteDetailResult'; import { useGetPollInfo } from '../../hooks/query/useGetPollInfo'; import ErrorIndicator from '../../components/ErrorIndicator/ErrorIndicator'; import { TeamKey } from '../../type/type'; -import { useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import DialogModal from '../../components/DialogModal/DialogModal'; export default function DebateVoteResultPage() { // 매개변수 검증 @@ -32,6 +32,17 @@ export default function DebateVoteResultPage() { const handleGoHome = () => { navigate('/'); }; + const handleGoToEndPage = useCallback(() => { + navigate(`/table/customize/${tableId}/end`, { replace: true }); + }, [navigate, tableId]); + + useEffect(() => { + if (!isArgsValid) return; + + window.addEventListener('popstate', handleGoToEndPage); + return () => window.removeEventListener('popstate', handleGoToEndPage); + }, [handleGoToEndPage, isArgsValid]); + const isLoading = isFetching || isRefetching; const isError = isFetchError || isRefetchError; const { openModal, ModalWrapper, closeModal } = useModal({ @@ -108,11 +119,11 @@ export default function DebateVoteResultPage() {