issue #
Enter키 동작 구현
This commit is contained in:
@@ -1,11 +1,20 @@
|
|||||||
|
import { Validator } from '@/util/Validator';
|
||||||
import * as z from 'zod';
|
import * as z from 'zod';
|
||||||
|
|
||||||
export const LoginSchema = z.object({
|
export const LoginSchema = z.object({
|
||||||
id: z
|
id: z
|
||||||
.string()
|
.string()
|
||||||
|
.refine((val) => {
|
||||||
|
if (val.includes('@')) {
|
||||||
|
return Validator.isEmail(val);;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}, {
|
||||||
|
message: "이메일 형식이 올바르지 않습니다."
|
||||||
|
})
|
||||||
, password: z
|
, password: z
|
||||||
.string()
|
.string()
|
||||||
.min(8, "비밀번호는 8-12 자리여야 합니다.")
|
.min(8, "비밀번호는 8-12 자리여야 합니다.")
|
||||||
.max(12, "비밀번호는 8-12 자리여야 합니다.")
|
.max(12, "비밀번호는 8-12 자리여야 합니다.")
|
||||||
.regex(/^[a-z](?=.*[0-9])(?=.*[!@#$]).*$/, "비밀번호는 영소문자로 시작하여 숫자, 특수문자(!@#$)를 한 개 이상 포함하여야 합니다.")
|
.regex(/^(?=.*[0-9])(?=.*[!@#$%^])[a-zA-Z0-9!@#$%^]+$/, "비밀번호는 영소문자로 시작하여 숫자, 특수문자(!@#$)를 한 개 이상 포함하여야 합니다.")
|
||||||
});
|
});
|
||||||
@@ -6,12 +6,12 @@ export const ResetPasswordSchema = z.object({
|
|||||||
, code: z
|
, code: z
|
||||||
.string()
|
.string()
|
||||||
.length(8)
|
.length(8)
|
||||||
.regex(/^[a-z](?=.*[0-9])(?=.*[!@#$%^]).*$/, "영소문자로 시작하고 숫자와 특수문자(!@#$%^)를 포함해야 합니다.")
|
.regex(/^(?=.*[0-9])(?=.*[!@#$%^])[a-zA-Z0-9!@#$%^]+$/, "영소문자로 시작하고 숫자와 특수문자(!@#$%^)를 포함해야 합니다.")
|
||||||
, password: z
|
, password: z
|
||||||
.string()
|
.string()
|
||||||
.min(8, "비밀번호는 8-12 자리여야 합니다.")
|
.min(8, "비밀번호는 8-12 자리여야 합니다.")
|
||||||
.max(12, "비밀번호는 8-12 자리여야 합니다.")
|
.max(12, "비밀번호는 8-12 자리여야 합니다.")
|
||||||
.regex(/^[a-z](?=.*[0-9])(?=.*[!@#$%^]).*$/, "영소문자로 시작하고 숫자와 특수문자(!@#$%^)를 포함해야 합니다.")
|
.regex(/^(?=.*[0-9])(?=.*[!@#$%^])[a-zA-Z0-9!@#$%^]+$/, "영소문자로 시작하고 숫자와 특수문자(!@#$%^)를 포함해야 합니다.")
|
||||||
, passwordConfirm: z
|
, passwordConfirm: z
|
||||||
.string()
|
.string()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ export const SignUpSchema = z.object({
|
|||||||
accountId: z
|
accountId: z
|
||||||
.string()
|
.string()
|
||||||
.min(5, "아이디는 5 자리 이상이어야 합니다.")
|
.min(5, "아이디는 5 자리 이상이어야 합니다.")
|
||||||
|
.refine((val) => {
|
||||||
|
return /^[a-zA-z-_.]*$/.test(val);
|
||||||
|
}, {
|
||||||
|
message: "영문, 숫자, '- _ .' 를 제외한 문자를 사용할 수 없습니다."
|
||||||
|
})
|
||||||
, email: z
|
, email: z
|
||||||
.string()
|
.string()
|
||||||
.min(5, "이메일을 입력해주십시오.")
|
.min(5, "이메일을 입력해주십시오.")
|
||||||
@@ -11,7 +16,7 @@ export const SignUpSchema = z.object({
|
|||||||
.string()
|
.string()
|
||||||
.min(8, "비밀번호는 8-12 자리여야 합니다.")
|
.min(8, "비밀번호는 8-12 자리여야 합니다.")
|
||||||
.max(12, "비밀번호는 8-12 자리여야 합니다.")
|
.max(12, "비밀번호는 8-12 자리여야 합니다.")
|
||||||
.regex(/^[a-z](?=.*[0-9])(?=.*[!@#$%^]).*$/, "영소문자로 시작하고 숫자와 특수문자(!@#$%^)를 포함해야 합니다.")
|
.regex(/^(?=.*[0-9])(?=.*[!@#$%^])[a-zA-Z0-9!@#$%^]+$/, "영소문자로 시작하고 숫자와 특수문자(!@#$%^)를 포함해야 합니다.")
|
||||||
, name: z
|
, name: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "이름을 입력해주시십시오.")
|
.min(1, "이름을 입력해주시십시오.")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Field, FieldError, FieldLabel } from '@/components/ui/field';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { PageRouting } from '@/const/PageRouting';
|
import { PageRouting } from '@/const/PageRouting';
|
||||||
@@ -98,6 +98,13 @@ export default function LoginPage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleEnterKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (!(e.key === 'Enter')) return;
|
||||||
|
const result = await loginForm.trigger();
|
||||||
|
if (!result) return;
|
||||||
|
await reqLogin();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full flex flex-col justify-center items-center">
|
<div className="w-full h-full flex flex-col justify-center items-center">
|
||||||
<Card className="w-md pl-2 pr-2">
|
<Card className="w-md pl-2 pr-2">
|
||||||
@@ -117,6 +124,8 @@ export default function LoginPage() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="form-login-id"
|
id="form-login-id"
|
||||||
aria-invalid={fieldState.invalid}
|
aria-invalid={fieldState.invalid}
|
||||||
|
tabIndex={1}
|
||||||
|
onKeyDown={handleEnterKeyDown}
|
||||||
/>
|
/>
|
||||||
<FieldError errors={[fieldState.error]} />
|
<FieldError errors={[fieldState.error]} />
|
||||||
</Field>
|
</Field>
|
||||||
@@ -134,6 +143,7 @@ export default function LoginPage() {
|
|||||||
className="p-0 bg-transparent hover:bg-transparent h-fit w-fit text-xs text-gray-400 hover:text-gray-500 cursor-pointer"
|
className="p-0 bg-transparent hover:bg-transparent h-fit w-fit text-xs text-gray-400 hover:text-gray-500 cursor-pointer"
|
||||||
onClick={moveToResetPasswordPage}
|
onClick={moveToResetPasswordPage}
|
||||||
type="button"
|
type="button"
|
||||||
|
tabIndex={3}
|
||||||
>
|
>
|
||||||
비밀번호를 잊으셨습니까?
|
비밀번호를 잊으셨습니까?
|
||||||
</Button>
|
</Button>
|
||||||
@@ -143,6 +153,8 @@ export default function LoginPage() {
|
|||||||
type="password"
|
type="password"
|
||||||
id="form-login-password"
|
id="form-login-password"
|
||||||
aria-invalid={fieldState.invalid}
|
aria-invalid={fieldState.invalid}
|
||||||
|
tabIndex={2}
|
||||||
|
onKeyDown={handleEnterKeyDown}
|
||||||
/>
|
/>
|
||||||
<FieldError errors={[fieldState.error]} />
|
<FieldError errors={[fieldState.error]} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Field, FieldError, FieldLabel } from '@/components/ui/field';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { PageRouting } from '@/const/PageRouting';
|
import { PageRouting } from '@/const/PageRouting';
|
||||||
@@ -122,7 +122,7 @@ export default function ResetPasswordPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleThirdStepButton = async () => {
|
const handleClickThirdStepButton = async () => {
|
||||||
if (isLoading) return;
|
if (isLoading) return;
|
||||||
const passwordValid = await resetPasswordForm.trigger('password');
|
const passwordValid = await resetPasswordForm.trigger('password');
|
||||||
if (!passwordValid) return;
|
if (!passwordValid) return;
|
||||||
@@ -159,6 +159,19 @@ export default function ResetPasswordPage() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleEnterKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (currentStep === 1) {
|
||||||
|
await handleClickFirstStepButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currentStep === 3) {
|
||||||
|
await handleClickThirdStepButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stepper
|
<Stepper
|
||||||
value={currentStep}
|
value={currentStep}
|
||||||
@@ -211,13 +224,7 @@ export default function ResetPasswordPage() {
|
|||||||
type="email"
|
type="email"
|
||||||
id="reset-password-email"
|
id="reset-password-email"
|
||||||
aria-invalid={fieldState.invalid}
|
aria-invalid={fieldState.invalid}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={handleEnterKeyDown}
|
||||||
if (e.key === 'Enter') {
|
|
||||||
e.preventDefault();
|
|
||||||
if (email.length === 0) return;
|
|
||||||
handleClickFirstStepButton();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<FieldError className="font-[12px]" errors={[fieldState.error]} />
|
<FieldError className="font-[12px]" errors={[fieldState.error]} />
|
||||||
</>
|
</>
|
||||||
@@ -275,6 +282,7 @@ export default function ResetPasswordPage() {
|
|||||||
type={ showPassword ? "text" : "password" }
|
type={ showPassword ? "text" : "password" }
|
||||||
id="reset-password-password"
|
id="reset-password-password"
|
||||||
aria-invalid={fieldState.invalid}
|
aria-invalid={fieldState.invalid}
|
||||||
|
onKeyDown={handleEnterKeyDown}
|
||||||
className="pr-10"
|
className="pr-10"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@@ -306,6 +314,7 @@ export default function ResetPasswordPage() {
|
|||||||
id="reset-password-password-confirm"
|
id="reset-password-password-confirm"
|
||||||
className="pr-10"
|
className="pr-10"
|
||||||
aria-invalid={fieldState.invalid}
|
aria-invalid={fieldState.invalid}
|
||||||
|
onKeyDown={handleEnterKeyDown}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -380,7 +389,7 @@ export default function ResetPasswordPage() {
|
|||||||
(password.trim().length < 1)
|
(password.trim().length < 1)
|
||||||
&& (passwordConfirm.trim().length < 1)
|
&& (passwordConfirm.trim().length < 1)
|
||||||
}
|
}
|
||||||
onClick={handleThirdStepButton}
|
onClick={handleClickThirdStepButton}
|
||||||
>
|
>
|
||||||
비밀번호 변경
|
비밀번호 변경
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ export class Validator {
|
|||||||
|
|
||||||
static validatePasswordFormat = (password: string): boolean => {
|
static validatePasswordFormat = (password: string): boolean => {
|
||||||
if (password.length < 8) return false;
|
if (password.length < 8) return false;
|
||||||
|
if (password.includes(' ')) return false;
|
||||||
|
|
||||||
const alphabets = 'abcdefghijklmnopqrstuvwxyz';
|
const alphabets = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
const numbers = '0123456789';
|
const numbers = '0123456789';
|
||||||
const specials = '!@#$%^';
|
const specials = '!@#$%^';
|
||||||
|
|||||||
Reference in New Issue
Block a user