Skip to content

Commit

Permalink
Merge pull request #448 from jisurk/part3-우지석-week14
Browse files Browse the repository at this point in the history
[우지석] Week14
  • Loading branch information
choinashil authored May 21, 2024
2 parents 0c228dc + 6bf4fe8 commit 5b4db1f
Show file tree
Hide file tree
Showing 36 changed files with 2,394 additions and 954 deletions.
76 changes: 76 additions & 0 deletions components/EmailInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// components/EmailInput.tsx

import React, { useState, useEffect } from "react";
import classNames from "classnames/bind";
import styles from "@/styles/signin.module.scss";

interface EmailInputProps {
value: string;
onChange: (value: string) => void;
error?: string;
}

export const emailCheck = (email: string) => {
const emailForm =
/^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i;
return emailForm.test(email);
};

export function EmailInput({ value, onChange, error }: EmailInputProps) {
const cx = classNames.bind(styles);
const [isFocused, setIsFocused] = useState(false);
const [emailErrorText, setEmailErrorText] = useState("");

useEffect(() => {
setEmailErrorText(error || "");
}, [error]);

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const emailInput = e.target.value;
onChange(emailInput);
};

const handleBlur = () => {
setIsFocused(false);
if (value) {
if (!emailCheck(value)) {
setEmailErrorText("올바른 이메일 주소가 아닙니다.");
} else {
setEmailErrorText("");
}
} else {
setEmailErrorText("이메일을 입력해 주세요.");
}
};

const handleFocus = () => {
setIsFocused(true);
};

const isError = !isFocused && (error || emailErrorText);

return (
<div className={cx("input__section")}>
<label className={cx("text")}>
이메일 <br />
</label>
<input
id="email"
placeholder="이메일을 입력해 주세요."
className={cx("user-input", { "error-input": isError })}
type="email"
name="email"
value={value}
onChange={handleChange}
onBlur={handleBlur}
onFocus={handleFocus}
/>
<div
id="email-errorText"
className={cx("errortext", { error: !isError })}
>
{emailErrorText}
</div>
</div>
);
}
70 changes: 70 additions & 0 deletions components/PasswordInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useState } from "react";
import classNames from "classnames/bind";
import styles from "@/styles/signin.module.scss";

interface PasswordInputProps {
value: string;
onChange: (value: string) => void;
onBlur?: () => void;
error?: string;
id?: string;
}

export function PasswordInput({
value,
onChange,
onBlur,
error,
id,
}: PasswordInputProps) {
const cx = classNames.bind(styles);
const [isFocused, setIsFocused] = useState(false);
const [errorText, setErrorText] = useState("");

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

const handleBlur = () => {
setIsFocused(false);
if (onBlur) {
onBlur();
}
if (!value) {
setErrorText("비밀번호를 입력해 주세요.");
} else {
setErrorText("");
}
};

const handleFocus = () => {
setIsFocused(true);
};

const isError = !isFocused && (error || errorText);

return (
<div className={cx("input__section", "password-section")}>
<label className={cx("text")}>
비밀번호 <br />
</label>
<input
id={id || "password"}
placeholder="비밀번호를 입력해 주세요."
className={cx("user-input", { "error-input": isError })}
type="password"
name="password"
value={value}
onChange={handleChange}
onBlur={handleBlur}
onFocus={handleFocus}
/>
<div
id="password-errorText"
className={cx("errortext", { error: !isError })}
>
{error || errorText}
</div>
</div>
);
}
51 changes: 51 additions & 0 deletions components/SignInForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useState } from "react";
import { useRouter } from "next/router";
import axios from "axios";
import { EmailInput } from "./EmailInput";
import { PasswordInput } from "./PasswordInput";
import styles from "@/styles/signin.module.scss";
import classNames from "classnames/bind";

