Skip to content

Commit

Permalink
feat: 이름, 프로젝트명에 대한 유효성 검사 및 에러 메세지 안내 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
ImxYJL committed Aug 14, 2024
1 parent 7f281d8 commit e45f369
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import styled from '@emotion/styled';
export const FormBody = styled.div<{ direction: React.CSSProperties['flexDirection'] }>`
display: flex;
flex-direction: ${({ direction }) => direction};
gap: 1.6em;
gap: 1.8rem;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import { Input, Button } from '@/components';
import { useGroupAccessCode } from '@/hooks';
import { debounce } from '@/utils/debounce';

import { isValidAccessCodeInput } from '../../utils/validateInput';
import { FormLayout } from '../index';

import * as S from './styles';

const DEBOUNCE_TIME = 300;

const ALPHANUMERIC_ERROR_MESSAGE = '알파벳 대소문자와 숫자만 입력 가능합니다.';

// NOTE: groupAccessCode가 유효한지를 확인하는 API 호출은 fetch로 고정!
// 1. 요청을 통해 단순히 true, false 정도의 데이터를 단발적으로 가져오는 API이므로
// 리액트 쿼리를 사용할 만큼 서버 상태를 정교하게 가지고 있을 필요 없음
Expand Down Expand Up @@ -43,7 +46,7 @@ const ReviewAccessForm = () => {

try {
if (!isAlphanumeric(groupAccessCode)) {
setErrorMessage('알파벳 대소문자와 숫자만 입력 가능합니다.');
setErrorMessage(ALPHANUMERIC_ERROR_MESSAGE);
return;
}

Expand Down Expand Up @@ -71,7 +74,7 @@ const ReviewAccessForm = () => {
/>
<Button
type="button"
styleType={groupAccessCode ? 'primary' : 'disabled'}
styleType={isValidAccessCodeInput(groupAccessCode) ? 'primary' : 'disabled'}
onClick={handleAccessReviewButtonClick}
disabled={!groupAccessCode}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';

import { DataForURL } from '@/apis/group';
import { Button, Input } from '@/components';
Expand All @@ -7,10 +7,16 @@ import useModals from '@/hooks/useModals';
import { debounce } from '@/utils/debounce';

import usePostDataForURL from '../../queries/usePostDataForURL';
import { isValidReviewGroupDataInput, isWithinMaxLength } from '../../utils/validateInput';
import { FormLayout, ReviewGroupDataModal } from '../index';

import * as S from './styles';

// TODO: 디바운스 시간을 모든 경우에 0.3초로 고정할 것인지(전역 상수로 사용) 논의하기
const DEBOUNCE_TIME = 300;
const MAX_VALID_REVIEW_GROUP_DATA_INPUT = 50;

const LENGTH_ERROR_MESSAGE = `${MAX_VALID_REVIEW_GROUP_DATA_INPUT}자까지 입력할 수 있습니다.`;

const MODAL_KEYS = {
confirm: 'CONFIRM',
Expand All @@ -21,10 +27,15 @@ const URLGeneratorForm = () => {
const [projectName, setProjectName] = useState('');
const [reviewRequestCode, setReviewRequestCode] = useState('');

const [revieweeNameErrorMessage, setRevieweeNameErrorMessage] = useState('');
const [projectNameErrorMessage, setProjectNameErrorMessage] = useState('');

const mutation = usePostDataForURL();
const { updateGroupAccessCode } = useGroupAccessCode();
const { isOpen, openModal, closeModal } = useModals();

const isFormValid = isValidReviewGroupDataInput(revieweeName) && isValidReviewGroupDataInput(projectName);

const postDataForURL = () => {
const dataForURL: DataForURL = { revieweeName, projectName };

Expand Down Expand Up @@ -63,20 +74,38 @@ const URLGeneratorForm = () => {
openModal(MODAL_KEYS.confirm);
}, DEBOUNCE_TIME);

useEffect(() => {
isWithinMaxLength(revieweeName, MAX_VALID_REVIEW_GROUP_DATA_INPUT)
? setRevieweeNameErrorMessage('')
: setRevieweeNameErrorMessage(LENGTH_ERROR_MESSAGE);
}, [revieweeName]);

useEffect(() => {
isWithinMaxLength(projectName, MAX_VALID_REVIEW_GROUP_DATA_INPUT)
? setProjectNameErrorMessage('')
: setProjectNameErrorMessage(LENGTH_ERROR_MESSAGE);
}, [projectName]);

return (
<FormLayout title="함께한 팀원으로부터 리뷰를 받아보세요!" direction="column">
<Input value={revieweeName} onChange={handleNameInputChange} type="text" placeholder="이름을 입력해주세요" />
<Input
value={projectName}
onChange={handleProjectNameInputChange}
type="text"
placeholder="함께한 프로젝트 이름을 입력해주세요"
/>
<S.InputContainer>
<Input value={revieweeName} onChange={handleNameInputChange} type="text" placeholder="이름을 입력해주세요" />
<S.ErrorMessage>{revieweeNameErrorMessage}</S.ErrorMessage>
</S.InputContainer>
<S.InputContainer>
<Input
value={projectName}
onChange={handleProjectNameInputChange}
type="text"
placeholder="함께한 프로젝트 이름을 입력해주세요"
/>
<S.ErrorMessage>{projectNameErrorMessage}</S.ErrorMessage>
</S.InputContainer>
<Button
type="button"
styleType={revieweeName && projectName ? 'primary' : 'disabled'}
styleType={isFormValid ? 'primary' : 'disabled'}
onClick={handleUrlCreationButtonClick}
disabled={!(revieweeName && projectName)}
disabled={!isFormValid}
>
리뷰 요청 URL 생성하기
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import styled from '@emotion/styled';

export const InputContainer = styled.div`
display: flex;
flex-direction: column;
gap: 0.2rem;
`;

export const ErrorMessage = styled.p`
font-size: 1.3rem;
color: ${({ theme }) => theme.colors.red};
height: 1.3rem;
padding-left: 0.7rem;
`;

0 comments on commit e45f369

Please sign in to comment.