Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[강성구] Sprint8 #256

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 30 additions & 0 deletions src/components/auth/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Link } from 'react-router-dom';

import logoImg from '../../core/assets/images/logo/[email protected]';
import styled from 'styled-components';

const Wrapper = styled.header`
display: flex;
justify-content: center;
align-items: center;
margin: 3.75rem 0.5rem;
`;

const Logo = styled.img`
width: 40rem;
@media (375px <= width < 768px) {
width: 30rem;
}
`;

const Header = () => {
return (
<Wrapper>
<Link to='/'>
<Logo src={logoImg} alt="판다마켓 로고" />
</Link>
</Wrapper>
);
}

export default Header;
53 changes: 53 additions & 0 deletions src/components/auth/OAuth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Link } from 'react-router-dom';

import kakaoIcon from '../../core/assets/icons/sns/kakao/kakao.svg';
import googleIcon from '../../core/assets/icons/sns/google/google.svg';
import styled from 'styled-components';

const OAuthLoginContainer = styled.div`
display: flex;
background-color: #e6f2ff;
border-radius: 0.8rem;
padding: 0.8rem 3.2rem ;
justify-content: space-between;
align-items: center;
`;

const OAuthIcons = styled.div`
display: flex;
align-items: center;
gap: 1.6rem;
`;

const OAuthIcon = styled.img`
cursor: pointer;
width: 4.4rem;
height: 4.4rem;
`;

const ToggleSign = styled.div`
text-align: center;
`;

interface OAuthProps {
isLogin: boolean;
}

const OAuth = ({isLogin}:OAuthProps) => {
return (
<>
<OAuthLoginContainer>
<p>간편 로그인하기</p>
<OAuthIcons>
<a href="https://www.google.com/"><OAuthIcon src={googleIcon} alt="구글 아이콘"/></a>
<a href="https://www.kakaocorp.com/page/"><OAuthIcon src={kakaoIcon} alt="카카오 아이콘"/></a>
</OAuthIcons>
</OAuthLoginContainer>
<ToggleSign>
<p>{isLogin ? '판다마켓이 처음이신가요?' : '이미 회원이신가요?'} <Link to={isLogin?'/signUp':'/signIn'}>{isLogin?'회원가입':'로그인'}</Link></p>
</ToggleSign>
</>
);
}

export default OAuth;
41 changes: 41 additions & 0 deletions src/components/auth/signIn/SignInForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import usePasswordVisibility from 'lib/hooks/usePasswordVisibility';

import BtnLarge from 'core/buttons/BtnLarge';

import { Container, ErrorMessage, Form, Icon, Input, InputWrapper, Label } from '../styles';

const SignInForm = () => {
const {ref,icon, handlePasswordVisibility} = usePasswordVisibility();
const navigate = useNavigate();
const [isValid, setIsValid] = useState<boolean>(false);
const emailErrorMessage = '';
const passwordErrorMessage = '';

const handleSubmit = (e:React.MouseEvent<HTMLFormElement, MouseEvent>) => {
e.preventDefault();
navigate('/items');
}

return (
<Form onSubmit={handleSubmit}>
<Container>
<Label htmlFor="email">이메일</Label>
<Input type="email" id="email" name="email" placeholder="이메일을 입력해주세요"/>
<ErrorMessage>{emailErrorMessage}</ErrorMessage>
</Container>
<Container>
<Label htmlFor="password">비밀번호</Label>
<InputWrapper>
<Input ref={ref} type='password' id="password" name="password" placeholder="비밀번호를 입력해주세요"/>
<Icon src={icon} onClick={handlePasswordVisibility}/>
</InputWrapper>
<ErrorMessage>{passwordErrorMessage}</ErrorMessage>
</Container>
<BtnLarge bgColor={'var(--gray-400)'} color={'var(--font-button)'} disabled={!isValid}>로그인</BtnLarge>
</Form>
);
}

export default SignInForm;
96 changes: 96 additions & 0 deletions src/components/auth/signUp/SignUpForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { useState } from "react";

import usePasswordVisibility from "lib/hooks/usePasswordVisibility";
import useValidate, { InputValue } from "lib/hooks/useValidate";
import BtnLarge from "core/buttons/BtnLarge";

import { Container, ErrorMessage, Form, Input, InputWrapper, Label, Icon } from "../styles";

const INITIAL_VALUE = {
email: '',
nickname: '',
password: '',
passwordConfirm: '',
}

