Skip to content

Commit

Permalink
로그인/회원가입 페이지를 만듭니다. (#133)
Browse files Browse the repository at this point in the history
* feat: `login` 페이지 구현

* feat: `register` 페이지 구현

* fix: gnb active 스타일 수정
  • Loading branch information
ludacirs authored Sep 19, 2023
1 parent e396603 commit 019b02a
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 76 deletions.
37 changes: 11 additions & 26 deletions apps/realworld/src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
import { LoginForm } from '@/features/user';
import { PathBuilder } from '@/shared/utils/routes';
import React from 'react';

const Login = () => {
return (
<React.Fragment>
<div className="auth-page">
<div className="container page">
<div className="row">
<div className="col-md-6 offset-md-3 col-xs-12">
<h1 className="text-xs-center">Sign in</h1>
<p className="text-xs-center">
<a href={PathBuilder.buildRegister().getPath()}>Need an account?</a>
</p>

<ul className="error-messages">
<li>That email is already taken</li>
</ul>

<form>
<fieldset className="form-group">
<input className="form-control form-control-lg" type="text" placeholder="Email" />
</fieldset>
<fieldset className="form-group">
<input className="form-control form-control-lg" type="password" placeholder="Password" />
</fieldset>
<button className="btn btn-lg btn-primary pull-xs-right">Sign in</button>
</form>
</div>
</div>
<div className="flex flex-col items-center w-full">
<div className="flex flex-col gap-16 w-540">
<div className="flex flex-col gap-8">
<h1 className="text-[2.5rem] text-center">Sign in</h1>
<p className="text-center text-green600">
<a href={PathBuilder.buildRegister().getPath()}>Need an account?</a>
</p>
</div>

<LoginForm />
</div>
</React.Fragment>
</div>
);
};

Expand Down
57 changes: 13 additions & 44 deletions apps/realworld/src/app/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,21 @@
import React from "react";
import { RegisterForm } from '@/features/user';
import { PathBuilder } from '@/shared/utils/routes';
import React from 'react';

const Register = () => {
return (
<React.Fragment>
<div className="auth-page">
<div className="container page">
<div className="row">
<div className="col-md-6 offset-md-3 col-xs-12">
<h1 className="text-xs-center">Sign up</h1>
<p className="text-xs-center">
<a href="/login">Have an account?</a>
</p>

<ul className="error-messages">
<li>That email is already taken</li>
</ul>

<form>
<fieldset className="form-group">
<input
className="form-control form-control-lg"
type="text"
placeholder="Username"
/>
</fieldset>
<fieldset className="form-group">
<input
className="form-control form-control-lg"
type="text"
placeholder="Email"
/>
</fieldset>
<fieldset className="form-group">
<input
className="form-control form-control-lg"
type="password"
placeholder="Password"
/>
</fieldset>
<button className="btn btn-lg btn-primary pull-xs-right">
Sign up
</button>
</form>
</div>
</div>
<div className="flex flex-col items-center w-full">
<div className="flex flex-col gap-16 w-540">
<div className="flex flex-col gap-8">
<h1 className="text-[2.5rem] text-center">Sign up</h1>
<p className="text-center text-green600">
<a href={PathBuilder.buildLogin().getPath()}>Have an account?</a>
</p>
</div>

<RegisterForm />
</div>
</React.Fragment>
</div>
);
};

Expand Down
4 changes: 3 additions & 1 deletion apps/realworld/src/features/user/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import LoginForm from './login-form/login-form';
import RegisterForm from './register-form/register-form';
import UserFollowToggleButton from './user-follow-toggle-button/user-follow-toggle-button';

export { UserFollowToggleButton };
export { UserFollowToggleButton, LoginForm, RegisterForm };
53 changes: 53 additions & 0 deletions apps/realworld/src/features/user/ui/login-form/login-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client';

import { useLogin } from '@/shared/api/realworld/endpoints/user-and-authentication/user-and-authentication';
import { Button, Input } from '@packages/ui';
import React, { useState } from 'react';

const LoginForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { mutateAsync: login, error: loginError, isLoading: loginLoading } = useLogin();

const handleChangeEmail = (_: React.ChangeEvent<HTMLInputElement>, email: string) => {
setEmail(email);
};

const handleChangePassword = (_: React.ChangeEvent<HTMLInputElement>, password: string) => {
setPassword(password);
};

const handleSubmitLogin = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
login({ data: { user: { email, password } } });
};

const buttonDisabled = loginLoading;

