INtiful / SootheWithMe

같이 달램
https://soothe-with-me.vercel.app/
0 stars 0 forks source link

feat: 로그인/ 회원가입 페이지 레이아웃 작성 #42

Closed hakyoung12 closed 3 weeks ago

hakyoung12 commented 3 weeks ago

✏️ 작업 내용

-로그인 페이지 레이아웃 작성 -회원가입 페이지 레이아웃 작성 -클라이언트에서 할 수 있는 유효성 검사 추가

📷 스크린샷

로그인 페이지

스크린샷 2024-09-10 오후 5 42 17

회원가입 페이지

스크린샷 2024-09-10 오후 5 41 55

폼 내용 채우지 않을 시 제출 버튼 비활성화

스크린샷 2024-09-10 오후 5 44 12

제출버튼 활성화

스크린샷 2024-09-10 오후 5 44 49

유효성 검사 오류 화면

스크린샷 2024-09-10 오후 5 47 57

✍️ 사용법

🎸 기타

yunsung-hodoopapa commented 1 week ago
<FormField label={<BasicLabel label={'이름'} isRequired={true} />}>
  <FormInput
    id="name"
    name="name"
    label="name"
    placeholder="이름을 입력해주세요"
    limit={50}
    editable={true}
    required={true}
  />
</FormField>
import React, { useEffect } from 'react';
import classNames from 'classnames';
import InputField, { InputProps } from '../InputField/InputField';
import { FieldValues, Path, RegisterOptions, useFormContext } from 'react-hook-form';
import './FormInput.scss';
import { addHyphenPhoneNum } from '../../../lib/utils';

export type FormInputProps<TFormValues extends FieldValues> = {
name: Path<TFormValues>;
rules?: RegisterOptions;
label: string;
value?: string;
editable: boolean;
required: boolean;
limit?: number;
} & Omit<InputProps, 'name'>;

export const FormInput = <TFormValues extends Record<string, unknown>>({
name,
rules,
className,
value,
editable = true,
required = false,
limit,
...props
}: FormInputProps<TFormValues>): JSX.Element => {
const { register, formState, watch, setValue } = useFormContext();
const { errors } = formState;
const hasError = !!errors?.[name];

const watchedValue = watch(name);

useEffect(() => {
if (name === 'phone') {
setValue(name, addHyphenPhoneNum(watchedValue));
}
}, [watchedValue, name, setValue]);

const fieldType = name === 'password' || name === 'passwordConfirm' ? 'password' : props.type;

return (
<div className={classNames('form-input', className)} aria-live="polite">
<InputField
  {...props}
  className={classNames()}
  value={value}
  hasError={hasError}
  {...(register && register(name, { ...rules, required, maxLength: limit }))}
  readOnly={!editable}
  type={fieldType}
/>
<p className="error-message" data-testid={`${name}-error`}>
  {hasError ? (watchedValue?.length ? errors?.[name]?.message : '필수 정보입니다.') : null}
</p>
</div>
);
};