From ce7bd0d77e4e4cf0ee72289fcde88123c22f9301 Mon Sep 17 00:00:00 2001 From: LEE BO HYUN <92661884+frombozztoang@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:06:31 +0900 Subject: [PATCH] =?UTF-8?q?feat:#9=20modal=20nextui=20library=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/atoms/letter/Letter.tsx | 15 +-- src/components/molecules/modal/ModalView.tsx | 98 +++++++++++++--- .../modal/auth/AuthCheckingModalContent.tsx | 33 ++++++ .../modal/auth/AuthModal.stories.tsx | 18 +++ .../organisms/modal/auth/AuthModal.tsx | 69 +++++++++++ .../organisms/modal/letter/DetailModal.tsx | 15 +++ .../modal/letter/WriteModal.stories.tsx | 16 +++ .../organisms/modal/letter/WriteModal.tsx | 24 ++++ .../WriteModalContent.tsx} | 2 +- src/components/templates/main/MainDetail.tsx | 108 ++++++++++++++---- tailwind.config.ts | 12 +- 11 files changed, 357 insertions(+), 53 deletions(-) create mode 100644 src/components/organisms/modal/auth/AuthCheckingModalContent.tsx create mode 100644 src/components/organisms/modal/auth/AuthModal.stories.tsx create mode 100644 src/components/organisms/modal/auth/AuthModal.tsx create mode 100644 src/components/organisms/modal/letter/DetailModal.tsx create mode 100644 src/components/organisms/modal/letter/WriteModal.stories.tsx create mode 100644 src/components/organisms/modal/letter/WriteModal.tsx rename src/components/organisms/modal/{LetterModalContent.tsx => letter/WriteModalContent.tsx} (93%) diff --git a/src/components/atoms/letter/Letter.tsx b/src/components/atoms/letter/Letter.tsx index 9f01162..e4dc4aa 100644 --- a/src/components/atoms/letter/Letter.tsx +++ b/src/components/atoms/letter/Letter.tsx @@ -1,15 +1,10 @@ -import Image, { StaticImageData } from "next/image"; +import { COLORS } from "@/constants/letterColors"; +import { letterProps } from "@/types/Letter"; +import Image from "next/image"; import React from "react"; import trash from "../../../../public/icons/trash.png"; -interface LetterProps { - letterText: string; - user?: { name: string; profileImg: StaticImageData | string }; - backgroundColor: string; - isMine: boolean; -} - -const Letter = ({ letterText, user, backgroundColor, isMine }: LetterProps) => { +const Letter = ({ letterText, user, backgroundColor, isMine }: letterProps) => { const trimmedText = letterText.length > 140 ? `${letterText.slice(0, 140)}... 더보기` @@ -18,7 +13,7 @@ const Letter = ({ letterText, user, backgroundColor, isMine }: LetterProps) => {
diff --git a/src/components/molecules/modal/ModalView.tsx b/src/components/molecules/modal/ModalView.tsx index 34a06ea..45d41c1 100644 --- a/src/components/molecules/modal/ModalView.tsx +++ b/src/components/molecules/modal/ModalView.tsx @@ -1,23 +1,93 @@ +import { modalProps } from "@/types/Modal"; +import { + Button, + Modal, + ModalBody, + ModalContent, + ModalFooter, +} from "@nextui-org/react"; import React, { HTMLAttributes } from "react"; -interface Props extends HTMLAttributes { +interface modalViewProps extends HTMLAttributes { children?: React.ReactNode; -} - -const ModalView = ({ children, ...props }: Props) => { - // 모달 클릭 시 백드롭에도 터치 이벤트가 전파되는 것을 막기 위함 - const handleClickModalView = ( - e: React.MouseEvent - ) => { - e.stopPropagation(); + isOpen: boolean; + onOpen: () => void; + onOpenChange: (isOpen: boolean) => void; + noBtn?: { + info: string; + handler?: () => void; }; + yesBtn?: { + info: string; + handler?: () => void; + }; +} +const ModalView = ({ + children, + isOpen, + onOpen, + onOpenChange, + noBtn, + yesBtn, + ...props +}: modalViewProps) => { return ( -
-
- {children} -
-
+ + + {(onClose) => ( +
+ {children} + + {noBtn && yesBtn && ( +
+ + +
+ )} + {!noBtn && yesBtn && ( +
+ +
+ )} +
+
+ )} +
+
); }; diff --git a/src/components/organisms/modal/auth/AuthCheckingModalContent.tsx b/src/components/organisms/modal/auth/AuthCheckingModalContent.tsx new file mode 100644 index 0000000..fffb361 --- /dev/null +++ b/src/components/organisms/modal/auth/AuthCheckingModalContent.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +interface authCheckingModalProps { + name: string; + major: string; + studentId: string; +} + +const AuthCheckingModal = ({ + name, + major, + studentId, +}: authCheckingModalProps) => { + return ( +
+

+ 올바른 정보가 맞는지 확인해 주세요. +

+

이름: {name}

+

+ 학과/학번: {major} {studentId} +

+

+ * 정보가 다르다면 관리자에게 문의해 주세요. +

+

+ mjuletter@gmail.com +

+
+ ); +}; + +export default AuthCheckingModal; diff --git a/src/components/organisms/modal/auth/AuthModal.stories.tsx b/src/components/organisms/modal/auth/AuthModal.stories.tsx new file mode 100644 index 0000000..04448e5 --- /dev/null +++ b/src/components/organisms/modal/auth/AuthModal.stories.tsx @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import AuthModal from "./AuthModal"; + +const meta: Meta = { + title: "components/organisms/modal/AuthModal", + component: AuthModal, + tags: ["autodocs"], + argTypes: {}, +}; + +export default meta; + +type Story = StoryObj; + +export const Primary: Story = { + args: {}, +}; diff --git a/src/components/organisms/modal/auth/AuthModal.tsx b/src/components/organisms/modal/auth/AuthModal.tsx new file mode 100644 index 0000000..27ad753 --- /dev/null +++ b/src/components/organisms/modal/auth/AuthModal.tsx @@ -0,0 +1,69 @@ +import ModalView from "@/components/molecules/modal/ModalView"; +import { AuthModalProps } from "@/types/Modal"; +import { useDisclosure } from "@nextui-org/react"; +import React from "react"; +import AuthCheckingModalContent from "./AuthCheckingModalContent"; + +const AuthModal = ({ authStatus }: AuthModalProps) => { + const { isOpen, onOpen, onOpenChange } = useDisclosure(); + const handleYesClick = () => { + console.log("Yes button clicked!"); + }; + const handleNoClick = () => { + console.log("No button clicked!"); + }; + + return ( + <> + {authStatus === "proceeding" && ( + + // + // + // + )} + {authStatus === "checking" && ( + + } + yesBtn={{ info: "확인", handler: handleYesClick }} + noBtn={{ info: "취소", handler: handleNoClick }} + /> + // + // + // } + // yesBtn={{ info: "확인", handler: handleYesClick }} + // noBtn={{ info: "취소", handler: handleNoClick }} + // /> + // + )} + {authStatus === "failed" && ( + + // + // + // + )} + + ); +}; + +export default AuthModal; diff --git a/src/components/organisms/modal/letter/DetailModal.tsx b/src/components/organisms/modal/letter/DetailModal.tsx new file mode 100644 index 0000000..e0a4536 --- /dev/null +++ b/src/components/organisms/modal/letter/DetailModal.tsx @@ -0,0 +1,15 @@ +import { StaticImageData } from "next/image"; +import React from "react"; + +interface DetailModalProps { + letterText: string; + user?: { name: string; profileImg: StaticImageData | string }; + backgroundColor: string; + isMine: boolean; +} + +const DetailModal = () => { + return
DetailModal
; +}; + +export default DetailModal; diff --git a/src/components/organisms/modal/letter/WriteModal.stories.tsx b/src/components/organisms/modal/letter/WriteModal.stories.tsx new file mode 100644 index 0000000..2b6ea34 --- /dev/null +++ b/src/components/organisms/modal/letter/WriteModal.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import WriteModal from "./WriteModal"; +const meta: Meta = { + title: "components/organisms/modal/WriteModal", + component: WriteModal, + tags: ["autodocs"], + argTypes: {}, +}; + +export default meta; + +type Story = StoryObj; + +export const Primary: Story = { + args: {}, +}; diff --git a/src/components/organisms/modal/letter/WriteModal.tsx b/src/components/organisms/modal/letter/WriteModal.tsx new file mode 100644 index 0000000..a1c3a22 --- /dev/null +++ b/src/components/organisms/modal/letter/WriteModal.tsx @@ -0,0 +1,24 @@ +import ModalView from "@/components/molecules/modal/ModalView"; +import { COLORS } from "@/constants/letterColors"; +import React, { useState } from "react"; +import LetterModalContent from "./WriteModalContent"; + +const WriteModal = () => { + const [selectedColor, setSelectedColor] = + useState("red"); + const [isChecked, setIsChecked] = useState(false); + const [textAreaValue, setTextAreaValue] = useState(""); + + return ( + + ); +}; + +export default WriteModal; diff --git a/src/components/organisms/modal/LetterModalContent.tsx b/src/components/organisms/modal/letter/WriteModalContent.tsx similarity index 93% rename from src/components/organisms/modal/LetterModalContent.tsx rename to src/components/organisms/modal/letter/WriteModalContent.tsx index 5165d2a..be042d6 100644 --- a/src/components/organisms/modal/LetterModalContent.tsx +++ b/src/components/organisms/modal/letter/WriteModalContent.tsx @@ -20,7 +20,7 @@ const LetterModalContent = ({ setSelectedColor, }: letterModalContentProps) => { return ( -
+
롤링페이퍼로 마음을 전해보세요.
diff --git a/src/components/templates/main/MainDetail.tsx b/src/components/templates/main/MainDetail.tsx index d4bfd9a..af0d834 100644 --- a/src/components/templates/main/MainDetail.tsx +++ b/src/components/templates/main/MainDetail.tsx @@ -1,22 +1,32 @@ "use client"; -import DetailProfile from "../../atoms/profile/detailProfile/DetailProfile"; import React, { useState } from "react"; import test from "../../../../public/icons/testProfile.png"; -import Letter from "../../atoms/letter/Letter"; -import BottomFixedBtn from "../../atoms/button/bottomFixed/BottomFixed"; -import LetterModal from "@/components/organisms/modal/LetterModal"; +import WriteModal from "@/components/organisms/modal/letter/WriteModal"; +import { useDisclosure } from "@nextui-org/react"; +import ModalView from "@/components/molecules/modal/ModalView"; +import BottomFixedBtn from "@/components/atoms/button/bottomFixed/BottomFixed"; +import Letter from "@/components/atoms/letter/Letter"; +import DetailProfile from "@/components/atoms/profile/detailProfile/DetailProfile"; const MainDetail = () => { - const [isLetterModalOpened, setLetterModalOpened] = useState(false); + const { isOpen, onOpen, onOpenChange } = useDisclosure(); + const handleYesClick = () => { + console.log("Yes button clicked!"); + }; + const handleNoClick = () => { + console.log("No button clicked!"); + }; return ( <> - {isLetterModalOpened && ( - - )} -
+ } + yesBtn={{ info: "확인", handler: handleYesClick }} + noBtn={{ info: "취소", handler: handleNoClick }} + /> +
{ letterText={ "안!~!~!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸지마~~!~!~!~!~!~!~!" } - backgroundColor={"#F0D36D"} + backgroundColor="green" + isMine={false} + /> +
{" "} +
+
@@ -41,25 +60,42 @@ const MainDetail = () => { letterText={ "안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지마~~!~!~!~!~!~!~!" } - backgroundColor={"#F39889"} + backgroundColor="blue" isMine={false} />
-
+
{" "} +
+
+
+ +
{" "}
@@ -67,7 +103,7 @@ const MainDetail = () => { letterText={ "안!~!~!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸!~!~!안녕 녕 말걸지마~~!~!~!~!~!~!~!" } - backgroundColor={"#F0D36D"} + backgroundColor="blue" isMine={false} />
@@ -76,18 +112,42 @@ const MainDetail = () => { letterText={ "안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지안녕 말걸지마~~!~!~!~!~!~!~!" } - backgroundColor={"#F39889"} + backgroundColor="green" + isMine={false} + /> +
{" "} +
+ +
+
+ +
{" "} +
+
-
setLetterModalOpened(!isLetterModalOpened)} - className="m-16 fixed bottom-0 right-0" - > +
+
); diff --git a/tailwind.config.ts b/tailwind.config.ts index a6c5dcf..902ffc9 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,3 +1,4 @@ +import { nextui } from "@nextui-org/react"; import type { Config } from "tailwindcss"; const px0_10 = { ...Array.from(Array(11)).map((_, i) => `${i}px`) } as any; @@ -13,6 +14,7 @@ const config: Config = { "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + "./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}", ], theme: { extend: { @@ -49,12 +51,14 @@ const config: Config = { tablet: "1000px", }, zIndex: { - modal: "100", - navigatoinList: "200", - letterModal: "200", + modal: "30", + navigatoinList: "50", + letterModal: "30", + header: "10", }, }, }, - plugins: [require("tailwindcss")], + darkMode: "class", + plugins: [require("tailwindcss"), nextui()], }; export default config;