diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompo.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompo.tsx
index 32e6be0..cf85c96 100644
--- a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompo.tsx
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompo.tsx
@@ -2,6 +2,7 @@ import { IWorkoutConfirmationPageProps } from '@/types/workoutConfirmation';
import ConfirmationProfile from './ConfirmationProfile';
import ConfirmationCompoObjection from './ConfirmationCompoObjection';
import ConfirmationCompoConfirm from './ConfirmationCompoConfirm';
+import ConfirmationCompoTime from './ConfirmationCompoTime';
interface IConfirmationCompoProps {
workoutConfirmationPage: IWorkoutConfirmationPageProps;
@@ -30,15 +31,9 @@ export default function ConfirmationCompo({
workspaceId={workspaceId}
/>
)}
-
-
- {workoutConfirmationPage.createdAt.substring(11, 16)}
-
-
+
);
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompoTime.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompoTime.tsx
new file mode 100644
index 0000000..10a30c1
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ConfirmationCompoTime.tsx
@@ -0,0 +1,21 @@
+import { IWorkoutConfirmationPageProps } from '@/types/workoutConfirmation';
+
+interface IConfirmationPageProps {
+ workoutConfirmationPage: IWorkoutConfirmationPageProps;
+}
+
+export default function ConfirmationCompoTime({
+ workoutConfirmationPage,
+}: IConfirmationPageProps) {
+ return (
+
+
+ {workoutConfirmationPage.createdAt.substring(11, 16)}
+
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ScrollTop.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ScrollTop.tsx
new file mode 100644
index 0000000..9347238
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/_components/ScrollTop.tsx
@@ -0,0 +1,14 @@
+'use client';
+
+import { usePathname } from 'next/navigation';
+import { useEffect } from 'react';
+
+export default function ScrollTop() {
+ const pathName = usePathname();
+
+ useEffect(() => {
+ window.scrollTo(0, 0);
+ }, [pathName]);
+
+ return null;
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/page.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/page.tsx
index 443a7dd..cab5f6a 100644
--- a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/page.tsx
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/page.tsx
@@ -10,64 +10,91 @@ import ObjectionBell from './_components/ObjectionBell';
import IsSameDateAsPrevious from './_components/IsSameDataAsPrevious';
import ConfirmationCompo from './_components/ConfirmationCompo';
import useInfiniteQuerys from '@/hooks/workoutConfirmation/ useInfiniteQuerys';
-import { useEffect, useRef } from 'react';
+import { useEffect, useRef, useState } from 'react';
+import NoDataUI from '../../_components/NoDataUI';
export default function Page() {
const workspaceId = useWorkoutIdFromParams();
- const [ref, inView] = useInView({ threshold: 0, delay: 0 });
+ const [initialObserve, setInitialObserve] = useState(false);
+
+ const [ref, inView] = useInView({
+ threshold: 0.1,
+ delay: 500,
+ });
const scrollBottomRef = useRef(null);
- const isInitialRender = useRef(true);
+ const isInitialRender = useRef(true);
const workoutConfirmation = useInfiniteQuerys({
queryKey: ['workoutConfirmations', workspaceId],
dataReqFn: workoutConfirmations,
params: { workspaceId },
- inView,
+ inView: inView && initialObserve,
});
- const workoutConfirmationPages = workoutConfirmation?.pages.flatMap(
- (pages) => pages.data.data
- );
+ const workoutConfirmationPages = workoutConfirmation?.pages
+ .slice()
+ .reverse()
+ .flatMap((pages) => pages.data.data);
+
const workoutConfirmationVoteInCompletionCount =
workoutConfirmation?.pages.flatMap(
(pages) => pages.data.voteIncompletionCount
);
useEffect(() => {
- if (scrollBottomRef.current && isInitialRender) {
- scrollBottomRef.current?.scrollIntoView({ behavior: 'auto' });
- isInitialRender.current = false;
- }
+ if (
+ isInitialRender.current &&
+ workoutConfirmationPages &&
+ workoutConfirmationPages.length
+ )
+ setTimeout(() => {
+ scrollBottomRef.current?.scrollIntoView({
+ behavior: 'auto',
+ });
+ isInitialRender.current = false;
+ setTimeout(() => {
+ setInitialObserve(true);
+ }, 100);
+ }, 100);
}, [workoutConfirmationPages]);
return (
-
- {workoutConfirmationPages?.map(
- (
- workoutConfirmationPage: IWorkoutConfirmationPageProps,
- index: number
- ) => {
- return (
-
-
-
-
- );
- }
+ {workoutConfirmationPages?.length === 0 ? (
+
+
+
+ ) : (
+
+
+ {workoutConfirmationPages?.map(
+ (
+ workoutConfirmationPage: IWorkoutConfirmationPageProps,
+ index: number
+ ) => {
+ return (
+
+
+
+
+ );
+ }
+ )}
+
+
)}
-
);
}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfimationDetailImage.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfimationDetailImage.tsx
new file mode 100644
index 0000000..ba781e0
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfimationDetailImage.tsx
@@ -0,0 +1,29 @@
+import Image from 'next/image';
+
+import confirmDetailNoImage from '@/../public/svgs/workspace/workspaceConfirmaion/confirmDetailNoImage.svg';
+import { IWorkspaceConfirmationDetailProps } from '@/types/workoutConfirmation';
+
+interface IConfirmationDetailImage {
+ workspaceConfirmationDetail: IWorkspaceConfirmationDetailProps | undefined;
+}
+
+export default function ConfirmationDetailImage({
+ workspaceConfirmationDetail,
+}: IConfirmationDetailImage) {
+ return (
+
+ {workspaceConfirmationDetail?.workoutConfirmationImageUrl === '' ? (
+
+ ) : (
+ src}
+ loading='lazy'
+ sizes='360px'
+ fill
+ />
+ )}
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailCompo.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailCompo.tsx
new file mode 100644
index 0000000..5a3923e
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailCompo.tsx
@@ -0,0 +1,49 @@
+'use client';
+
+import { useQuery } from '@tanstack/react-query';
+
+import ConfirmationDetailImage from './ConfimationDetailImage';
+import ConfirmationDetailProfile from './ConfirmationDetailProfile';
+import { IWorkspaceConfirmationDetailProps } from '@/types/workoutConfirmation';
+import useWorkoutIdFromParams from '@/hooks/workoutHistory/useWorkoutIdFromParams';
+import { workoutConfirmaionsDetail } from '@/api/workspaceConfirmaion';
+
+interface IConfirmationDetailCompoProps {
+ workoutConfirmationId: number;
+}
+
+export default function ConfirmationDetailCompo({
+ workoutConfirmationId,
+}: IConfirmationDetailCompoProps) {
+ const workspaceId = useWorkoutIdFromParams();
+
+ const { data: workspaceConfirmationDetail } = useQuery<{
+ data: IWorkspaceConfirmationDetailProps;
+ }>({
+ queryKey: [
+ 'workspaceConfimationDetail',
+ workspaceId,
+ workoutConfirmationId,
+ ],
+ queryFn: () =>
+ workoutConfirmaionsDetail({
+ workspaceId,
+ workoutConfirmationId,
+ }),
+ });
+ return (
+
+
+
+
+ {workspaceConfirmationDetail?.data.comment}
+
+
+
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailObjectionInput.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailObjectionInput.tsx
new file mode 100644
index 0000000..76c49c7
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailObjectionInput.tsx
@@ -0,0 +1,102 @@
+'use client';
+
+import { workoutObjectionReason } from '@/api/workspaceConfirmaion';
+import {
+ DialogClose,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from '@/components/ui/dialog';
+import useWorkoutIdFromParams from '@/hooks/workoutHistory/useWorkoutIdFromParams';
+import { DialogDescription } from '@radix-ui/react-dialog';
+import { useMutation } from '@tanstack/react-query';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+
+interface IConfirmationDetailObjectionInputProps {
+ workoutConfirmationId: number;
+}
+
+export default function ConfirmationDetailObjectionInput({
+ workoutConfirmationId,
+}: IConfirmationDetailObjectionInputProps) {
+ const router = useRouter();
+ const [reasonInput, setReasonInput] = useState('');
+ const workspaceId = useWorkoutIdFromParams();
+
+ const objectionReason = useMutation({
+ mutationFn: workoutObjectionReason,
+ onSuccess: (data) => {
+ console.log('Success:', data);
+ alert('이의 신청이 성공적으로 제출되었습니다.');
+ router.push(`/workspace/${workspaceId}/workspaceConfirmation`);
+ },
+ onError: (error) => {
+ console.error('Error:', error);
+ alert('이의 신청 제출 중 오류가 발생했습니다.');
+ },
+ });
+
+ const handleReasonPost = (event: React.MouseEvent) => {
+ event.preventDefault();
+
+ if (reasonInput.length < 10) {
+ alert('10자 이상 작성하셔야 합니다.');
+ }
+
+ if (reasonInput.length >= 10) {
+ objectionReason.mutate({
+ workspaceId,
+ workoutConfirmationId,
+ objectionReason: reasonInput,
+ });
+ }
+ };
+
+ return (
+
+
+
+
+ 이의 신청 이유를 입력해주세요.
+
+
+
+ setReasonInput(e.target.value)}
+ />
+ {reasonInput.length <= 10 ? (
+
+ 이의 신청 이유는 10자 이상 작성해주세요.
+
+ ) : (
+ <>>
+ )}
+
+
+
+
+
+
+ cancel
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailProfile.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailProfile.tsx
new file mode 100644
index 0000000..f1feb5e
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/ConfirmationDetailProfile.tsx
@@ -0,0 +1,26 @@
+import ConfirmationProfileImg from '../../_components/ConfirmationProfileImg';
+import { IWorkspaceConfirmationDetailProps } from '@/types/workoutConfirmation';
+
+interface IConfirmationDetailProfileProps {
+ workspaceConfirmationDetail: IWorkspaceConfirmationDetailProps | undefined;
+}
+
+export default function ConfirmationDetailProfile({
+ workspaceConfirmationDetail,
+}: IConfirmationDetailProfileProps) {
+ return (
+
+
+
+
+ {workspaceConfirmationDetail?.nickname}
+
+
+ {workspaceConfirmationDetail?.loginId}
+
+
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/confirmationObjection/ConfirmationObjectionCompo.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/confirmationObjection/ConfirmationObjectionCompo.tsx
new file mode 100644
index 0000000..e87918e
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/confirmationObjection/ConfirmationObjectionCompo.tsx
@@ -0,0 +1,180 @@
+'use client';
+
+import { useState } from 'react';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
+
+import Image from 'next/image';
+import { ReadonlyURLSearchParams } from 'next/navigation';
+import { DialogTrigger } from '@/components/ui/dialog';
+
+import objectedWorkoutVoteIcon from '@/../public/svgs/workspace/workspaceConfirmaion/objectedWorkoutVoteIcon.svg';
+import RemaineTime from '../RemaineTime';
+import {
+ workoutObjections,
+ workoutObjectionsVote,
+} from '@/api/workspaceConfirmaion';
+import useWorkoutIdFromParams from '@/hooks/workoutHistory/useWorkoutIdFromParams';
+import ConfirmationObjectionProgressBars from './ConfirmationObjectionProgressBars';
+import { IWorkoutObjectionProps } from '@/types/workoutConfirmation';
+
+interface IConfirmationObjectionCompo {
+ seachParams: ReadonlyURLSearchParams;
+}
+
+export default function ConfirmationObjectionCompo({
+ seachParams,
+}: IConfirmationObjectionCompo) {
+ const workspaceId = useWorkoutIdFromParams();
+ const [isObjectionVote, setIsObjectionVote] = useState(null);
+ const objectionId = parseInt(seachParams.get('objectionId') || '0', 10);
+
+ const isObjection = seachParams.get('isObjection') === 'false';
+
+ const { data: workoutObjection } = useQuery<{ data: IWorkoutObjectionProps }>(
+ {
+ queryKey: ['workoutObjection', workspaceId, objectionId],
+ queryFn: () =>
+ workoutObjections({
+ workspaceId,
+ objectionId,
+ }),
+ enabled: !isObjection,
+ }
+ );
+
+ const queryClient = useQueryClient();
+
+ const OBJECTTIONVOTE_QUERYKEY = {
+ workoutObjection: (workspaceId: number, objectionId: number) => [
+ 'workoutObjection',
+ workspaceId,
+ objectionId,
+ ],
+ };
+
+ const objectionVote = useMutation({
+ mutationFn: workoutObjectionsVote,
+ onSuccess: (data) => {
+ console.log('Success:', data);
+ alert('이의 신청 투표가 성공적으로 제출되었습니다.');
+
+ queryClient.invalidateQueries({
+ queryKey: OBJECTTIONVOTE_QUERYKEY.workoutObjection(
+ workspaceId,
+ objectionId
+ ),
+ });
+ },
+
+ onError: (error) => {
+ console.error('Error:', error);
+ alert('이의 신청 투표 중 오류가 발생했습니다.');
+ },
+ });
+
+ const handleVotePost = (event: React.MouseEvent) => {
+ event.preventDefault();
+
+ if (isObjectionVote === null) {
+ alert('이의신청 투표를 진행해주세요.');
+ }
+
+ if (isObjectionVote !== null) {
+ objectionVote.mutate({
+ workspaceId,
+ objectionId,
+ objectionVote: isObjectionVote,
+ });
+ }
+ };
+
+ return (
+
+ {isObjection ? (
+
+
+
+
+
+ ) : (
+
+
+
+
+ {!workoutObjection?.data.inInProgress
+ ? `투표 결과: ${
+ workoutObjection?.data.confirmationCompletion
+ ? '찬성'
+ : '반대'
+ }`
+ : '이의 신청 투표'}
+
+
+
+ {workoutObjection?.data.reason}
+
+
+
+ {!workoutObjection?.data.inInProgress ? (
+ '투표 종료'
+ ) : (
+ <>
+ 투표 종료까지{' '}
+
+ >
+ )}
+ {' * '}
+ {workoutObjection?.data.voteParticipationCount}명 참여
+
+
+ {!workoutObjection?.data.inInProgress ? (
+
+ 투표 종료
+
+ ) : (
+
+
+
+ {workoutObjection?.data.voteCompletion ? (
+
투표완료
+ ) : (
+
+ )}
+
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/confirmationObjection/ConfirmationObjectionProgressBars.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/confirmationObjection/ConfirmationObjectionProgressBars.tsx
new file mode 100644
index 0000000..e83252e
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/_components/confirmationObjection/ConfirmationObjectionProgressBars.tsx
@@ -0,0 +1,48 @@
+import { IWorkoutObjectionProps } from '@/types/workoutConfirmation';
+import ProgressBar from '../ProgressBar';
+import { Dispatch, SetStateAction } from 'react';
+
+interface IConfirmationObjectionProgressBarsProps {
+ isObjectionVote: boolean | null;
+ setIsObjectionVote: Dispatch>;
+ workoutObjection: IWorkoutObjectionProps;
+}
+
+export default function ConfirmationObjectionProgressBars({
+ isObjectionVote,
+ setIsObjectionVote,
+ workoutObjection,
+}: IConfirmationObjectionProgressBarsProps) {
+ const handleVote = (isObjection: boolean) => {
+ setIsObjectionVote((prev) => (prev === isObjection ? null : isObjection));
+ };
+
+ const appovalCount =
+ (workoutObjection?.approvalCount / workoutObjection?.headCount) * 100;
+ const rejectionCount =
+ (workoutObjection?.rejectionCount / workoutObjection?.headCount) * 100;
+
+ if (appovalCount > 100 || rejectionCount > 100) {
+ appovalCount === 100 || rejectionCount === 100;
+ }
+ return (
+
+
{
+ if (!workoutObjection?.voteCompletion) handleVote(true);
+ }}
+ isObjectionVote={isObjectionVote === true}
+ />
+ {
+ if (!workoutObjection?.voteCompletion) handleVote(false);
+ }}
+ isObjectionVote={isObjectionVote === false}
+ />
+
+ );
+}
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/page.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/page.tsx
index fea5dde..78f3197 100644
--- a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/page.tsx
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceConfirmation/workspaceConfirmaionDetail/page.tsx
@@ -1,345 +1,33 @@
'use client';
-import Image from 'next/image';
-import { useState } from 'react';
+import { Dialog } from '@/components/ui/dialog';
-import {
- Dialog,
- DialogClose,
- DialogContent,
- DialogFooter,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from '@/components/ui/dialog';
+import { useSearchParams } from 'next/navigation';
-import objectedWorkoutVoteIcon from '@/../public/svgs/workspace/workspaceConfirmaion/objectedWorkoutVoteIcon.svg';
-import confirmDetailNoImage from '@/../public/svgs/workspace/workspaceConfirmaion/confirmDetailNoImage.svg';
-
-import { DialogDescription } from '@radix-ui/react-dialog';
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
-import { useRouter, useSearchParams } from 'next/navigation';
-import useWorkoutIdFromParams from '@/hooks/workoutHistory/useWorkoutIdFromParams';
-import {
- workoutConfirmaionsDetail,
- workoutObjectionReason,
- workoutObjections,
- workoutObjectionsVote,
-} from '@/api/workspaceConfirmaion';
-import ProgressBar from './_components/ProgressBar';
-import RemaineTime from './_components/RemaineTime';
-import ConfirmationProfileImg from '../_components/ConfirmationProfileImg';
+import ScrollTop from '../_components/ScrollTop';
+import ConfirmationObjectionCompo from './_components/confirmationObjection/ConfirmationObjectionCompo';
+import ConfirmationDetailCompo from './_components/ConfirmationDetailCompo';
+import ConfirmationDetailObjectionInput from './_components/ConfirmationDetailObjectionInput';
export default function Page() {
- const [reasonInput, setReasonInput] = useState('');
- const [isObjectionVote, setIsObjection] = useState(null);
- const router = useRouter();
- const workspaceId = useWorkoutIdFromParams();
const seachParams = useSearchParams();
const workoutConfirmationId = parseInt(
seachParams.get('workoutConfirmationId') || '0',
10
);
- const isObjection = seachParams.get('isObjection') === 'false';
-
- const objectionId = parseInt(seachParams.get('objectionId') || '0', 10);
-
- const { data: workspaceConfirmationDetail } = useQuery({
- queryKey: [
- 'workspaceConfimationDetail',
- workspaceId,
- workoutConfirmationId,
- ],
- queryFn: () =>
- workoutConfirmaionsDetail({
- workspaceId,
- workoutConfirmationId,
- }),
- });
-
- const { data: workoutObjection } = useQuery({
- queryKey: ['workoutObjection', workspaceId, objectionId],
- queryFn: () =>
- workoutObjections({
- workspaceId,
- objectionId,
- }),
- enabled: !isObjection,
- });
-
- const queryClient = useQueryClient();
-
- const objectionReason = useMutation({
- mutationFn: workoutObjectionReason,
- onSuccess: (data) => {
- console.log('Success:', data);
- alert('이의 신청이 성공적으로 제출되었습니다.');
- router.push(`/workspace/${workspaceId}/workspaceConfirmation`);
- },
- onError: (error) => {
- console.error('Error:', error);
- alert('이의 신청 제출 중 오류가 발생했습니다.');
- },
- });
-
- const handleReasonPost = (event: React.MouseEvent) => {
- event.preventDefault();
-
- if (reasonInput.length < 10) {
- alert('10자 이상 작성하셔야 합니다.');
- }
-
- if (reasonInput.length >= 10) {
- objectionReason.mutate({
- workspaceId,
- workoutConfirmationId,
- objectionReason: reasonInput,
- });
- }
- };
-
- const handleVote = (isObjection: boolean) => {
- setIsObjection((prev) => (prev === isObjection ? null : isObjection));
- };
-
- const OBJECTTIONVOTE_QUERYKEY = {
- workoutObjection: (workspaceId: number, objectionId: number) => [
- 'workoutObjection',
- workspaceId,
- objectionId,
- ],
- };
-
- const objectionVote = useMutation({
- mutationFn: workoutObjectionsVote,
- onSuccess: (data) => {
- console.log('Success:', data);
- alert('이의 신청 투표가 성공적으로 제출되었습니다.');
-
- queryClient.invalidateQueries({
- queryKey: OBJECTTIONVOTE_QUERYKEY.workoutObjection(
- workspaceId,
- objectionId
- ),
- });
- },
-
- onError: (error) => {
- console.error('Error:', error);
- alert('이의 신청 투표 중 오류가 발생했습니다.');
- },
- });
-
- const handleVotePost = (event: React.MouseEvent) => {
- event.preventDefault();
-
- if (isObjectionVote === null) {
- alert('이의신청 투표를 진행해주세요.');
- }
-
- if (isObjectionVote !== null) {
- objectionVote.mutate({
- workspaceId,
- objectionId,
- objectionVote: isObjectionVote,
- });
- }
- };
-
- const appovalCount =
- (workoutObjection?.data.approvalCount / workoutObjection?.data.headCount) *
- 100;
- const rejectionCount =
- (workoutObjection?.data.rejectionCount / workoutObjection?.data.headCount) *
- 100;
- if (appovalCount > 100 || rejectionCount > 100) {
- appovalCount === 100 || rejectionCount === 100;
- }
return (
-
-
-
-
- {workspaceConfirmationDetail?.data.nickname}
-
-
- {workspaceConfirmationDetail?.data.loginId}
-
-
-
-
-
- {workspaceConfirmationDetail?.data.comment}
-
-
- {workspaceConfirmationDetail?.data.workoutConfirmationImageUrl ===
- '' ? (
-
- ) : (
- src}
- loading='lazy'
- sizes='360px'
- fill
- />
- )}
-
-
+
+
{/* 이의 신청 팝업창 */}
);
diff --git a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceHistory/page.tsx b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceHistory/page.tsx
index 4171dee..195529c 100644
--- a/src/app/(afterLogin)/workspace/[workspaceId]/workspaceHistory/page.tsx
+++ b/src/app/(afterLogin)/workspace/[workspaceId]/workspaceHistory/page.tsx
@@ -4,8 +4,6 @@ import Image from 'next/image';
import { useQuery } from '@tanstack/react-query';
import { useSearchParams } from 'next/navigation';
-import noGroup from '@/../public/svgs/noGroup.svg';
-
import { workspaceHistoryDataConst } from '@/constants/queryKey';
import { workspaceHistorys } from '@/api/workspace';
@@ -17,6 +15,8 @@ import useWorkoutHistoryIds from '@/hooks/workoutHistory/useWorkoutHistoryIds';
import useWorkoutIdFromParams from '@/hooks/workoutHistory/useWorkoutIdFromParams';
import type { THistorys, TQueryTypes } from '@/types/workspaceHistory';
+import NoDataUI from '../../_components/NoDataUI';
+import ScrollTop from '../workspaceConfirmation/_components/ScrollTop';
function useUserInfo(): TQueryTypes {
const searchParams = useSearchParams();
@@ -58,6 +58,7 @@ function Page() {
return (
+
'}
{workspaceHistoryDatas?.data.workoutHistories.length === 0 ? (
-
-
-
- 아직 운동 히스토리가 없습니다.
-
-
+
) : (
{workspaceHistoryDatas?.data.workoutHistories.map(
diff --git a/src/app/(afterLogin)/workspace/_components/NoDataUI.tsx b/src/app/(afterLogin)/workspace/_components/NoDataUI.tsx
new file mode 100644
index 0000000..71b795b
--- /dev/null
+++ b/src/app/(afterLogin)/workspace/_components/NoDataUI.tsx
@@ -0,0 +1,16 @@
+import Image from 'next/image';
+
+import noGroup from '@/../public/svgs/noGroup.svg';
+
+interface INoDataUI {
+ content: string;
+}
+
+export default function NoDataUI({ content }: INoDataUI) {
+ return (
+
+
+ {content}
+
+ );
+}
diff --git a/src/types/workoutConfirmation.ts b/src/types/workoutConfirmation.ts
index 37ba7ae..3bad659 100644
--- a/src/types/workoutConfirmation.ts
+++ b/src/types/workoutConfirmation.ts
@@ -17,3 +17,24 @@ export interface IWorkoutConfirmationObjectionListPageProps {
voteCompletion: boolean;
workoutConfirmationId: number;
}
+
+export interface IWorkspaceConfirmationDetailProps {
+ comment: string;
+ loginId: string;
+ nickname: string;
+ objectionId: number | null;
+ profileImageUrl: any;
+ workoutConfirmationImageUrl: any;
+}
+
+export interface IWorkoutObjectionProps {
+ approvalCount: number;
+ confirmationCompletion: boolean | null;
+ deadline: string;
+ headCount: number;
+ inInProgress: boolean;
+ reason: string;
+ rejectionCount: number;
+ voteCompletion: boolean | null;
+ voteParticipationCount: number;
+}