[개인 포트폴리오] [클라이밍 커뮤니티 SNS] 2. 코드 분석 <login.js>

2024. 12. 20. 10:31웹개발 포트폴리오

728x90

 

import { auth } from "../firebase";
import React from "react";
import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { FirebaseError } from "firebase/app";
import { signInWithEmailAndPassword } from "firebase/auth";
import GithubButton from "../component/github-btn";
import styled from "styled-components";

const Switcher = styled.p` 
    color: white;

    a {
        color: white;
        text-decoration: none;
    }

    a:hover {
        text-decoration: underline;
    }
`;

const Logo = styled.img`
  position: absolute;
  width: 25vw;
  top: 10vw;
  right: 45vh;

  @media (max-width: 768px) {
    display: none;
  }
`;

const Wrapper = styled.div`
  color: white;
  margin: 0 5vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  position: relative;
  z-index: 1;

  @media (max-width: 768px) {
    margin: 0 2vw;
  }
`;

const Background = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-image: url('/background.jpg');
  background-size: cover;
  background-position: center;
  filter: blur(1px); /* 배경만 흐림 효과 적용 */
  z-index: -1; /* 배경이 콘텐츠 뒤에 위치하도록 설정 */

      &::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.5); /* 50% 어두운 효과 */
        z-index: 1;
    }
    
    /* Wrapper 내의 모든 컨텐츠는 오버레이 위에 위치 */
    & > * {
        position: relative;
        z-index: 2;
    }
`;

const Input = styled.input`
  padding: 10px;
  margin: 10px;
  width: 25vw;
  border: 1px solid #ccc;
  border-radius: 5px;

  @media (max-width: 768px) {
    width: 70vw;
  }
`;

const Form = styled.form`
  display: flex;
  flex-direction: column;
  align-items: center;
`;

export default function Login() {
    const navigate = useNavigate();
    // React Router에서 제공하는 훅으로, 프로그래밍 방식으로 경로를 이동(네비게이션) 하기 위해 사용
    
    const [isLoading, setLoading] = useState(false);
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [error, setError] = useState("");

    const onChange = (e) => {
        const { name, value } = e.target;
        if (name === "email") {
            setEmail(value);
        } else if (name === "password") {
            setPassword(value);
        }
    };

    const onSubmit = async (e) => {
        e.preventDefault();
        // 새로고침 방지
        setError("");
        if (email === "" || password === "") {
            setError("이메일과 패스워드를 입력해주세요.");
            return;
        }
        try {
            setLoading(true);
            await signInWithEmailAndPassword(auth, email, password);
            navigate("/");  // 로그인 성공 후 홈으로 이동
        } catch (e) {
            if (e instanceof FirebaseError) {
                switch (e.code) {
                    case "auth/user-not-found":
                        setError("존재하지 않는 계정입니다.");
                        break;
                    case "auth/wrong-password":
                        setError("비밀번호가 틀렸습니다.");
                        break;
                    case "auth/invalid-email":
                        setError("유효하지 않은 이메일입니다.");
                        break;
                    default:
                        setError("로그인 중 오류가 발생했습니다. 다시 시도해 주세요.");
                        break;
                }
            }
        } finally {
            setLoading(false);
        }
    };

    return (
        <>
        <Background />
        <Wrapper>
            <h1>다시 만나 반가워요!</h1>
            <Form onSubmit={onSubmit}>
                <Input
                    onChange={onChange}
                    name="email"
                    value={email}
                    placeholder="이메일"
                    type="email"
                    required
                />
                <Input
                    onChange={onChange}
                    name="password"
                    value={password}
                    placeholder="패스워드"
                    type="password"
                    required
                />
                <Input type="submit" value={isLoading ? "로딩중..." : "로그인"} />
            </Form>
            {error && <p style={{ color: "red" }}>{error}</p>}
            <Switcher>
                <Link to="/create-account"> 아직 계정이 없나요? </Link>
            </Switcher>
            <GithubButton />
        </Wrapper>
        <Logo src="/logo.png" alt="Logo" />
        </>
    );
}
728x90