export function SignIn() {
const cx = classNames.bind(styles);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [emailError, setEmailError] = useState("");
const [passwordError, setPasswordError] = useState("");
const router = useRouter();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setEmailError("");
setPasswordError("");
const data = { email, password };
try {
const response = await axios.post(
"https://bootcamp-api.codeit.kr/api/sign-in",
data
);
if (response.status === 200) {
router.push("/folder");
}
} catch (error: any) {
if (error.response) {
if (error.response.status === 400) {
setEmailError("이메일을 확인해 주세요.");
setPasswordError("비밀번호를 확인해 주세요.");
}
}
}
};
return (
<form className={cx("input")} onSubmit={handleSubmit}>
<EmailInput value={email} onChange={setEmail} error={emailError} />
<PasswordInput
value={password}
onChange={setPassword}
error={passwordError}
/>
<button type="submit" id="btn" className={cx("signin", "button")}>
로그인
</button>
</form>
);
}
66 changes: 66 additions & 0 deletions components/SignUpForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useState } from "react";
import { useRouter } from "next/router";
import axios from "axios";
import { EmailInput, emailCheck } from "./EmailInput";
import { SignUpPassword, isValidPassword } from "./SignUpPassword";
import styles from "@/styles/signup.module.scss";
import classNames from "classnames/bind";

export function SignUp() {
const cx = classNames.bind(styles);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [emailError, setEmailError] = useState("");
const router = useRouter();

const signUp = async (e: React.FormEvent) => {
e.preventDefault();
const emailChecked = emailCheck(email);
const validPassword = isValidPassword(password);
const passwordMatch = password === confirmPassword;

if (emailChecked && validPassword && passwordMatch) {
const checkEmailUrl = "https://bootcamp-api.codeit.kr/api/check-email";
const checkEmailData = { email };
try {
const checkEmailResponse = await axios.post(
checkEmailUrl,
checkEmailData
);
if (checkEmailResponse.status === 409) {
setEmailError("이미 사용 중인 이메일입니다.");
console.log("hello~");
return;
} else {
setEmailError("");
}

const signUpUrl = "https://bootcamp-api.codeit.kr/api/sign-up";
const signUpData = { email, password };
const signUpResponse = await axios.post(signUpUrl, signUpData);
if (signUpResponse.status === 200) {
router.push("/folder");
}
} catch (error) {
console.log("Error:", error);
console.log("hello2");
}
}
};

return (
<form className={cx("signup__form")} onSubmit={signUp}>
<EmailInput value={email} onChange={setEmail} error={emailError} />
<SignUpPassword
password={password}
confirmPassword={confirmPassword}
onPasswordChange={setPassword}
onConfirmPasswordChange={setConfirmPassword}
/>
<button type="submit" className={cx("signup__button")}>
회원가입
</button>
</form>
);
}
60 changes: 60 additions & 0 deletions components/SignUpPassword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useState } from "react";
import { PasswordInput } from "./PasswordInput";

interface SignUpPasswordProps {
password: string;
confirmPassword: string;
onBlur?: () => void;
onPasswordChange: (value: string) => void;
onConfirmPasswordChange: (value: string) => void;
}

export const isValidPassword = (password: string) => {
const passwordForm = /(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
return passwordForm.test(password);
};

export function SignUpPassword({
password,
confirmPassword,
onPasswordChange,
onConfirmPasswordChange,
}: SignUpPasswordProps) {
const [passwordError, setPasswordError] = useState("");
const [confirmPasswordError, setConfirmPasswordError] = useState("");

const validatePassword = () => {
const validPassword = isValidPassword(password);
if (!validPassword) {
setPasswordError("비밀번호는 영문,숫자 조합 8자 이상 입력해 주세요.");
} else {
setPasswordError("");
}
};

const checkPassword = () => {
if (password !== confirmPassword) {
setConfirmPasswordError("비밀번호가 일치하지 않아요.");
} else {
setConfirmPasswordError("");
}
};

return (
<>
<PasswordInput
value={password}
onChange={onPasswordChange}
onBlur={validatePassword}
error={passwordError}
/>
<PasswordInput
value={confirmPassword}
onChange={onConfirmPasswordChange}
onBlur={checkPassword}
error={confirmPasswordError}
id="password-confirm"
/>
</>
);
}
16 changes: 16 additions & 0 deletions components/passwordToggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
$(document).ready(function () {
$(".password-section i").on("click", function () {
$("input").toggleClass("active");
if ($("input").hasClass("active")) {
$(this)
.attr("class", "fa fa-eye-slash fa-lg")
.prev("input")
.attr("type", "text");
} else {
$(this)
.attr("class", "fa fa-eye fa-lg")
.prev("input")
.attr("type", "password");
}
});
});
Loading

0 comments on commit 5b4db1f

Please sign in to comment.