Skip to content

Commit

Permalink
[#561] [모임 생성] 모임 상세 퍼널 개선 (#567)
Browse files Browse the repository at this point in the history
* feat: Input 컴포넌트 type="number" 일때 표시되는 버튼 제거

* refactor: 모임 상세 퍼널 스텝 스타일 수정, 성능개선, 기능 추가

- CustomMemberCountField의 Input 컴포넌트 after 스타일 추가
- watch를 useWatch()로 대체
- SetUpDetailStepValues에 FormValues 추가(book, queryKeyword)
- SelectedBookInfoField에 bookId 받을 수 있도록 수정

* refactor: 폴더 구조 변경

* fix: 모임 상세 퍼널 스토리 수정

* chore: /bookGroup/create/funnel/index.ts 변경사항 업데이트

- 불필요한 코드이지만 컨플릭트날것을 대비하여 우선 업데이트 합니다.
- 이후 Funnel 작업 시 제거합니다.

* fix: 모임상세 스텝 스토리 수정

- FormValues에 누락 된 customMemberCount 추가
- onNextStep 이벤트에 alert 추가

* fix: 불필요한 코드 삭제 및 수정
  • Loading branch information
hanyugeon authored May 6, 2024
1 parent cc2a3e3 commit d1271ed
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 72 deletions.
50 changes: 0 additions & 50 deletions src/stories/bookGroup/create/funnel/SetUpDetailStep.stories.tsx

This file was deleted.

72 changes: 72 additions & 0 deletions src/stories/bookGroup/create/steps/SetUpDetailStep.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { appLayoutMeta } from '@/stories/meta';
import { Meta, StoryObj } from '@storybook/react';
import { FormProvider, useForm } from 'react-hook-form';

import { getTodayDate } from '@/utils/date';

import {
SetUpDetailStep,
type SetUpDetailStepValues,
} from '@/v1/bookGroup/create/steps/SetUpDetailStep';

const meta: Meta<typeof SetUpDetailStep> = {
title: 'bookGroup/create/steps/SetUpDetailStep',
component: SetUpDetailStep,
...appLayoutMeta,
};

export default meta;

type Story = StoryObj<typeof SetUpDetailStep>;

const SetUpDetailForm = () => {
const methods = useForm<SetUpDetailStepValues>({
mode: 'all',
defaultValues: {
title: '',
book: {
bookId: 23,
},
introduce: '',
maxMemberCount: '',
customMemberCount: '',
startDate: getTodayDate(),
endDate: '',
isPublic: false,
},
});

const onNextStep = () => {
const {
book,
title,
introduce,
maxMemberCount,
customMemberCount,
startDate,
endDate,
isPublic,
} = methods.getValues();
alert(`
bookId: ${book.bookId},
title: ${title},
introduce: ${introduce},
maxMemberCount: ${maxMemberCount},
customMemberCount: ${customMemberCount},
startDate: ${startDate},
endDate: ${endDate},
isPublic: ${isPublic}`);
};

return (
<FormProvider {...methods}>
<form>
<SetUpDetailStep onNextStep={onNextStep} />
</form>
</FormProvider>
);
};

export const Default: Story = {
render: () => <SetUpDetailForm />,
};
13 changes: 13 additions & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
max-width: 43rem;
margin: 0 auto !important;
}

/* DatePicker Calendar 스타일링 */
input[type='date']::-webkit-calendar-picker-indicator {
background-image: none;
position: absolute;
Expand All @@ -42,6 +44,17 @@
padding: 0;
cursor: pointer;
}

/* Input type=number 버튼 제거 */
/* Chrome, Safari, Edge, Opera */
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* FireFox */
input[type='number'] {
-moz-appearance: textfield;
}
}

@layer utilities {
Expand Down
2 changes: 1 addition & 1 deletion src/v1/bookGroup/create/funnel/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// export { default as SelectBookStep } from './SelectBookStep';
export { default as SetUpDetailStep } from './SetUpDetailStep';
export { default as SetUpDetailStep } from '../steps/SetUpDetailStep/SetUpDetailStep';
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useFormContext } from 'react-hook-form';
import { useFormContext, useWatch } from 'react-hook-form';

import type { SearchedBookWithId } from '@/types/book';
import type { APICreateGroup } from '@/types/group';

import { getTodayDate } from '@/utils/date';
import { MAX_MEMBER_COUNT_OPTIONS } from '@/constants';
import { getTodayDate } from '@/utils/date';

import BottomActionButton from '@/v1/base/BottomActionButton';
import DatePicker from '@/v1/base/DatePicker';
Expand All @@ -13,35 +14,42 @@ import InputLength from '@/v1/base/InputLength';
import RadioButton from '@/v1/base/RadioButton';
import Switch from '@/v1/base/Switch';
import TextArea from '@/v1/base/TextArea';
import BookInfoCard from '../../BookInfoCard';
import BookInfoCard from '@/v1/bookGroup/BookInfoCard';

interface MoveFunnelStepProps {
onPrevStep?: () => void;
onNextStep?: () => void;
onSubmit?: () => void;
}

interface SetUpDetailStepValues
/**
* @todo
* Field 컴포넌트 분리
* goToSelectBookStep 받도록 수정
*/

export interface SetUpDetailStepValues
extends Pick<
APICreateGroup,
'bookId' | 'title' | 'introduce' | 'startDate' | 'endDate' | 'isPublic'
> {
book: SearchedBookWithId;
maxMemberCount: string;
customMemberCount: string;
}