return (
<div className="flex flex-col gap-16">
{Boolean(loginError) && <p className="ml-16 font-bold text-red600"> • email or password is invalid</p>}

<form onSubmit={handleSubmitLogin} className="flex flex-col gap-16">
<fieldset className="form-group">
<Input required value={email} size="lg" placeholder="Email" onChange={handleChangeEmail} type="email" />
</fieldset>
<fieldset className="form-group">
<Input
required
value={password}
size="lg"
type="password"
placeholder="Password"
onChange={handleChangePassword}
/>
</fieldset>
<Button className="ml-auto" type="submit" variant="fill" color="primary" size="lg" disabled={buttonDisabled}>
Sign in
</Button>
</form>
</div>
);
};

export default LoginForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';
import { useCreateUser } from '@/shared/api/realworld/endpoints/user-and-authentication/user-and-authentication';
import { Button, Input } from '@packages/ui';
import React, { useState } from 'react';

const RegisterForm = () => {
const [email, setEmail] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const { mutateAsync: createUser, error: createUserError, isLoading: createUserLoading } = useCreateUser();

const handleChangeUsername = (_: React.ChangeEvent<HTMLInputElement>, username: string) => {
setUsername(username);
};

const handleChangeEmail = (_: React.ChangeEvent<HTMLInputElement>, email: string) => {
setEmail(email);
};

const handleChangePassword = (_: React.ChangeEvent<HTMLInputElement>, password: string) => {
setPassword(password);
};

const handleSubmitCreateUser = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
createUser({ data: { user: { email, password, username } } });
};

const buttonDisabled = createUserLoading;

return (
<div className="flex flex-col gap-16">
{Boolean(createUserError) && <p className="ml-16 font-bold text-red600"> • That email is already taken</p>}

<form className="flex flex-col gap-16" onSubmit={handleSubmitCreateUser}>
<fieldset className="form-group">
<Input
required
value={username}
size="lg"
placeholder="Username"
onChange={handleChangeUsername}
type="text"
/>
</fieldset>
<fieldset className="form-group">
<Input required value={email} size="lg" placeholder="Email" onChange={handleChangeEmail} type="email" />
</fieldset>
<fieldset className="form-group">
<Input
required
value={password}
size="lg"
type="password"
placeholder="Password"
onChange={handleChangePassword}
/>
</fieldset>
<Button className="ml-auto" type="submit" variant="fill" color="primary" size="lg" disabled={buttonDisabled}>
Sign up
</Button>
</form>
</div>
);
};

export default RegisterForm;
1 change: 1 addition & 0 deletions apps/realworld/src/widgets/gnb/api/isActiveLink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const isActiveLink = (currentPath: string, path: string) => currentPath === path;
17 changes: 12 additions & 5 deletions apps/realworld/src/widgets/gnb/ui/gnb/gnb.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
'use client';

import { responsiveWidth } from '@/shared/css/responsive-width';
import { PathBuilder } from '@/shared/utils/routes';
import { PathBuilder, RoutePath } from '@/shared/utils/routes';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import React from 'react';
import { isActiveLink } from '../../api/isActiveLink';

const GNB = () => {
const pathname = usePathname();
const activeLinkStyle = (path: RoutePath) => {
return isActiveLink(pathname, path) ? 'text-black' : 'text-black/30';
};

return (
<nav className="flex items-center justify-center w-full h-56">
<div className={`flex justify-between ${responsiveWidth}`}>
<Link data-testid="gnbLogo" href={PathBuilder.buildHome().getPath()} className="no-underline ">
<Link data-testid="gnbLogo" href={PathBuilder.buildHome().getPath()} className="no-underline">
<p className="text-2xl font-bold text-green600">conduit</p>
</Link>
<ul className="flex gap-16">
<li>
<Link data-testid="gnbHome" href={PathBuilder.buildHome().getPath()} className="no-underline">
<p className="text-black">Home</p>
<p className={`hover:text-black ${activeLinkStyle('/')}`}>Home</p>
</Link>
</li>
<li>
<Link data-testid="gnbSignIn" href={PathBuilder.buildLogin().getPath()} className="no-underline">
<p className="text-black">Sign in</p>
<p className={`hover:text-black ${activeLinkStyle('/login')}`}>Sign in</p>
</Link>
</li>
<li>
<Link data-testid="gnbSignUp" href={PathBuilder.buildRegister().getPath()} className="no-underline">
<p className="text-black">Sign up</p>
<p className={`hover:text-black ${activeLinkStyle('/register')}`}>Sign up</p>
</Link>
</li>
</ul>
Expand Down

0 comments on commit 019b02a

Please sign in to comment.