Skip to content

Commit

Permalink
refactor: 모달 상태관리 코드 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
hyeonjinan096 committed Jul 9, 2024
1 parent 022b6f8 commit 86e68b7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 38 deletions.
5 changes: 0 additions & 5 deletions src/app/(post)/createPost/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Link from 'next/link';

import TopBar from '../../../components/Topbar';
import PostForm from './_components/PostForm';

Expand All @@ -9,9 +7,6 @@ const CreatePostPage = () => {
<TopBar.Container>
<TopBar.BackButton href='/' />
<TopBar.Title>투표 만들기</TopBar.Title>
<Link className=' font-title-1-md text-primary' href='/'>
<span>등록</span>
</Link>
</TopBar.Container>
<PostForm />
</>
Expand Down
39 changes: 30 additions & 9 deletions src/app/(post)/result/[postId]/_components/Posting/VoteForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,26 @@ import { useParams } from 'next/navigation';

import { useGetPostDetailAPI } from '@/src/apis/postDetail';
import { useGetVoteDetailAPI } from '@/src/apis/vote';
import FullImageModal from '@/src/components/FullImageModal';
import Icon from '@/src/components/Icon';
import ConfirmationModal from '@/src/components/Modal/ConfirmationModal';
import { cn } from '@/src/utils/cn';

import { useCreateVote } from '../../hooks/useCreateVote';
import useTerminateVote from '../../hooks/useTerminateVote';

type ImageModal = { isVisible: boolean; url: string };

const VoteForm = () => {
const [selectedOption, setSelectedOption] = useState<null | number>(null);
const [isShowModal, setIsShowModal] = useState(false);

const [isShowTerminateModal, setIsShowTerminateModal] = useState(false);

const [imageModalState, setImageModalState] = useState<ImageModal>({
isVisible: false,
url: '',
});

const { postId } = useParams() as { postId: string };
const { voteOptions, voteTitle, totalNumber, voteId } =
useGetVoteDetailAPI(postId);
Expand All @@ -39,13 +49,14 @@ const VoteForm = () => {
terminateVote();
};

const handelCloseModal = () => {
setIsShowModal(false);
const handleTerminateModal = (isVisible: boolean) => () => {
setIsShowTerminateModal(isVisible);
};

const handleOpenModal = () => {
setIsShowModal(true);
};
const handleImageModal =
(state: { isVisible: boolean; url: string }) => () => {
setImageModalState(state);
};

return (
<div className='flex items-center justify-center rounded-[8px] bg-gray-accent1'>
Expand Down Expand Up @@ -85,6 +96,10 @@ const VoteForm = () => {
width={24}
height={24}
className='absolute right-[10px] max-h-[24px] max-w-[24px] rounded-[4px]'
onClick={handleImageModal({
isVisible: true,
url: voteOptionImageUrl,
})}
/>
)}
</label>
Expand All @@ -94,7 +109,7 @@ const VoteForm = () => {
{isAuthor ? (
<button
className='font-title-1-md w-full rounded-lg bg-sub py-3 text-primary'
onClick={handleOpenModal}
onClick={handleTerminateModal(true)}
>
투표 종료하기
</button>
Expand All @@ -112,11 +127,17 @@ const VoteForm = () => {
)}
</div>
<ConfirmationModal
isShow={isShowModal}
isShow={isShowTerminateModal}
description='투표를 종료하시겠습니까?'
onClose={handelCloseModal}
onClose={handleTerminateModal(false)}
onConfirm={handleTerminateVote}
/>
<FullImageModal
isShow={imageModalState.isVisible}
onClose={handleImageModal({ isVisible: false, url: '' })}
imageUrl={imageModalState.url}
altText='항목 상세 이미지'
/>
</div>
);
};
Expand Down
41 changes: 21 additions & 20 deletions src/app/(post)/result/[postId]/_components/Posting/VoteResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import { useParams } from 'next/navigation';

import { useGetPostDetailAPI } from '@/src/apis/postDetail';
import { useGetVoteDetailAPI } from '@/src/apis/vote';
import FullScreenModal from '@/src/components/FullScreenModal';
import FullImageModal from '@/src/components/FullImageModal';
import Icon from '@/src/components/Icon';
import { cn } from '@/src/utils/cn';

type ImageModal = { isVisible: boolean; url: string };

const VoteResult = () => {
const { postId } = useParams() as { postId: string };
const {
Expand All @@ -22,18 +24,17 @@ const VoteResult = () => {
} = useGetVoteDetailAPI(postId);

const maxCount = Math.max(...voteOptions.map(({ count }) => count));
const [isShowModal, setIsShowModal] = useState<boolean>(false);
const [selectedImage, setSelectedImage] = useState<string>('');
const { isAuthor } = useGetPostDetailAPI(postId);

const showImageModal = (url: string) => {
setIsShowModal(true);
setSelectedImage(url);
};
const [imageModalState, setImageModalState] = useState<ImageModal>({
isVisible: false,
url: '',
});

const handelCloseModal = () => {
setIsShowModal(false);
};
const handleImageModal =
(state: { isVisible: boolean; url: string }) => () => {
setImageModalState(state);
};

return (
<div className='flex items-center justify-center rounded-[8px] bg-gray-accent1'>
Expand Down Expand Up @@ -102,9 +103,10 @@ const VoteResult = () => {
width={24}
height={24}
className='absolute right-[10px] z-0 max-h-[24px] max-w-[24px] rounded-[4px]'
onClick={() => {
showImageModal(voteOptionImageUrl);
}}
onClick={handleImageModal({
isVisible: true,
url: voteOptionImageUrl,
})}
/>
)}
</div>
Expand All @@ -116,13 +118,12 @@ const VoteResult = () => {
{isTerminated ? '종료된 투표입니다.' : '투표 완료'}
</button>
</div>
<FullScreenModal show={isShowModal} onClose={handelCloseModal}>
<div className='flex h-full w-full items-center'>
<div className='relative h-[260px] w-full'>
<Image src={selectedImage} alt='로고' fill />
</div>
</div>
</FullScreenModal>
<FullImageModal
isShow={imageModalState.isVisible}
onClose={handleImageModal({ isVisible: false, url: '' })}
imageUrl={imageModalState.url}
altText='항목 상세 이미지'
/>
</div>
);
};
Expand Down
34 changes: 34 additions & 0 deletions src/components/FullImageModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Image from 'next/image';

import FullModal from '../FullModal';

interface FullImageModalProps {
isShow: boolean;
onClose: () => void;
imageUrl: string;
altText: string;
}

const FullImageModal = ({
isShow,
onClose,
imageUrl,
altText,
}: FullImageModalProps) => {
return (
<FullModal show={isShow} onClose={onClose}>
<div className='flex h-full w-full items-center'>
<div className='relative h-[260px] w-full'>
<Image
src={imageUrl}
alt={altText}
layout='fill'
objectFit='contain'
/>
</div>
</div>
</FullModal>
);
};

export default FullImageModal;
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ import { cn } from '@/src/utils/cn';
import Icon from '../Icon';
import TopBar from '../Topbar';

interface FullScreenModalProps {
interface FullModalProps {
show: boolean;
onClose: () => void;
backgroundClassName?: string;
contentClassName?: string;
}

const FullScreenModal = ({
const FullModal = ({
show,
onClose,
backgroundClassName,
children,
}: PropsWithChildren<FullScreenModalProps>) => {
}: PropsWithChildren<FullModalProps>) => {
const modalRoot = document.getElementById('layout-Root');

if (!show || !modalRoot) {
Expand All @@ -42,4 +42,4 @@ const FullScreenModal = ({
);
};

export default FullScreenModal;
export default FullModal;

0 comments on commit 86e68b7

Please sign in to comment.