From a9719cb4b9bd7af1ff6d04e2d76a107ae17f833b Mon Sep 17 00:00:00 2001 From: llddang <77055208+llddang@users.noreply.github.com> Date: Thu, 9 May 2024 21:21:16 +0900 Subject: [PATCH] =?UTF-8?q?Feature/#201=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=EC=82=AD=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 스터디 종료/삭제 관련 모달 props 타입 정의 #201 * feat: 스터디 삭제 모달 구현 #201 * feat: 스터디 종료 모달 구현 #201 * feat: 스터디 종료, 삭제 버튼 추가 #201 * refact: studyControlPanel 분리 #201 * refact: 큰 따옴표를 표시하는 방식 수정 #201 * refact: 큰 따옴표를 표시하는 방식 수정 #201 --- .../team/[teamId]/study/[studyId]/page.tsx | 102 ++++++++++-------- .../study/Modal/DeleteStudyModal/index.tsx | 30 ++++++ .../study/Modal/TerminateStudyModal/index.tsx | 32 ++++++ src/containers/study/Modal/types.ts | 11 ++ .../study/StudyControlPanel/index.tsx | 40 +++++++ .../study/StudyControlPanel/types.ts | 4 + 6 files changed, 177 insertions(+), 42 deletions(-) create mode 100644 src/containers/study/Modal/DeleteStudyModal/index.tsx create mode 100644 src/containers/study/Modal/TerminateStudyModal/index.tsx create mode 100644 src/containers/study/Modal/types.ts create mode 100644 src/containers/study/StudyControlPanel/index.tsx create mode 100644 src/containers/study/StudyControlPanel/types.ts diff --git a/src/app/team/[teamId]/study/[studyId]/page.tsx b/src/app/team/[teamId]/study/[studyId]/page.tsx index c6a284c0..d17a5a7b 100644 --- a/src/app/team/[teamId]/study/[studyId]/page.tsx +++ b/src/app/team/[teamId]/study/[studyId]/page.tsx @@ -1,12 +1,18 @@ +'use client'; + import { Flex, Grid, IconButton, Text, Link } from '@chakra-ui/react'; import NextLink from 'next/link'; +import { useState } from 'react'; import { MdOutlineArrowForwardIos } from 'react-icons/md'; import CurriculumCard from '@/components/CurriculumCard'; import StudyAssetCard from '@/components/StudyAssetCard'; import Title from '@/components/Title'; import Feed from '@/containers/study/Feed'; +import DeleteStudyModal from '@/containers/study/Modal/DeleteStudyModal'; +import TerminateStudyModal from '@/containers/study/Modal/TerminateStudyModal'; import Participant from '@/containers/study/Participant'; +import StudyControlPanel from '@/containers/study/StudyControlPanel'; import StudyInfoCard from '@/containers/study/StudyInfoCard'; import participantData from '@/mocks/participant'; import studyAssetCardData from '@/mocks/studyAssetCard'; @@ -15,51 +21,63 @@ import studyCardData from '@/mocks/studyCard'; const sampleStudy = studyCardData[0]; const Page = () => { + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [isTerminateModalOpen, setIsTerminateModalOpen] = useState(false); + return ( - - - - <StudyInfoCard - progress={sampleStudy.percent} - startAt={new Date(sampleStudy.startDate)} - endAt={new Date(sampleStudy.endDate)} - /> - </Flex> - <Grid gap="4" templateColumns={{ base: '', xl: '2fr 1fr' }} w="100%"> - <Flex direction="column" rowGap={{ base: '6', '2xl': '12' }}> - <CurriculumCard /> - <Flex align="right" direction="column" rowGap="3"> - <Link as={NextLink} gap="3" display="flex" w="fit-content" ml="auto" href="/"> - <IconButton - fontSize="16px" - aria-label="" - icon={<MdOutlineArrowForwardIos />} - isRound - size="icon_sm" - variant="icon_orange" - /> - <Text>전체 보기</Text> - </Link> - <Grid gap="2" templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(4, 1fr)' }}> - {studyAssetCardData.map((data) => ( - <StudyAssetCard - key={data.title} - title={data.title} - content={data.content} - date={data.date} - bookmark={data.bookmark} - img={data.img} + <> + <Flex direction="column" gap="0" w="100%" p="8"> + <Flex justify="space-between" w="100%"> + <Title name={sampleStudy.name} description={sampleStudy.description} /> + <StudyInfoCard + progress={sampleStudy.percent} + startAt={new Date(sampleStudy.startDate)} + endAt={new Date(sampleStudy.endDate)} + /> + </Flex> + <StudyControlPanel terminateModalOpen={setIsTerminateModalOpen} deleteModalOpen={setIsDeleteModalOpen} /> + <Grid gap="4" templateColumns={{ base: '', xl: '2fr 1fr' }} w="100%"> + <Flex direction="column" rowGap={{ base: '6', '2xl': '12' }}> + <CurriculumCard /> + <Flex align="right" direction="column" rowGap="3"> + <Link as={NextLink} gap="3" display="flex" w="fit-content" ml="auto" href="/"> + <IconButton + fontSize="16px" + aria-label="" + icon={<MdOutlineArrowForwardIos />} + isRound + size="icon_sm" + variant="icon_orange" /> - ))} - </Grid> + <Text>전체 보기</Text> + </Link> + <Grid gap="2" templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(4, 1fr)' }}> + {studyAssetCardData.map((data) => ( + <StudyAssetCard + key={data.title} + title={data.title} + content={data.content} + date={data.date} + bookmark={data.bookmark} + img={data.img} + /> + ))} + </Grid> + </Flex> </Flex> - </Flex> - <Flex direction="column" rowGap={{ base: '6', '2xl': '12' }}> - <Feed /> - <Participant participantInfos={participantData} /> - </Flex> - </Grid> - </Flex> + <Flex direction="column" rowGap={{ base: '6', '2xl': '12' }}> + <Feed /> + <Participant participantInfos={participantData} /> + </Flex> + </Grid> + </Flex> + <TerminateStudyModal + studyName={sampleStudy.name} + isOpen={isTerminateModalOpen} + setIsOpen={setIsTerminateModalOpen} + /> + <DeleteStudyModal studyName={sampleStudy.name} isOpen={isDeleteModalOpen} setIsOpen={setIsDeleteModalOpen} /> + </> ); }; diff --git a/src/containers/study/Modal/DeleteStudyModal/index.tsx b/src/containers/study/Modal/DeleteStudyModal/index.tsx new file mode 100644 index 00000000..22440ab6 --- /dev/null +++ b/src/containers/study/Modal/DeleteStudyModal/index.tsx @@ -0,0 +1,30 @@ +import { Text } from '@chakra-ui/react'; + +import ConfirmModal from '@/components/Modal/ConfirmModal'; + +import { DeleteStudyModalProps } from '../types'; + +const DeleteStudyModal = ({ studyName, isOpen, setIsOpen }: DeleteStudyModalProps) => { + const handleClickDelete = () => { + // TODO - API 연결 + setIsOpen(false); + }; + + return ( + <ConfirmModal + isOpen={isOpen} + onClose={() => setIsOpen(false)} + title="스터디 삭제" + confirmButtonText="삭제" + onConfirmButtonClick={handleClickDelete} + > + <Text align="center"> + 삭제된 스터디는 되돌릴 수 없습니다. + <br /> + {`"${studyName}"을 삭제하시겠습니까?`} + </Text> + </ConfirmModal> + ); +}; + +export default DeleteStudyModal; diff --git a/src/containers/study/Modal/TerminateStudyModal/index.tsx b/src/containers/study/Modal/TerminateStudyModal/index.tsx new file mode 100644 index 00000000..1c2131a4 --- /dev/null +++ b/src/containers/study/Modal/TerminateStudyModal/index.tsx @@ -0,0 +1,32 @@ +import { Text } from '@chakra-ui/react'; + +import ConfirmModal from '@/components/Modal/ConfirmModal'; + +import { TerminateStudyModalProps } from '../types'; + +const TerminateStudyModal = ({ studyName, isOpen, setIsOpen }: TerminateStudyModalProps) => { + const handleClickTerminate = () => { + // TODO - API 연결 + setIsOpen(false); + }; + + return ( + <ConfirmModal + isOpen={isOpen} + onClose={() => setIsOpen(false)} + title="스터디 종료" + confirmButtonText="종료" + onConfirmButtonClick={handleClickTerminate} + > + <Text align="center"> + 스터디 종료시 수료증이 발급되며 + <br /> + 스터디 정보 수정 및 삭제가 불가능합니다. + <br /> + {`"${studyName}"을 종료하시겠습니까?`} + </Text> + </ConfirmModal> + ); +}; + +export default TerminateStudyModal; diff --git a/src/containers/study/Modal/types.ts b/src/containers/study/Modal/types.ts new file mode 100644 index 00000000..d8bdff37 --- /dev/null +++ b/src/containers/study/Modal/types.ts @@ -0,0 +1,11 @@ +export interface TerminateStudyModalProps { + studyName: string; + isOpen: boolean; + setIsOpen: React.Dispatch<React.SetStateAction<boolean>>; +} + +export interface DeleteStudyModalProps { + studyName: string; + isOpen: boolean; + setIsOpen: React.Dispatch<React.SetStateAction<boolean>>; +} diff --git a/src/containers/study/StudyControlPanel/index.tsx b/src/containers/study/StudyControlPanel/index.tsx new file mode 100644 index 00000000..ce723eb1 --- /dev/null +++ b/src/containers/study/StudyControlPanel/index.tsx @@ -0,0 +1,40 @@ +import { Button, Flex } from '@chakra-ui/react'; + +import { StudyControlPanelProps } from './types'; + +const StudyControlPanel = ({ terminateModalOpen, deleteModalOpen }: StudyControlPanelProps) => { + return ( + <Flex gap="2" mb="8"> + <Button + w="fit-content" + px="4" + py="1" + color="white" + bg="orange_dark" + shadow="md" + _hover={{ bg: 'orange_dark' }} + aria-label="" + onClick={() => terminateModalOpen(true)} + size="xs" + > + 종료 + </Button> + <Button + w="fit-content" + px="4" + py="1" + color="black" + bg="white" + shadow="md" + _hover={{ bg: 'white' }} + aria-label="" + onClick={() => deleteModalOpen(true)} + size="xs" + > + 삭제 + </Button> + </Flex> + ); +}; + +export default StudyControlPanel; diff --git a/src/containers/study/StudyControlPanel/types.ts b/src/containers/study/StudyControlPanel/types.ts new file mode 100644 index 00000000..6c8a4a24 --- /dev/null +++ b/src/containers/study/StudyControlPanel/types.ts @@ -0,0 +1,4 @@ +export interface StudyControlPanelProps { + terminateModalOpen: React.Dispatch<React.SetStateAction<boolean>>; + deleteModalOpen: React.Dispatch<React.SetStateAction<boolean>>; +}