const SetUpDetailStep = ({
// FIXME: goToSelectBookStep,
// goToSelectBookStep,
onNextStep,
}: MoveFunnelStepProps) => {
const { handleSubmit, getValues } = useFormContext<SetUpDetailStepValues>();

return (
<article className="flex flex-col gap-[3.2rem] overflow-y-scroll pb-[7rem]">
<TitleField name={'title'} />
<SelectedBookInfoField bookId={getValues('bookId')} />

<SelectedBookInfoField bookId={getValues('book')?.bookId} />
<IntroduceField name={'introduce'} />

<section className="flex flex-col gap-[1.6rem]">
<MaxMemberCountField name={'maxMemberCount'} />
<CustomMemberCountField name={'customMemberCount'} />
Expand Down Expand Up @@ -71,14 +79,13 @@ type SetUpDetailFieldProps = {
const TitleField = ({ name }: SetUpDetailFieldProps) => {
const {
register,
watch,
control,
formState: { errors },
} = useFormContext<SetUpDetailStepValues>();

const watchedName = watch(name);
const currentLength =
typeof watchedName === 'string' ? watchedName.length : 0;

const titleValue = useWatch({ control, name: name });
const titleValueLength =
typeof titleValue === 'string' ? titleValue.length : 0;
const titleErrors = errors[name];

return (
Expand All @@ -95,7 +102,7 @@ const TitleField = ({ name }: SetUpDetailFieldProps) => {
/>
<div className="flex flex-row-reverse justify-between gap-[0.4rem]">
<InputLength
currentLength={currentLength}
currentLength={titleValueLength}
maxLength={20}
isError={!!titleErrors}
/>
Expand Down Expand Up @@ -151,7 +158,7 @@ const MaxMemberCountField = ({ name }: SetUpDetailFieldProps) => {
return (
<>
<h2>최대 인원</h2>
<div className="inline-flex w-[23rem] flex-wrap gap-[1rem]">
<fieldset className="inline-flex w-[70%] flex-wrap gap-[1rem]">
{MAX_MEMBER_COUNT_OPTIONS.map(option => (
<RadioButton
key={option.value}
Expand All @@ -162,7 +169,7 @@ const MaxMemberCountField = ({ name }: SetUpDetailFieldProps) => {
})}
/>
))}
</div>
</fieldset>
<ErrorMessage>{maxMemberCountErrors?.message}</ErrorMessage>
</>
);
Expand All @@ -171,12 +178,13 @@ const MaxMemberCountField = ({ name }: SetUpDetailFieldProps) => {
const CustomMemberCountField = ({ name }: SetUpDetailFieldProps) => {
const {
register,
watch,
control,
formState: { errors },
} = useFormContext<SetUpDetailStepValues>();

const maxMemberCount = useWatch({ control, name: 'maxMemberCount' });
const isCustomInputCount = maxMemberCount === 'custom';
const customMemberCountErrors = errors[name];
const isCustomInputCount = watch('maxMemberCount') === 'custom';

return (
<>
Expand All @@ -185,6 +193,8 @@ const CustomMemberCountField = ({ name }: SetUpDetailFieldProps) => {
<Input
type="number"
placeholder="1000명 이상의 인원은 제한 없음을 선택해주세요"
className="after:content-['명']"
error={!!customMemberCountErrors}
{...register(name, {
required: {
value: isCustomInputCount,
Expand All @@ -204,10 +214,13 @@ const CustomMemberCountField = ({ name }: SetUpDetailFieldProps) => {
const PickStartDateField = ({ name }: SetUpDetailFieldProps) => {
const {
register,
control,
formState: { errors },
} = useFormContext<SetUpDetailStepValues>();

const startDateErrors = errors[name];
const endDate = useWatch({ control, name: 'endDate' });
const todayDate = getTodayDate();

return (
<section className="flex flex-col gap-[0.5rem]">
Expand All @@ -217,9 +230,13 @@ const PickStartDateField = ({ name }: SetUpDetailFieldProps) => {
{...register(name, {
required: '모임 시작일을 선택해주세요',
min: {
value: getTodayDate(),
value: todayDate,
message: '모임 시작일은 오늘 혹은 그 이후로 선택해주세요',
},
max: {
value: endDate,
message: '모임 시작일은 종료일 보다 빨라야해요',
},
})}
/>
</div>
Expand All @@ -231,10 +248,13 @@ const PickStartDateField = ({ name }: SetUpDetailFieldProps) => {
const PickEndDateField = ({ name }: SetUpDetailFieldProps) => {
const {
register,
watch,
control,
formState: { errors },
} = useFormContext<SetUpDetailStepValues>();

const startDate = useWatch({ control, name: 'startDate' });
const todayDate = getTodayDate();

const endDateErrors = errors[name];

return (
Expand All @@ -245,8 +265,8 @@ const PickEndDateField = ({ name }: SetUpDetailFieldProps) => {
{...register(name, {
required: '모임 종료일을 선택해주세요',
min: {
value: watch('startDate'),
message: '모임 종료일은 시작일보다 늦어야해요',
value: startDate || todayDate,
message: '모임 종료일은 시작일과 오늘 이후여야 해요',
},
})}
/>
Expand Down
2 changes: 2 additions & 0 deletions src/v1/bookGroup/create/steps/SetUpDetailStep/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { SetUpDetailStepValues } from './SetUpDetailStep';
export { default as SetUpDetailStep } from './SetUpDetailStep';

0 comments on commit d1271ed

Please sign in to comment.