diff --git a/src/components/commons/SignInput/SignInput.module.scss b/src/components/commons/SignInput/SignInput.module.scss index c006bea..a100beb 100644 --- a/src/components/commons/SignInput/SignInput.module.scss +++ b/src/components/commons/SignInput/SignInput.module.scss @@ -6,6 +6,9 @@ .input-field { @extend %input-base; } + .disabled { + color: $gray30; + } .helper-text { @include text-style(1.2, 400, $gray30); diff --git a/src/components/commons/SignInput/index.tsx b/src/components/commons/SignInput/index.tsx index f499a50..5d1570c 100644 --- a/src/components/commons/SignInput/index.tsx +++ b/src/components/commons/SignInput/index.tsx @@ -8,15 +8,23 @@ interface SignInputProps extends InputHTMLAttributes { isError?: boolean; isVerified?: boolean; helperText?: string; + disabled?: boolean; } const SignInput = forwardRef( - ({ id, type = "text", isError = false, isVerified = false, helperText, ...props }, ref) => { + ({ id, type = "text", isError = false, isVerified = false, helperText, disabled = false, ...props }, ref) => { const helperTextLines = helperText?.split("\n") || []; return (
- +
{helperTextLines.map((line, index) => (

diff --git a/src/components/commons/SignInputController/index.tsx b/src/components/commons/SignInputController/index.tsx index c38b76c..54f6ec5 100644 --- a/src/components/commons/SignInputController/index.tsx +++ b/src/components/commons/SignInputController/index.tsx @@ -8,9 +8,15 @@ interface SignInputControllerProps { control: Control; condition: SignField; setError?: UseFormSetError | undefined; + disabled?: boolean; } -const SignInputController = ({ name, control, condition }: SignInputControllerProps) => { +const SignInputController = ({ + name, + control, + condition, + disabled = false, +}: SignInputControllerProps) => { const { defaultMessage, type, ...inputProps } = condition; return ( @@ -22,6 +28,7 @@ const SignInputController = ({ name, control, condition } id={name} type={type} isError={!!fieldState.error} + disabled={disabled} helperText={fieldState.error?.message || defaultMessage} {...inputProps} {...field} diff --git a/src/components/domains/myPage/contents/UpdateUserInfo/UpdateUserInfo.module.scss b/src/components/domains/myPage/contents/UpdateUserInfo/UpdateUserInfo.module.scss new file mode 100644 index 0000000..ef13f6c --- /dev/null +++ b/src/components/domains/myPage/contents/UpdateUserInfo/UpdateUserInfo.module.scss @@ -0,0 +1,87 @@ +.container { + @include flexbox(center, start); + min-height: 100vh; + padding-bottom: 8.6rem; +} + +.items { + @include column-flexbox(); + gap: 4rem; + max-width: 40rem; + width: 100%; + + @include responsive("M") { + padding-left: 2rem; + padding-right: 2rem; + } +} + +.header { + @include text-style(3, 700); +} + +.user-container { + @include column-flexbox(); + width: 100%; +} + +.form { + @include column-flexbox(center, start); + gap: 3rem; + + &-input { + @include column-flexbox(center, start); + gap: 0.6rem; + + &-except-email { + @include column-flexbox(); + gap: 0.6rem; + width: 100%; + } + } +} + +.auth-form { + @include column-flexbox(start, center); + min-height: 100vh; + padding-top: 15vh; + padding-bottom: 8.6rem; + gap: 1rem; + + @include responsive("T") { + padding-top: 10vh; + } + + .auth-form-txt { + font-size: 20px; + } + + form { + @include column-flexbox(center, center); + width: 100%; + max-width: 35rem; + gap: 0.5rem; + } +} + +.input-field { + @extend %input-base; + margin: 2rem 0; +} +.disabled { + color: $gray30; +} + +.helper-text { + @include text-style(1.2, 400, $gray30); + @include column-flexbox(start, end); + min-height: 1.6rem; + + .verified { + color: $primary40; + } + + .error { + color: $red; + } +} diff --git a/src/components/domains/myPage/contents/UpdateUserInfo/index.tsx b/src/components/domains/myPage/contents/UpdateUserInfo/index.tsx index 9dfca7f..7d116b7 100644 --- a/src/components/domains/myPage/contents/UpdateUserInfo/index.tsx +++ b/src/components/domains/myPage/contents/UpdateUserInfo/index.tsx @@ -1,8 +1,170 @@ +import Text from "@/components/commons/Text"; + +import classNames from "classnames/bind"; +import styles from "./UpdateUserInfo.module.scss"; +const cx = classNames.bind(styles); + const UpdateUserInfo = () => { + const [auth, setAuth] = useState(false); + const [password, setPassword] = useState(""); + + const handlePasswordSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (password) { + setAuth(true); + } + }; + return ( - <> -

UpdateUserInfo Component

- +
+
+ {auth ? ( + + ) : ( +
+ + +
+ setPassword(e.target.value)} + placeholder="비밀번호를 입력해주세요" + /> + +
+
+ )} +
+
); }; + export default UpdateUserInfo; + +import Button from "@/components/commons/Button"; +import SignInputController from "@/components/commons/SignInputController"; +import { StatusType } from "@/constants/emailAndCodeStatus"; +import { inputOrder, SIGNUP_DEFAULT_VALUES } from "@/constants/signDefaultValues"; +import { SIGN_UP_CONDITION, SIGN_UP_EMAIL_CONDITION } from "@/constants/signInputCondition"; +import { useEmailAndCodeValidation } from "@/hooks/useEmailAndCodeValidation"; +import { useNicknameValidation } from "@/hooks/useNicknameValidation"; +import { useSignUpMutation } from "@/hooks/useSignUpMutation"; +import { SignUpFormInputs, signUpSchema } from "@/schemas/signUpSchema"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { useForm, useFormState } from "react-hook-form"; + +const UserForm = () => { + const submitButtonRef = useRef(null); + const [submitKey, setSubmitKey] = useState(0); + + const { control, formState, setError, watch, clearErrors, setValue, trigger, getValues, setFocus } = + useForm({ + resolver: zodResolver(signUpSchema), + mode: "onChange", + defaultValues: SIGNUP_DEFAULT_VALUES, + }); + + const { emailStatus, codeStatus, validateEmailAndCode } = useEmailAndCodeValidation( + watch, + setValue, + setError, + clearErrors, + ); + + const nickname = watch("nickname"); + + const { + errors: { email: isEmailError, nickname: isNicknameError }, + } = useFormState({ control, name: ["email", "nickname"] }); + + useNicknameValidation(nickname, Boolean(isNicknameError), setError); + + const { signUp } = useSignUpMutation(); + + const customSubmit = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + setSubmitKey((prev) => prev + 1); + + if (isEmailError) { + await trigger(["password", "confirmPassword", "name", "nickname", "phoneNumber"]); + return; + } else { + const isZodValid = await trigger(); + + if (!isZodValid) { + alert("회원정보입력을 잘못하셨습니다"); + return; + } + const { email, name, nickname, password, phoneNumber } = getValues(); + alert("회원정보변경 완료"); + console.log({ email, name, nickname, password, phoneNumber }); + // signUp({ email, name, nickname, password, phoneNumber }); + } + }, + [isEmailError, trigger, validateEmailAndCode, getValues, signUp], + ); + + useEffect(() => { + const errors = formState.errors; + + if (emailStatus.status !== StatusType.SUCCESS) { + setFocus("email"); + return; + } else if (codeStatus.status !== StatusType.SUCCESS) { + setFocus("code"); + return; + } + if (Object.keys(errors).length > 0) { + console.log(errors); + const firstErrorField = inputOrder.find((field) => errors[field]); + + if (firstErrorField) { + setFocus(firstErrorField); + } + } + }, [formState.errors, submitKey, codeStatus.status, emailStatus.status, setFocus]); + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + e.preventDefault(); + submitButtonRef.current?.click(); + } + }; + + return ( +
+
+
+ + {(Object.keys(SIGN_UP_CONDITION) as Array).map((key) => ( + + ))} +
+
+ + +
+ ); +}; + +UserForm;