const SignUpForm = () => {
const [value, setValue] = useState<InputValue>(INITIAL_VALUE);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InputValue가 코드상에 없는거보니까 리팩토링하면서 삭제하신것 같네요 ! 꼼꼼한 타입지정 잘 하셨습니다 !

const {ref:passwordRef,icon:passwordIcon, handlePasswordVisibility:handlePasswordView} = usePasswordVisibility();
const {ref:passwordConfirmRef, icon:passwordConfirmIcon, handlePasswordVisibility:handlePasswordConfirmView} = usePasswordVisibility();

const {errorMessage, isValidate} = useValidate({mode: "signup", value});

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

switch (target.name) {
case 'email':
setValue((prev) => ({
...prev,
email: target.value,
}))
break;
case 'nickname':
setValue((prev) => ({
...prev,
nickname: target.value,
}))
break;
case 'password':
setValue((prev) => ({
...prev,
password: target.value,
}))
break;
case 'passwordConfirm':
setValue((prev) => ({
...prev,
passwordConfirm: target.value,
}))
break;
default:
break;
}
}

const handleSubmit = (e:React.MouseEvent<HTMLFormElement, MouseEvent>) => {
e.preventDefault();
if (isValidate) {

}
}

return (
<Form onSubmit={handleSubmit}>
<Container>
<Label htmlFor="email">이메일</Label>
<Input type="email" name="email" value={value.email} onChange={handleChange} id="email" placeholder="이메일을 입력해주세요"/>
<ErrorMessage>{errorMessage.email}</ErrorMessage>
</Container>
<Container>
<Label htmlFor="nickname">닉네임</Label>
<Input type="nickname" name="nickname" value={value.nickname} onChange={handleChange} id="nickname" placeholder="닉네임을 입력해주세요"/>
<ErrorMessage>{errorMessage.nickname}</ErrorMessage>
</Container>
<Container>
<Label htmlFor="password">비밀번호</Label>
<InputWrapper>
<Input ref={passwordRef} type="password" id="password" value={value.password} onChange={handleChange} name="password" placeholder="비밀번호를 입력해주세요"/>
<Icon src={passwordIcon} onClick={handlePasswordView}/>
</InputWrapper>
<ErrorMessage>{errorMessage.password}</ErrorMessage>
</Container>
<Container>
<Label htmlFor="password-confirm">비밀번호 확인</Label>
<InputWrapper>
<Input ref={passwordConfirmRef} type="password" id="passwordConfirm" value={value.passwordConfirm} onChange={handleChange} name="passwordConfirm" placeholder="비밀번호를 다시 한 번 입력해주세요"/>
<Icon src={passwordConfirmIcon} onClick={handlePasswordConfirmView}/>
</InputWrapper>
<ErrorMessage>{errorMessage.passwordConfirm}</ErrorMessage>
</Container>
<BtnLarge bgColor={isValidate ? 'var(--main-color)':'var(--gray-400)' } color={'var(--font-button)'} disabled={!isValidate} >회원가입</BtnLarge>
</Form>
);
}

export default SignUpForm;
64 changes: 64 additions & 0 deletions src/components/auth/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { styled } from "styled-components";

export const Form = styled.form`
display: flex;
flex-direction: column;
gap: 2.4rem;
margin-bottom: 2rem;
@media (375px <= width < 768px) {
max-width: 40rem;
width: 100%;
}
`;

export const Label = styled.label`
display: block;
font-weight: 700;
font-size: 1.8rem;
color: var(--gray-800);
line-height: 2.148rem;
`;

export const InputWrapper = styled.div`
position: relative;
`;

export const Input = styled.input`
width:100%;
color: var(--gray-400);
background-color: var(--gray-100);
font-weight: 400;
line-height: 2.4rem;
height: 5.6rem;
border-radius: 1.2rem;
border: none;
padding-left: 2.4rem;
:focus {
border: var(--blue);
}
`;

export const Icon = styled.img`
width: 2.4rem;
height: 2.4rem;
position: absolute;
right: 1.6rem;
bottom: 1.6rem;
margin: auto 0.2rem;
cursor: pointer;
`;

export const ErrorMessage = styled.p`
visibility: hidden;
margin: 0 0 0 1.6rem;
color: var(--error-red);
font-size: 1.5rem;
font-weight: 600;
line-height: 1.79rem;
`;

export const Container = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
`;
2 changes: 1 addition & 1 deletion src/components/nav/LoginBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface LoginBtnProps {

const LoginBtn = ({ onClick }: LoginBtnProps) => {
return (
<Link to="/auth">
<Link to="/signIn">
<BtnSmall onClick={onClick} disabled={false}>
로그인
</BtnSmall>
Expand Down
10 changes: 10 additions & 0 deletions src/core/assets/icons/sns/google/google.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/core/assets/icons/sns/kakao/kakao.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/core/assets/icons/visibility/disvisibility.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading