Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions components/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, { useState } from 'react';

interface InputFieldProps {
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
type?: 'text' | 'email' | 'password' | 'name' | 'passwordConfirm';
placeholder?: string;
label?: string;
compareValue?: string;
}

const InputField: React.FC<InputFieldProps> = ({
value,
onChange,
type = 'text',
placeholder,
label,
compareValue,
}) => {
const [errorMessage, setErrorMessage] = useState<string | undefined>(
undefined
);

const validateInput = (value: string) => {
if (!value) return undefined;

if (type === 'email') {
if (!/\S+@\S+\.\S+/.test(value)) {
return '이메일 형식으로 작성해 주세요.';
}
}
if (type === 'password') {
if (value.length < 8) {
return '8자 이상 입력해주세요.';
}
}
if (type === 'name') {
if (value.length > 10) {
return '열 자 이하로 작성해주세요.';
}
}
if (type === 'passwordConfirm' && compareValue !== undefined) {
if (value !== compareValue) {
return '비밀번호가 일치하지 않습니다.';
}
}
return undefined;
};

const handleBlur = () => {
const error = validateInput(value);
setErrorMessage(error);
};

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e);
const error = validateInput(e.target.value);
setErrorMessage(error);
};
//스타일에 따른 클래스
const variantClass = {
container: 'mb-[24px] flex flex-col gap-[10px]',
label: 'text-14 text-gray-500',
base: 'px-[20px] py-[10px] h-[45px] w-[400px] rounded-md text-[14px] text-gray-500 placeholder:text-14 focus:outline-none mo:w-[355px]',
error: 'border border-red-100 bg-red-50',
normal:
'bg-gray-100 focus:border-green-200 focus:ring-1 focus:ring-green-200',
errorText: 'text-12 text-red-100',
};

const inputClass = `${variantClass.base} ${
errorMessage ? variantClass.error : variantClass.normal
}`;

return (
<div className={variantClass.container}>
{label && <label className={variantClass.label}>{label}</label>}
<input
type={
type === 'name'
? 'text'
: type === 'passwordConfirm'
? 'password'
: type
}
value={value}
onChange={handleChange}
placeholder={placeholder}
onBlur={handleBlur}
className={inputClass}
/>
{errorMessage && (
<span className={variantClass.errorText}>{errorMessage}</span>
)}
</div>
);
};

export default InputField;
Empty file added components/SearchInput.tsx
Empty file.
71 changes: 71 additions & 0 deletions pages/signup/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useState } from 'react';
import InputField from '@/components/Input';

const SignUp: React.FC = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [passwordConfirm, setPasswordConfirm] = useState('');
const [name, setName] = useState('');

const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setEmail(e.target.value);
};

const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
};

const handlePasswordConfirmChange = (
e: React.ChangeEvent<HTMLInputElement>
) => {
setPasswordConfirm(e.target.value);
};

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
alert('가입이 완료되었습니다');
};

return (
<form onSubmit={handleSubmit}>
<InputField
label="이름"
type="name"
value={name}
onChange={handleNameChange}
placeholder="이름을 입력해 주세요"
/>

<InputField
label="이메일"
type="email"
value={email}
onChange={handleEmailChange}
placeholder="이메일을 입력해 주세요"
/>

<InputField
label="비밀번호"
type="password"
value={password}
onChange={handlePasswordChange}
placeholder="비밀번호를 입력해 주세요"
/>

<InputField
label="비밀번호 확인"
type="passwordConfirm"
value={passwordConfirm}
onChange={handlePasswordConfirmChange}
placeholder="비밀번호를 다시 입력해 주세요"
compareValue={password}
/>
</form>
);
};

export default SignUp;
7 changes: 5 additions & 2 deletions pages/test/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Signup from '@/pages/signup';
export default function Test() {
const commonCellClass = 'border-r border-gray-300';
const commonRowClass = 'flex flex-wrap items-end gap-2';
Expand All @@ -13,8 +14,10 @@ export default function Test() {
</thead>
<tbody>
<tr>
<td className={commonCellClass}>컴포넌트명 입력</td>
<td className={commonRowClass}>{/* 컴포넌트를 추가해주세요 */}</td>
<td className={commonCellClass}>inputfield</td>
<td className={commonRowClass}>
<Signup />
</td>
</tr>
<tr>
<td className={commonCellClass}>컴포넌트명 입력</td>
Expand Down
Loading