From da7b63ebd7be9560f5bf567b2af752d89e06db0f Mon Sep 17 00:00:00 2001
From: harry kim <73218463+hanyugeon@users.noreply.github.com>
Date: Thu, 8 Aug 2024 15:27:52 +0900
Subject: [PATCH] =?UTF-8?q?[#679]=20[=EB=AA=A8=EC=9E=84=20=EC=83=9D?=
=?UTF-8?q?=EC=84=B1]=20=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20?=
=?UTF-8?q?=ED=8D=BC=EB=84=90=20=EC=A2=85=EB=A3=8C=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EC=B6=94=EA=B0=80=20(#683)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: 모임생성 퍼널 종료 버튼 추가
* feat: FunnelBottomActionButton 합성 컴포넌트 작성
* feat: FunnelBottomActionButton 적용
* feat: 모임 생성 종료 Modal 작성
* fix: 모임 생성 모달 종료 옵션을 router.push에서 router.back으로 수정
* feat: StickyFooter 작성
* refactor: 기존의 BottomActionButtond을 StickyFooter로 교체
* fix: LoginBottomActionButton 내부의 link 태그 위치 수정
---
src/app/book/[bookId]/page.tsx | 11 +--
src/app/group/[groupId]/join/page.tsx | 10 ++-
.../create/CreateBookGroupFunnel.tsx | 67 ++++++++++++++-----
.../steps/EnterTitleStep/EnterTitleStep.tsx | 30 ++++++---
.../SelectJoinTypeStep/SelectJoinTypeStep.tsx | 30 ++++++---
.../steps/SetUpDetailStep/SetUpDetailStep.tsx | 29 +++++---
.../bookGroup/detail/JoinBookGroupButton.tsx | 19 ++++--
src/components/common/BottomActionButton.tsx | 23 -------
.../common/LoginBottomActionButton.tsx | 11 +--
src/components/common/StickyFooter.tsx | 44 ++++++++++++
.../common/BottomActionButton.stories.tsx | 28 --------
src/stories/common/StickyFooter.stories.tsx | 55 +++++++++++++++
12 files changed, 248 insertions(+), 109 deletions(-)
delete mode 100644 src/components/common/BottomActionButton.tsx
create mode 100644 src/components/common/StickyFooter.tsx
delete mode 100644 src/stories/common/BottomActionButton.stories.tsx
create mode 100644 src/stories/common/StickyFooter.stories.tsx
diff --git a/src/app/book/[bookId]/page.tsx b/src/app/book/[bookId]/page.tsx
index 57f4d2ed..166320fb 100644
--- a/src/app/book/[bookId]/page.tsx
+++ b/src/app/book/[bookId]/page.tsx
@@ -16,12 +16,13 @@ import { SERVICE_ERROR_MESSAGE } from '@/constants';
import Skeleton from '@/components/common/Skeleton';
import SSRSafeSuspense from '@/components/common/SSRSafeSuspense';
import TopNavigation from '@/components/common/TopNavigation';
-import BottomActionButton from '@/components/common/BottomActionButton';
+import StickyFooter from '@/components/common/StickyFooter';
import LoginBottomActionButton from '@/components/common/LoginBottomActionButton';
import CommentDrawer from '@/components/comment/CommentDrawer';
import BackButton from '@/components/common/BackButton';
import BookInfo, { BookInfoSkeleton } from '@/components/book/detail/BookInfo';
import BookCommentList from '@/components/comment/BookCommentList';
+import Button from '@/components/common/Button';
const BookDetailPage = ({
params: { bookId },
@@ -125,9 +126,11 @@ const AddBookCommentButton = ({ bookId }: { bookId: APIBook['bookId'] }) => {
return (
<>
-
- 코멘트 작성하기
-
+
+
+
{
- 제출하기
+
+
+
+
);
};
diff --git a/src/components/bookGroup/create/CreateBookGroupFunnel.tsx b/src/components/bookGroup/create/CreateBookGroupFunnel.tsx
index fa14f2e5..a760f2fe 100644
--- a/src/components/bookGroup/create/CreateBookGroupFunnel.tsx
+++ b/src/components/bookGroup/create/CreateBookGroupFunnel.tsx
@@ -7,14 +7,17 @@ import type { CreateBookGroupFormValues } from '@/components/bookGroup/create/ty
import useCreateBookGroupMutation from '@/queries/group/useCreateBookGroupMutation';
import { useFunnel } from '@/hooks/useFunnel';
+import useDisclosure from '@/hooks/useDisclosure';
import useToast from '@/components/common/Toast/useToast';
import { getTodayDate } from '@/utils/date';
import { isAxiosErrorWithCustomCode } from '@/utils/helpers';
import { SERVICE_ERROR_MESSAGE } from '@/constants';
-import { IconArrowLeft } from '@public/icons';
+import { IconClose } from '@public/icons';
import TopNavigation from '@/components/common/TopNavigation';
import Stepper from '@/components/common/Stepper';
+import Modal from '@/components/common/Modal';
+import Button from '@/components/common/Button';
import {
EnterTitleStep,
SelectBookStep,
@@ -34,7 +37,7 @@ const steps = [
{ label: '모임이름' },
{ label: '모임정보' },
{ label: '가입유형' },
-];
+] as const;
const CreateBookGroupFunnel = () => {
const router = useRouter();
@@ -44,6 +47,7 @@ const CreateBookGroupFunnel = () => {
const stepIndex = FUNNEL_STEPS.indexOf(currentStep);
const activeStep = stepIndex !== -1 ? stepIndex : 0;
+ const { isOpen, onOpen, onClose } = useDisclosure();
const { show: showToast } = useToast();
const { mutate } = useCreateBookGroupMutation();
@@ -58,16 +62,9 @@ const CreateBookGroupFunnel = () => {
},
});
- const handleBackButtonClick = () => {
- const currentStepIndex = FUNNEL_STEPS.indexOf(currentStep);
-
- if (currentStepIndex === 0 || currentStepIndex === -1) {
- router.back();
- } else {
- setStep(FUNNEL_STEPS[currentStepIndex - 1]);
- }
-
- return;
+ const handleCloseButtonClick = () => {
+ onClose();
+ router.back();
};
const handleCreateGroupSubmit: SubmitHandler<
@@ -118,10 +115,16 @@ const CreateBookGroupFunnel = () => {
-
+
+
+
@@ -138,16 +141,21 @@ const CreateBookGroupFunnel = () => {
setStep('EnterTitle')} />
- setStep('SetUpDetail')} />
+ setStep('SelectBook')}
+ onNextStep={() => setStep('SetUpDetail')}
+ />
setStep('SelectBook')}
+ onPrevStep={() => setStep('EnterTitle')}
onNextStep={() => setStep('SelectJoinType')}
+ goToSelectBookStep={() => setStep('SelectBook')}
/>
setStep('SetUpDetail')}
onSubmit={methods.handleSubmit(handleCreateGroupSubmit)}
/>
@@ -158,3 +166,32 @@ const CreateBookGroupFunnel = () => {
};
export default CreateBookGroupFunnel;
+
+const FunnelCloseModal = ({
+ isOpen,
+ onClose,
+ handleSubmit,
+}: {
+ isOpen: boolean;
+ onClose?: () => void;
+ handleSubmit?: () => void;
+}) => {
+ return (
+ onClose?.()}>
+
+ 독서모임 만들기를 그만할까요?
+
+ 작성한 내용은 저장되지 않아요.
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx b/src/components/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx
index 532808b5..52cd9aa9 100644
--- a/src/components/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx
+++ b/src/components/bookGroup/create/steps/EnterTitleStep/EnterTitleStep.tsx
@@ -6,9 +6,10 @@ import type { EnterTitleStepFormValues } from '@/components/bookGroup/create/typ
import useRemoveVerticalScroll from '@/hooks/useRemoveVerticalScroll';
import { TitleField } from '@/components/bookGroup/create/steps/EnterTitleStep/fields';
-import BottomActionButton from '@/components/common/BottomActionButton';
+import StickyFooter from '@/components/common/StickyFooter';
+import Button from '@/components/common/Button';
-const EnterTitleStep = ({ onNextStep }: MoveFunnelStepProps) => {
+const EnterTitleStep = ({ onPrevStep, onNextStep }: MoveFunnelStepProps) => {
const {
handleSubmit,
formState: { isValid },
@@ -25,13 +26,24 @@ const EnterTitleStep = ({ onNextStep }: MoveFunnelStepProps) => {
- onNextStep?.())}
- >
- 다음
-
+
+
+
+
);
};
diff --git a/src/components/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx b/src/components/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx
index 4ef50567..5fd12ea6 100644
--- a/src/components/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx
+++ b/src/components/bookGroup/create/steps/SelectJoinTypeStep/SelectJoinTypeStep.tsx
@@ -7,12 +7,13 @@ import {
JoinPasswordFieldset,
JoinTypeFieldset,
} from '@/components/bookGroup/create/steps/SelectJoinTypeStep/fields';
-import BottomActionButton from '@/components/common/BottomActionButton';
+import StickyFooter from '@/components/common/StickyFooter';
+import Button from '@/components/common/Button';
export type JoinTypeStepFieldName = keyof SelectJoinTypeStepFormValues;
export type JoinTypeStepFieldProp = { name: JoinTypeStepFieldName };
-const SelectJoinTypeStep = ({ onSubmit }: MoveFunnelStepProps) => {
+const SelectJoinTypeStep = ({ onPrevStep, onSubmit }: MoveFunnelStepProps) => {
const {
handleSubmit,
formState: { isValid },
@@ -35,13 +36,24 @@ const SelectJoinTypeStep = ({ onSubmit }: MoveFunnelStepProps) => {
-
- 독서모임 만들기
-
+
+
+
+
);
};
diff --git a/src/components/bookGroup/create/steps/SetUpDetailStep/SetUpDetailStep.tsx b/src/components/bookGroup/create/steps/SetUpDetailStep/SetUpDetailStep.tsx
index d0f08a6e..db8c6d54 100644
--- a/src/components/bookGroup/create/steps/SetUpDetailStep/SetUpDetailStep.tsx
+++ b/src/components/bookGroup/create/steps/SetUpDetailStep/SetUpDetailStep.tsx
@@ -7,7 +7,6 @@ import { MAX_MEMBER_COUNT_OPTIONS } from '@/constants';
import { getTodayDate } from '@/utils/date';
import withScrollLockOnFocus from '@/hocs/withScrollLockOnFocus';
-import BottomActionButton from '@/components/common/BottomActionButton';
import DatePicker from '@/components/common/DatePicker';
import ErrorMessage from '@/components/common/ErrorMessage';
import Input from '@/components/common/Input';
@@ -16,6 +15,8 @@ import RadioButton from '@/components/common/RadioButton';
import Switch from '@/components/common/Switch';
import TextArea from '@/components/common/TextArea';
import BookInfoCard from '@/components/bookGroup/BookInfoCard';
+import StickyFooter from '@/components/common/StickyFooter';
+import Button from '@/components/common/Button';
interface SetUpDetailStepProps extends MoveFunnelStepProps {
goToSelectBookStep?: () => void;
@@ -28,6 +29,7 @@ interface SetUpDetailStepProps extends MoveFunnelStepProps {
const SetUpDetailStep = ({
goToSelectBookStep,
+ onPrevStep,
onNextStep,
}: SetUpDetailStepProps) => {
const {
@@ -56,13 +58,24 @@ const SetUpDetailStep = ({
- onNextStep?.())}
- >
- 다음
-
+
+
+
+
);
};
diff --git a/src/components/bookGroup/detail/JoinBookGroupButton.tsx b/src/components/bookGroup/detail/JoinBookGroupButton.tsx
index 95457fe6..43191ff5 100644
--- a/src/components/bookGroup/detail/JoinBookGroupButton.tsx
+++ b/src/components/bookGroup/detail/JoinBookGroupButton.tsx
@@ -1,7 +1,8 @@
import { usePathname, useRouter } from 'next/navigation';
import useJoinBookGroup from '@/hooks/group/useJoinBookGroup';
-import BottomActionButton from '@/components/common/BottomActionButton';
+import StickyFooter from '@/components/common/StickyFooter';
+import Button from '@/components/common/Button';
const JoinBookGroupButton = ({ groupId }: { groupId: number }) => {
const router = useRouter();
@@ -24,16 +25,20 @@ const JoinBookGroupButton = ({ groupId }: { groupId: number }) => {
if (isExpired) {
return (
-
- 모임이 종료되었어요.
-
+
+
+
);
}
return (
-
- 참여하기
-
+
+
+
);
};
diff --git a/src/components/common/BottomActionButton.tsx b/src/components/common/BottomActionButton.tsx
deleted file mode 100644
index 1e5b3e5e..00000000
--- a/src/components/common/BottomActionButton.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ComponentPropsWithoutRef } from 'react';
-
-import Button from '@/components/common/Button';
-
-type BottomActionButtonProps = Omit<
- ComponentPropsWithoutRef,
- 'className'
->;
-
-const BottomActionButton = ({
- children,
- ...props
-}: BottomActionButtonProps) => {
- return (
-
- );
-};
-
-export default BottomActionButton;
diff --git a/src/components/common/LoginBottomActionButton.tsx b/src/components/common/LoginBottomActionButton.tsx
index d1241956..84ce687f 100644
--- a/src/components/common/LoginBottomActionButton.tsx
+++ b/src/components/common/LoginBottomActionButton.tsx
@@ -1,10 +1,13 @@
-import BottomActionButton from '@/components/common/BottomActionButton';
+import StickyFooter from '@/components/common/StickyFooter';
import LoginLink from '@/components/common/LoginLink';
+import Button from '@/components/common/Button';
const LoginBottomActionButton = () => (
-
- 로그인 및 회원가입
-
+
+
+
+
+
);
export default LoginBottomActionButton;
diff --git a/src/components/common/StickyFooter.tsx b/src/components/common/StickyFooter.tsx
new file mode 100644
index 00000000..bdc6f9a1
--- /dev/null
+++ b/src/components/common/StickyFooter.tsx
@@ -0,0 +1,44 @@
+import { useMemo } from 'react';
+
+type Direction = 'row' | 'column';
+
+type StickyFooterProps = {
+ children?: React.ReactNode;
+ direction?: Direction;
+ className?: string;
+};
+
+const getDirectionClass = (direction: Direction) => {
+ switch (direction) {
+ case 'row': {
+ return 'flex-row';
+ }
+ case 'column': {
+ return 'flex-col';
+ }
+ }
+};
+
+const BASE_STICKY_FOOTER_CLASSES =
+ 'fixed bottom-0 left-0 right-0 z-10 mx-auto flex w-full max-w-[43rem] gap-[0.8rem] bg-white px-[2.0rem] pb-[calc(env(safe-area-inset-bottom)+1.5rem)] pt-[1.5rem]';
+
+const StickyFooter = ({
+ children,
+ direction = 'row',
+ className,
+}: StickyFooterProps) => {
+ const directionClass = useMemo(
+ () => getDirectionClass(direction),
+ [direction]
+ );
+
+ return (
+
+ );
+};
+
+export default StickyFooter;
diff --git a/src/stories/common/BottomActionButton.stories.tsx b/src/stories/common/BottomActionButton.stories.tsx
deleted file mode 100644
index cee9d753..00000000
--- a/src/stories/common/BottomActionButton.stories.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import BottomActionButton from '@/components/common/BottomActionButton';
-import { Meta, StoryObj } from '@storybook/react';
-
-const meta: Meta = {
- title: 'Common/BottomActionButton',
- component: BottomActionButton,
- tags: ['autodocs'],
- parameters: {
- docs: {
- story: {
- inline: false,
- },
- },
- },
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {},
- render: () => (
- alert('click!')}>
- 다음
-
- ),
-};
diff --git a/src/stories/common/StickyFooter.stories.tsx b/src/stories/common/StickyFooter.stories.tsx
new file mode 100644
index 00000000..3ed9153c
--- /dev/null
+++ b/src/stories/common/StickyFooter.stories.tsx
@@ -0,0 +1,55 @@
+import Button from '@/components/common/Button';
+import StickyFooter from '@/components/common/StickyFooter';
+import { Meta, StoryObj } from '@storybook/react';
+
+const meta: Meta = {
+ title: 'Common/StickyFooter',
+ component: StickyFooter,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ story: {
+ inline: false,
+ },
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {},
+ render: () => (
+
+
+
+ ),
+};
+
+export const Row: Story = {
+ args: { direction: 'row' },
+ render: args => (
+
+
+
+
+ ),
+};
+
+export const Column: Story = {
+ args: { direction: 'column' },
+ render: args => (
+
+
+
+
+ ),
+};