Skip to content

Commit

Permalink
refactor: 방 생성, 방 관리의 폼 관리 리팩토링 (#502)
Browse files Browse the repository at this point in the history
* refactor: FORM_LITERAL 객체로 폼 관련 상수 관리

* remove: 루틴 수정 기능, 방 삭제 탭 제거
  • Loading branch information
bbearcookie authored Feb 18, 2024
1 parent 1f61f9f commit 174ae7e
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 322 deletions.
2 changes: 0 additions & 2 deletions src/core/api/functions/roomAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ const roomAPI = {
roomId: string;
title: string;
announcement: string;
// TODO: 루틴 수정을 제한하는 요구사항 발생
// routines: string[];
password: string;
certifyTime: number;
maxUserCount: number;
Expand Down
4 changes: 2 additions & 2 deletions src/domain/RoomForm/components/Password.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback } from 'react';
import { useFormContext } from 'react-hook-form';
import { PasswordInput } from '@/shared/Input';
import { PASSWORD } from '@/domain/RoomForm/constants/literals';
import { FORM_LITERAL } from '@/domain/RoomForm/constants/literals';
import { errorStyle } from '../constants/styles';

interface PasswordProps {
Expand Down Expand Up @@ -29,7 +29,7 @@ const Password = ({ placeholder }: PasswordProps) => {
<PasswordInput
{...register('password')}
placeholder={placeholder}
maxLength={PASSWORD.max}
maxLength={FORM_LITERAL.password.max.value}
onChange={handleChangePassword}
/>
{errors.password && (
Expand Down
10 changes: 5 additions & 5 deletions src/domain/RoomForm/components/Routines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
import { InnerTextInput } from '@/shared/Input';
import { Icon } from '@/shared/Icon';
import { ROUTINE_COUNT, ROUTINE_NAME } from '../constants/literals';
import { FORM_LITERAL } from '../constants/literals';
import { errorStyle, iconButtonStyle } from '../constants/styles';

const Routines = () => {
Expand All @@ -25,7 +25,7 @@ const Routines = () => {
});

const handleAppendRoutine = useCallback(() => {
if (routines.length >= ROUTINE_COUNT.max) {
if (routines.length >= FORM_LITERAL.routines.max.value) {
return;
}

Expand Down Expand Up @@ -54,10 +54,10 @@ const Routines = () => {
text={
watchRoutines[idx].value.length.toString() +
' / ' +
ROUTINE_NAME.max
FORM_LITERAL.routines.item.max.value
}
placeholder="루틴 이름"
maxLength={ROUTINE_NAME.max}
maxLength={FORM_LITERAL.routines.item.max.value}
/>
{idx !== 0 && (
<div
Expand Down Expand Up @@ -91,7 +91,7 @@ const Routines = () => {
/>
</button>
<div className="text-center text-xs">
{routines.length} / {ROUTINE_COUNT.max}
{routines.length} / {FORM_LITERAL.routines.max.value}
</div>
</li>
</ul>
Expand Down
4 changes: 2 additions & 2 deletions src/domain/RoomForm/components/UserCount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { useFormContext } from 'react-hook-form';
import { Icon } from '@/shared/Icon';
import { iconButtonStyle, errorStyle } from '../constants/styles';
import { USER_COUNT } from '../constants/literals';
import { FORM_LITERAL } from '../constants/literals';

const UserCount = () => {
const {
Expand All @@ -15,7 +15,7 @@ const UserCount = () => {

const handleSetUserCount = useCallback(
(count: number) => {
if (count <= 0 || count > USER_COUNT.max) {
if (count <= 0 || count > FORM_LITERAL.userCount.max.value) {
return;
}

Expand Down
131 changes: 77 additions & 54 deletions src/domain/RoomForm/constants/literals.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,80 @@
// 새 종류 별 방 타입
import { RoomInfo } from '@/core/types/Room';

export const ROOM_TYPES = ['MORNING', 'NIGHT'] as const;
export const FORM_LITERAL = {
/** 방 종류 */
roomType: {
value: ['MORNING', 'NIGHT'],
message: '방 종류를 선택해주세요.'
},
/** 루틴 목록 */
routines: {
min: {
value: 0
},
max: {
value: 4,
message: '루틴은 최대 4개까지 등록할 수 있어요.'
},
item: {
min: {
value: 2,
message: '루틴 내용은 2글자 이상이어야 해요.'
},
max: {
value: 20,
message: '루틴 내용은 20글자 이하로 입력해주세요.'
}
}
},
/** 방 제목 */
title: {
min: {
value: 1,
message: '방 제목은 1글자 이상이어야 해요.'
},
max: {
value: 20,
message: '방 제목은 20글자 이하로 입력해주세요.'
}
},
/** 방에 참여할 수 있는 인원 수 */
userCount: {
min: {
value: 1,
message: '인원을 1명 이상 선택해주세요.'
},
max: {
value: 10,
message: '인원을 10명 이하로 선택해주세요.'
}
},
/** 방 비밀번호 */
password: {
min: {
value: 4,
message: '비밀번호는 4자리 이상이어야 해요.'
},
max: {
value: 8,
message: '비밀번호는 8자리 이하로 입력해주세요.'
},
onlyNumeric: {
message: '비밀번호는 숫자로만 입력해주세요.'
}
},
/** 공지사항 */
announcement: {
min: {
value: 0
},
max: {
value: 100,
message: '공지사항은 100글자 이하로 입력해주세요.'
}
}
} as const;

// 새 종류 및 이미지
/** 새 종류 및 이미지 */
export const BIRD: Record<
RoomInfo['roomType'],
{
Expand All @@ -24,59 +95,11 @@ export const BIRD: Record<
}
} as const;

// 새 종류 별 선택할 수 있는 인증 시간 범위
/** 새 종류 별 선택할 수 있는 인증 시간 범위 */
export const TIME_RANGE: Record<RoomInfo['roomType'], [number, number]> = {
MORNING: [4, 10],
NIGHT: [20, 26]
};

// 참여할 수 있는 최대 방 수
export const ROOM_COUNT = {
max: 3
};

// 등록할 수 있는 최대 루틴 수
export const ROUTINE_COUNT = {
max: 4
};

// 루틴 이름 길이
export const ROUTINE_NAME = {
min: 2,
max: 20
};

// 방 제목 길이
export const ROOM_NAME = {
min: 1,
max: 20
};

// 비밀번호 길이
export const PASSWORD = {
min: 4,
max: 8
};

// 참여자 수
export const USER_COUNT = {
min: 1,
max: 10
};

// 공지사항 길이
export const ANNOUNCEMENT = {
min: 0,
max: 100
};

// 폼 유효성 검사 메시지
export const FORM_MESSAGE = {
ROOM_TYPE: `방 종류를 선택해주세요.`,
ANNOUNCEMENT: `공지사항은 ${ANNOUNCEMENT.min}글자에서 ${ANNOUNCEMENT.max}글자 사이여야 해요.`,
ROUTINE_NAME: `루틴 내용은 ${ROUTINE_NAME.min}글자에서 ${ROUTINE_NAME.max}글자 사이여야 해요.`,
ROOM_NAME: `방 제목은 ${ROOM_NAME.min}글자에서 ${ROOM_NAME.max}글자 사이여야 해요.`,
USER_COUNT: `인원을 올바르게 선택해주세요.`,
PASSWORD: `비밀번호는 ${PASSWORD.min}자리에서 ${PASSWORD.max}자리의 숫자여야 해요.`,
ONLY_NUMERIC_PASSWORD: `비밀번호는 숫자로만 입력해주세요.`
};
/** 참여할 수 있는 최대 방 수 */
export const MAX_ROOM_COUNT = 3;
8 changes: 4 additions & 4 deletions src/domain/RoomNew/components/BirdCardSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useFormContext } from 'react-hook-form';
import { roomOptions } from '@/core/api/options';
import { QueryErrorBoundary, NetworkFallback } from '@/shared/ErrorBoundary';
import {
ROOM_COUNT,
ROOM_TYPES,
MAX_ROOM_COUNT,
FORM_LITERAL,
TIME_RANGE
} from '@/domain/RoomForm/constants/literals';
import { Inputs } from '../hooks/useRoomForm';
Expand All @@ -29,12 +29,12 @@ const BirdCardSectionComponent = () => {
});

const isFull = (type: Inputs['roomType']) => {
return roomCount[type] >= ROOM_COUNT.max;
return roomCount[type] >= MAX_ROOM_COUNT;
};

return (
<>
{ROOM_TYPES.map((roomType) => (
{FORM_LITERAL.roomType.value.map((roomType) => (
<div
className="w-full"
key={roomType}
Expand Down
31 changes: 13 additions & 18 deletions src/domain/RoomNew/hooks/useRoomForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,40 @@ import roomAPI from '@/core/api/functions/roomAPI';
import { useMoveRoute } from '@/core/hooks';
import { Toast } from '@/shared/Toast';
import {
FORM_MESSAGE,
ROOM_TYPES,
TIME_RANGE,
ROUTINE_NAME,
ROOM_NAME,
USER_COUNT,
PASSWORD
FORM_LITERAL as L,
TIME_RANGE
} from '@/domain/RoomForm/constants/literals';

export const formSchema = z.object({
roomType: z.enum(ROOM_TYPES, {
required_error: FORM_MESSAGE.ROOM_TYPE
roomType: z.enum(L.roomType.value, {
required_error: L.roomType.message
}),
certifyTime: z.number(),
routines: z.array(
z.object({
value: z
.string()
.trim()
.min(ROUTINE_NAME.min, FORM_MESSAGE.ROUTINE_NAME)
.max(ROUTINE_NAME.max, FORM_MESSAGE.ROUTINE_NAME)
.min(L.routines.item.min.value, L.routines.item.min.message)
.max(L.routines.item.max.value, L.routines.item.max.message)
})
),
title: z
.string()
.trim()
.min(ROOM_NAME.min, FORM_MESSAGE.ROOM_NAME)
.max(ROOM_NAME.max, FORM_MESSAGE.ROOM_NAME),
.min(L.title.min.value, L.title.min.message)
.max(L.title.max.value, L.title.max.message),
userCount: z
.number()
.gte(USER_COUNT.min, FORM_MESSAGE.USER_COUNT)
.lte(USER_COUNT.max, FORM_MESSAGE.USER_COUNT),
.gte(L.userCount.min.value, L.userCount.min.message)
.lte(L.userCount.max.value, L.userCount.max.message),
password: z.literal('').or(
z
.string()
.min(PASSWORD.min, FORM_MESSAGE.PASSWORD)
.max(PASSWORD.max, FORM_MESSAGE.PASSWORD)
.min(L.password.min.value, L.password.min.message)
.max(L.password.max.value, L.password.max.message)
.refine((v) => /^\d*$/.test(v), {
message: FORM_MESSAGE.ONLY_NUMERIC_PASSWORD
message: L.password.onlyNumeric.message
})
)
});
Expand Down
8 changes: 5 additions & 3 deletions src/domain/RoomNew/steps/PasswordStep.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import clsx from 'clsx';
import { PASSWORD } from '@/domain/RoomForm/constants/literals';
import { FORM_LITERAL } from '@/domain/RoomForm/constants/literals';
import { Password } from '@/domain/RoomForm';
import { headingStyle, descriptionStyle } from '../constants/styles';

const PasswordStep = () => {
const min = FORM_LITERAL.password.min.value;
const max = FORM_LITERAL.password.max.value;

return (
<>
<h1 className={headingStyle}>
Expand All @@ -14,8 +17,7 @@ const PasswordStep = () => {
</h1>

<p className={clsx(descriptionStyle, 'mb-10')}>
선택사항입니다. {PASSWORD.min}자리에서 {PASSWORD.max}자리 숫자를
적어주세요!
선택사항입니다. {min}자리에서 {max}자리 숫자를 적어주세요!
</p>

<Password placeholder="비워두시면 공개방이 됩니다" />
Expand Down
4 changes: 2 additions & 2 deletions src/domain/RoomNew/steps/RoutineStep.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useFormContext } from 'react-hook-form';
import { Input } from '@/shared/Input';
import { ROOM_NAME } from '@/domain/RoomForm/constants/literals';
import { FORM_LITERAL } from '@/domain/RoomForm/constants/literals';
import { Routines, UserCount } from '@/domain/RoomForm';
import { errorStyle } from '../constants/styles';
import { Inputs } from '../hooks/useRoomForm';
Expand All @@ -20,7 +20,7 @@ const RoutineStep = () => {
</h2>
<Input
{...register('title')}
maxLength={ROOM_NAME.max}
maxLength={FORM_LITERAL.title.max.value}
placeholder="짧고 명확하게!"
/>
{errors.title && <p className={errorStyle}>{errors.title.message}</p>}
Expand Down
Loading

0 comments on commit 174ae7e

Please sign in to comment.