diff --git a/public/vite.svg b/public/vite.svg index e7b8dfb1..253e6a2d 100644 --- a/public/vite.svg +++ b/public/vite.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + diff --git a/src/App.tsx b/src/App.tsx index 98205afa..4f297a4d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,11 +1,32 @@ -import { ChakraProvider } from '@chakra-ui/react' +import { useEffect } from 'react' + +import { ChakraProvider, useToast } from '@chakra-ui/react' import { QueryClientProvider } from '@tanstack/react-query' import { queryClient } from '@/api/instance' import { Routes } from '@/routes' import theme from '@/styles/theme' +import { CookieAlaram } from './components/CookieAlaram' +import { useSSEMessage } from './hooks/useSSEMessage' + function App() { + const { message } = useSSEMessage() + const toast = useToast() + + useEffect(() => { + if (message) { + toast.closeAll() + toast({ + position: 'top', + duration: 3000, + render: () => ( + + ), + }) + } + }, [message, toast]) + return ( diff --git a/src/api/services/admin/admin.ts b/src/api/services/admin/admin.ts new file mode 100644 index 00000000..9de0992e --- /dev/null +++ b/src/api/services/admin/admin.ts @@ -0,0 +1,32 @@ +import { queryOptions } from '@tanstack/react-query' + +import { authorizationInstance } from '@/api/instance' +import { appendParamsToUrl } from '@/api/utils/common/appendParamsToUrl' +import { AdminQuestion, PagingRequestParams } from '@/types' + +type GetAdminQuestionsResponse = { + content: AdminQuestion[] + totalPages?: number + totalElements?: number +} + +const getAdminQuestions = async (params: PagingRequestParams) => { + const response = await authorizationInstance.get( + appendParamsToUrl('api/admin/question', params) + ) + + return { + questions: response.data.content, + totalPages: response.data.totalPages, + totalElements: response.data.totalElements, + } +} + +export const getAdminQuestionsQuries = { + all: () => ['getAdminQuestions'], + adminQuestions: (page?: number, size?: number) => + queryOptions({ + queryKey: [...getAdminQuestionsQuries.all(), page, size], + queryFn: () => getAdminQuestions({ page: String(page), size: 8 }), + }), +} diff --git a/src/components/PageLayout/SideNavigation/index.tsx b/src/components/PageLayout/SideNavigation/index.tsx index b8b4b764..b233eef9 100644 --- a/src/components/PageLayout/SideNavigation/index.tsx +++ b/src/components/PageLayout/SideNavigation/index.tsx @@ -8,9 +8,31 @@ import { useUserInfoStore } from '@/stores/user-info' export const SideNavigation = () => { const clearAuthToken = useAuthTokenStore((state) => state.clearAuthToken) + const isLoggedIn = useAuthTokenStore((state) => state.isLoggedIn()) + const clearUserInfo = useUserInfoStore((state) => state.clearUserInfo) const userId = useUserInfoStore((state) => state.userInfo?.userId) + if (!isLoggedIn) { + return ( + + + + + + ) + } + return ( { + if (!isLoggedIn) return () => {} + const eventSource = new EventSourcePolyfill( `${import.meta.env.VITE_BASE_URL}/api/alarm`, { @@ -27,7 +30,7 @@ export function useSEEMessage() { authorizationInstance.post('/api/alarm/disconnect', {}) eventSource.close() } - }, [authToken]) + }, [authToken, isLoggedIn]) return { message } } diff --git a/src/pages/Admin/GetQuestionAdminPage/index.tsx b/src/pages/Admin/GetQuestionAdminPage/index.tsx new file mode 100644 index 00000000..7384bf04 --- /dev/null +++ b/src/pages/Admin/GetQuestionAdminPage/index.tsx @@ -0,0 +1,64 @@ +import { Box, Flex, Text } from '@chakra-ui/react' +import { useQuery } from '@tanstack/react-query' + +import { getAdminQuestionsQuries } from '@/api/services/admin/admin' +import { Loading } from '@/components/Loading' +import ErrorPage from '@/pages/ErrorPage' + +export default function GetQuestionAdminPage() { + const { + data: questions, + status, + isLoading, + isError, + } = useQuery(getAdminQuestionsQuries.adminQuestions(0, 10)) + + if (status === 'pending' || isLoading) return + if (isError) return + if (!questions) return '질문 아무것도 없음' + + const questionsList = questions.questions + const totalElements = questions?.totalElements + const totalPages = questions?.totalPages + + return ( + + + + 질문 리스트 + + + + questionId + groupId + questionContent + createdAt + + status + + + {questionsList.map((question, idx) => ( + + {question.questionId} + {question.groupId} + {question.questionContent} + {question.createdAt} + + {question.status} + + + ))} + + + + ) +} diff --git a/src/pages/Admin/index.tsx b/src/pages/Admin/index.tsx new file mode 100644 index 00000000..9b41fb0e --- /dev/null +++ b/src/pages/Admin/index.tsx @@ -0,0 +1,59 @@ +import { useNavigate } from 'react-router-dom' + +import { Box, Button, Flex, Image, Text } from '@chakra-ui/react' +import { useQuery } from '@tanstack/react-query' + +import { getAdminQuestionsQuries } from '@/api/services/admin/admin' +import cookies from '@/assets/cookies.svg' +import { Loading } from '@/components/Loading' + +import ErrorPage from '../ErrorPage' + +export default function Admin() { + const { data, status, isLoading, isError } = useQuery( + getAdminQuestionsQuries.adminQuestions(0, 10) + ) + + const navigate = useNavigate() + + if (status === 'pending' || isLoading) return + if (isError) return + + console.log(data) + + return ( + + + + + Whokie 관리자 페이지 + + + + + + + + + + ) +} diff --git a/src/pages/GroupMembersPage/ExpelBtn/index.tsx b/src/pages/GroupMembersPage/ExpelBtn/index.tsx index bef26814..acc6e58f 100644 --- a/src/pages/GroupMembersPage/ExpelBtn/index.tsx +++ b/src/pages/GroupMembersPage/ExpelBtn/index.tsx @@ -29,6 +29,8 @@ export default function ExpelBtn({ mutationFn: () => expelMember({ groupId, userId }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['expelMember'] }) + queryClient.invalidateQueries({ queryKey: ['group', 'member', groupId] }) + queryClient.invalidateQueries({ queryKey: ['membersManage', groupId] }) window.location.reload() }, onError: () => { diff --git a/src/pages/GroupPage/ExitGroupButton/index.tsx b/src/pages/GroupPage/ExitGroupButton/index.tsx index ffd2f41b..7ccfbf8d 100644 --- a/src/pages/GroupPage/ExitGroupButton/index.tsx +++ b/src/pages/GroupPage/ExitGroupButton/index.tsx @@ -12,6 +12,7 @@ import { ConfirmModalButton, } from '@/components/Modal/ConfirmModal' import { useMembersLengthStore } from '@/stores/members-length' +import { useSelectedGroupStore } from '@/stores/selected-group' import { GroupRole } from '@/types' interface ExitGroupButtonProps { @@ -28,11 +29,15 @@ export const ExitGroupButton = ({ const warningAlert = useDisclosure() const errorAlert = useDisclosure() const navigate = useNavigate() + const setSelectedGroup = useSelectedGroupStore( + (state) => state.setSelectedGroup + ) const { mutate: exitGroup } = useMutation({ mutationFn: () => exitGroupMember(groupId), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['groups'] }) + setSelectedGroup(undefined) navigate('/') }, }) diff --git a/src/pages/GroupPage/GroupProfile/ImgModify/index.tsx b/src/pages/GroupPage/GroupProfile/ImgModify/index.tsx index b6bc7f5e..47ab8a7e 100644 --- a/src/pages/GroupPage/GroupProfile/ImgModify/index.tsx +++ b/src/pages/GroupPage/GroupProfile/ImgModify/index.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, useState } from 'react' +import { ChangeEvent, useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { BiError } from 'react-icons/bi' @@ -33,14 +33,32 @@ export default function ImgModify({ role, gprofile }: ImgModifyProps) { const [errorMessage, setErrorMessage] = useState('') const errorModal = useDisclosure() + const [timeoutId, setTimeoutId] = useState(null) const { mutate: uploadImage } = useMutation({ mutationFn: (data: ModifyGroupImgRequestBody) => modifyGroupImg(data), onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['group', gprofile.groupId] }) + if (timeoutId) { + clearTimeout(timeoutId) + } + + const newTimeoutId = setTimeout(() => { + queryClient.invalidateQueries({ queryKey: ['group', gprofile.groupId] }) + queryClient.invalidateQueries({ queryKey: ['groups'] }) + }, 2000) + + setTimeoutId(newTimeoutId) }, }) + useEffect(() => { + return () => { + if (timeoutId) { + clearTimeout(timeoutId) + } + } + }, [timeoutId]) + const handleFileChange = (e: ChangeEvent) => { const file = e.target.files ? e.target.files[0] : null diff --git a/src/pages/GroupPage/Management/CreateQuestion/index.tsx b/src/pages/GroupPage/Management/CreateQuestion/index.tsx index 5dff8770..61d52358 100644 --- a/src/pages/GroupPage/Management/CreateQuestion/index.tsx +++ b/src/pages/GroupPage/Management/CreateQuestion/index.tsx @@ -6,6 +6,7 @@ import { Box, Flex, useDisclosure } from '@chakra-ui/react' import { zodResolver } from '@hookform/resolvers/zod' import { useMutation } from '@tanstack/react-query' +import { queryClient } from '@/api/instance' import { CreateGroupQuestionPayload, createGroupQuestion, @@ -44,6 +45,10 @@ export const GroupQuestionCreateModal = ({ createGroupQuestion(payload), onSuccess: () => { onClose() + form.reset({ groupId, content: '' }) + queryClient.invalidateQueries({ + queryKey: ['groupQuestions', groupId, 'pending'], + }) }, onError: () => { setErrorMessage('질문 생성에 실패하였습니다') diff --git a/src/pages/GroupPage/Management/Questions/index.tsx b/src/pages/GroupPage/Management/Questions/index.tsx index ad95835c..29fa415c 100644 --- a/src/pages/GroupPage/Management/Questions/index.tsx +++ b/src/pages/GroupPage/Management/Questions/index.tsx @@ -4,6 +4,7 @@ import { useParams } from 'react-router-dom' import { Box, Text } from '@chakra-ui/react' import { useMutation } from '@tanstack/react-query' +import { queryClient } from '@/api/instance' import { approveGroupQuestion } from '@/api/services/group/group.api' import { useGroupRole } from '@/api/services/group/member.api' import { useGroupQuestion } from '@/api/services/question/group.api' @@ -24,7 +25,6 @@ export const QuestionManagement = () => { data: groupQuestions, isLoading, isError, - refetch, } = useGroupQuestion({ groupId: groupId || '', status, @@ -37,7 +37,12 @@ export const QuestionManagement = () => { return approveGroupQuestion(String(groupId), questionId, approve) }, onSuccess: () => { - refetch() + queryClient.invalidateQueries({ + queryKey: ['groupQuestions', groupId, status], + }) + queryClient.invalidateQueries({ + queryKey: ['question', 'common', 'random', 'group', groupId], + }) }, }) diff --git a/src/pages/InvitePage/InviteErrorFallback/ErrorModal/index.tsx b/src/pages/InvitePage/InviteErrorFallback/ErrorModal/index.tsx index 53e608a2..8393ed4e 100644 --- a/src/pages/InvitePage/InviteErrorFallback/ErrorModal/index.tsx +++ b/src/pages/InvitePage/InviteErrorFallback/ErrorModal/index.tsx @@ -30,3 +30,24 @@ export const InviteErrorMoal = ({ /> ) } + +export const InviteErrorMoalLogin = ({ + errorMessage, + detailMessage = '', +}: InviteErrorMoalProps) => { + const { onClose } = useDisclosure() + const navigate = useNavigate() + + return ( + { + navigate('/login') + onClose() + }} + icon={} + title={errorMessage} + description={detailMessage} + /> + ) +} diff --git a/src/pages/InvitePage/InviteErrorFallback/index.tsx b/src/pages/InvitePage/InviteErrorFallback/index.tsx index fbd9c6c6..28096805 100644 --- a/src/pages/InvitePage/InviteErrorFallback/index.tsx +++ b/src/pages/InvitePage/InviteErrorFallback/index.tsx @@ -1,11 +1,20 @@ import { FallbackProps } from 'react-error-boundary' import { InviteCardSkeleton } from '../InviteCard' -import { InviteErrorMoal } from './ErrorModal' +import { InviteErrorMoal, InviteErrorMoalLogin } from './ErrorModal' export const InviteErrorFallback = ({ error }: FallbackProps) => { const { status } = error + if (status === 401) { + return ( + <> + + + + ) + } + if (status === 403) { return ( <> diff --git a/src/pages/Layout/ProfileQuestionLayout/CreateQuestionButton/index.tsx b/src/pages/Layout/ProfileQuestionLayout/CreateQuestionButton/index.tsx index ac69b3bb..ebb4cf38 100644 --- a/src/pages/Layout/ProfileQuestionLayout/CreateQuestionButton/index.tsx +++ b/src/pages/Layout/ProfileQuestionLayout/CreateQuestionButton/index.tsx @@ -37,13 +37,13 @@ export const CreateQuestionButton = ({ userId }: CreateQuestionButtonProps) => { formModal.onClose() setNewQuestionContent('') queryClient.invalidateQueries({ queryKey: ['postNewQuestion'] }) - queryClient.refetchQueries({ - queryKey: ['profileQuestion', userId], + queryClient.invalidateQueries({ + queryKey: ['profileQuestion', userId.toString()], }) }, onError: () => { formModal.onClose() - setErrorMessage('답변 전송에 실패하였습니다') + setErrorMessage('질문 생성에 실패하였습니다') errorAlert.onOpen() }, }) diff --git a/src/pages/Layout/ProfileQuestionLayout/QuestionList/index.tsx b/src/pages/Layout/ProfileQuestionLayout/QuestionList/index.tsx index c68c3c69..5f24c88e 100644 --- a/src/pages/Layout/ProfileQuestionLayout/QuestionList/index.tsx +++ b/src/pages/Layout/ProfileQuestionLayout/QuestionList/index.tsx @@ -34,16 +34,7 @@ export const QuestionList = ({ isMyPage }: QuestionListProps) => { const deleteAlert = useDisclosure() const errorAlert = useDisclosure() - const questionId = useSelectedQuestionStore((state) => state.questionId) - const setSelectedQuestion = useSelectedQuestionStore( - (state) => state.setQuestionId - ) - const setQuestionContent = useSelectedQuestionStore( - (state) => state.setQuestionContent - ) - const setQuestionCreatedAt = useSelectedQuestionStore( - (state) => state.setQuestionCreatedAt - ) + const { selectedQuestion, setSelectedQuestion } = useSelectedQuestionStore() const location = useLocation() const userId: string = location.state?.userId.toString() @@ -70,25 +61,26 @@ export const QuestionList = ({ isMyPage }: QuestionListProps) => { }, []) useEffect(() => { - // 첫 렌더링 시 초기 store 지정 if (isFirstRender.current && questions && questions.length > 0) { - setSelectedQuestion(questions[0].profileQuestionId) - setQuestionContent(questions[0].profileQuestionContent) - setQuestionCreatedAt(questions[0].createdAt) - + setSelectedQuestion({ + selectQuestion: { + questionId: questions[0].profileQuestionId, + questionContent: questions[0].profileQuestionContent, + questionCreatedAt: questions[0].createdAt, + }, + }) isFirstRender.current = false } else if (isFirstRender.current && questions?.length === 0) { - setSelectedQuestion(undefined) - setQuestionContent(undefined) - setQuestionCreatedAt(undefined) + setSelectedQuestion({ + selectQuestion: { + questionId: undefined, + questionContent: undefined, + questionCreatedAt: undefined, + }, + }) + isFirstRender.current = false } - }, [ - questions, - questionId, - setSelectedQuestion, - setQuestionContent, - setQuestionCreatedAt, - ]) + }, [questions, setSelectedQuestion]) const { mutate: deleteQuestion } = useMutation< void, @@ -163,11 +155,17 @@ export const QuestionList = ({ isMyPage }: QuestionListProps) => { > { - setSelectedQuestion(question.profileQuestionId) - setQuestionContent(question.profileQuestionContent) - setQuestionCreatedAt(question.createdAt) + setSelectedQuestion({ + selectQuestion: { + questionId: question.profileQuestionId, + questionContent: question.profileQuestionContent, + questionCreatedAt: question.createdAt, + }, + }) }} > {question.profileQuestionContent} diff --git a/src/pages/MyPage/MyProfile/ProfileImage/index.tsx b/src/pages/MyPage/MyProfile/ProfileImage/index.tsx index 1974b3c6..09b3f06d 100644 --- a/src/pages/MyPage/MyProfile/ProfileImage/index.tsx +++ b/src/pages/MyPage/MyProfile/ProfileImage/index.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, useState } from 'react' +import { ChangeEvent, useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { BiError } from 'react-icons/bi' @@ -36,16 +36,36 @@ export const ProfileImage = ({ }) const [errorMessage, setErrorMessage] = useState('') + const [currentBackgroundImage, setCurrentBackgroundImage] = + useState(backgroundImage) const errorModal = useDisclosure() + const [timeoutId, setTimeoutId] = useState(null) const { mutate: uploadImage } = useMutation({ mutationFn: (data: { image: File }) => uploadProfileBg(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['myPage', userId] }) - window.location.reload() + + if (timeoutId) { + clearTimeout(timeoutId) + } + + const newTimeoutId = setTimeout(() => { + setCurrentBackgroundImage(URL.createObjectURL(form.getValues('image'))) + }, 2000) + + setTimeoutId(newTimeoutId) }, }) + useEffect(() => { + return () => { + if (timeoutId) { + clearTimeout(timeoutId) + } + } + }, [timeoutId]) + const handleFileChange = (e: ChangeEvent) => { const file = e.target.files ? e.target.files[0] : null @@ -69,7 +89,7 @@ export const ProfileImage = ({ return ( = ({ userId, isMyPage }: AnswerProps) => { - const questionId = useSelectedQuestionStore((state) => state.questionId) + const { selectedQuestion } = useSelectedQuestionStore() const [selectDeleteAnswerId, setSelectDeleteAnswerId] = useState< number | null >(null) @@ -43,7 +43,7 @@ const Answer: React.FC = ({ userId, isMyPage }: AnswerProps) => { onSuccess: () => { deleteAlert.onClose() queryClient.refetchQueries({ - queryKey: ['profileAnswer', userId, questionId], + queryKey: ['profileAnswer', userId, selectedQuestion.questionId], }) queryClient.invalidateQueries({ queryKey: ['deleteProfileAnswer'] }) }, @@ -57,7 +57,7 @@ const Answer: React.FC = ({ userId, isMyPage }: AnswerProps) => { data: answers, isLoading, isError, - } = useGetProfileAnswer(userId, questionId as number) + } = useGetProfileAnswer(userId, selectedQuestion.questionId as number) const boxRef = useRef(null) useEffect(() => { diff --git a/src/pages/ProfileQuestionPage/Question/index.tsx b/src/pages/ProfileQuestionPage/Question/index.tsx index f9280a21..0fbbc33b 100644 --- a/src/pages/ProfileQuestionPage/Question/index.tsx +++ b/src/pages/ProfileQuestionPage/Question/index.tsx @@ -9,29 +9,23 @@ import { ChatItem } from '@/types' import formatDate from '../Answer/formatDate' export default function Question() { - const questionId = useSelectedQuestionStore((state) => state.questionId) - const questionCreatedAt = useSelectedQuestionStore( - (state) => state.questionCreatedAt - ) - const questionContent = useSelectedQuestionStore( - (state) => state.questionContent - ) + const { selectedQuestion } = useSelectedQuestionStore() const [question, setQuestion] = useState(null) useEffect(() => { - if (questionId && questionContent) { + if (selectedQuestion.questionId && selectedQuestion.questionContent) { setQuestion({ - chatId: questionId, + chatId: selectedQuestion.questionId, direction: 'left', - createdAt: formatDate(questionCreatedAt as string), - content: questionContent, + createdAt: formatDate(selectedQuestion.questionCreatedAt as string), + content: selectedQuestion.questionContent, deleteBtn: false, }) } else { setQuestion(null) } - }, [questionId, questionContent, questionCreatedAt]) + }, [selectedQuestion]) return ( {question && } diff --git a/src/pages/ProfileQuestionPage/WriteReply/index.tsx b/src/pages/ProfileQuestionPage/WriteReply/index.tsx index d29f2fb8..ab55476b 100644 --- a/src/pages/ProfileQuestionPage/WriteReply/index.tsx +++ b/src/pages/ProfileQuestionPage/WriteReply/index.tsx @@ -46,6 +46,7 @@ export default function WriteReply({ userId, questionId }: WriteReplyProps) { queryClient.refetchQueries({ queryKey: ['profileAnswer', userId, questionId], }) + form.reset() }, onError: () => { setErrorMessage('답변 전송에 실패하였습니다') diff --git a/src/pages/ProfileQuestionPage/index.tsx b/src/pages/ProfileQuestionPage/index.tsx index 0d392505..1e0cdcda 100644 --- a/src/pages/ProfileQuestionPage/index.tsx +++ b/src/pages/ProfileQuestionPage/index.tsx @@ -14,8 +14,8 @@ export default function ProfileQuestionPage() { const navigate = useNavigate() const location = useLocation() const userId: number = location.state?.userId - const myUserId = useUserInfoStore((state) => state.userInfo?.userId) - const questionId = useSelectedQuestionStore((state) => state.questionId) + const myUserId = useMyUserIdStore((state) => state.myUserId) + const { selectedQuestion } = useSelectedQuestionStore() const isMyPage = Number(userId) === myUserId @@ -50,8 +50,8 @@ export default function ProfileQuestionPage() { {/* 이 영역만 스크롤 */} {userId && } - {!isMyPage && questionId && ( - + {!isMyPage && selectedQuestion.questionId && ( + )} ) diff --git a/src/routes/ProtectedRoute/index.tsx b/src/routes/ProtectedRoute/index.tsx index 4a06744b..1153c191 100644 --- a/src/routes/ProtectedRoute/index.tsx +++ b/src/routes/ProtectedRoute/index.tsx @@ -1,34 +1,16 @@ import { useEffect } from 'react' import { Outlet } from 'react-router-dom' -import { useToast } from '@chakra-ui/react' - -import { CookieAlaram } from '@/components/CookieAlaram' -import { useSEEMessage } from '@/hooks/useSEEMessage' import { useAuthTokenStore } from '@/stores/auth-token' export const ProtectedRoute = () => { const isLoggedIn = useAuthTokenStore((state) => state.isLoggedIn()) - const { message } = useSEEMessage() - const toast = useToast() - useEffect(() => { - if (isLoggedIn && message) { - toast.closeAll() - toast({ - position: 'top', - duration: 3000, - render: () => ( - - ), - }) - } - if (!isLoggedIn) { window.location.href = `/login` } - }, [toast, message, isLoggedIn]) + }, [isLoggedIn]) return } diff --git a/src/routes/index.tsx b/src/routes/index.tsx index fd1c0866..7beda6c1 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -2,6 +2,8 @@ import { RouterProvider, createBrowserRouter } from 'react-router-dom' import { useMediaQuery } from '@chakra-ui/react' +import Admin from '@/pages/Admin' +import GetQuestionAdminPage from '@/pages/Admin/GetQuestionAdminPage' import ComingSoonPage from '@/pages/ComingSoonPage' import CookieRecordPage from '@/pages/CookieRecordPage' import CreateGroupPage from '@/pages/CreateGroupPage' @@ -96,6 +98,14 @@ const router = createBrowserRouter([ path: '/invite/:groupId', element: , }, + { + path: '/admin/main', + element: , + }, + { + path: '/admin/get/questions', + element: , + }, { path: '/register', element: , diff --git a/src/stores/selected-question.ts b/src/stores/selected-question.ts index 35902694..86587e2f 100644 --- a/src/stores/selected-question.ts +++ b/src/stores/selected-question.ts @@ -1,27 +1,27 @@ import { create } from 'zustand' -interface SelectedQuestionProps { +interface SelectedQuestion { questionId: number | undefined questionContent: string | undefined questionCreatedAt: string | undefined - setQuestionId: (questionId: number | undefined) => void - setQuestionContent: (questionContent: string | undefined) => void - setQuestionCreatedAt: (questionCreatedAt: string | undefined) => void +} + +interface SelectedQuestionProps { + selectedQuestion: SelectedQuestion + setSelectedQuestion: (selectQuestion: { + selectQuestion: SelectedQuestion + }) => void } export const useSelectedQuestionStore = create( (set) => ({ - questionId: undefined, - questionContent: undefined, - questionCreatedAt: undefined, - setQuestionId: (questionId) => { - set({ questionId }) - }, - setQuestionContent: (questionContent) => { - set({ questionContent }) + selectedQuestion: { + questionId: undefined, + questionContent: undefined, + questionCreatedAt: undefined, }, - setQuestionCreatedAt: (questionCreatedAt) => { - set({ questionCreatedAt }) + setSelectedQuestion: ({ selectQuestion }) => { + set({ selectedQuestion: selectQuestion }) }, }) ) diff --git a/src/types/index.ts b/src/types/index.ts index eeeebc95..403eaee8 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -144,3 +144,11 @@ export type MemberTable = { userId: number role: GroupRole } + +export type AdminQuestion = { + questionId: number + questionContent: string + groupId: number + status: string + createdAt: string +}