diff --git a/client/package-lock.json b/client/package-lock.json index 2b0b49b..8f84442 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.14.15", "@mui/material": "^5.14.15", "framer-motion": "^10.16.4", "next": "14.0.0", @@ -3646,6 +3647,31 @@ "url": "https://opencollective.com/mui" } }, + "node_modules/@mui/icons-material": { + "version": "5.14.16", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.16.tgz", + "integrity": "sha512-wmOgslMEGvbHZjFLru8uH5E+pif/ciXAvKNw16q6joK6EWVWU5rDYWFknDaZhCvz8ZE/K8ZnJQ+lMG6GgHzXbg==", + "dependencies": { + "@babel/runtime": "^7.23.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/material": { "version": "5.14.16", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.16.tgz", diff --git a/client/package.json b/client/package.json index 982f308..5d7a2da 100644 --- a/client/package.json +++ b/client/package.json @@ -16,6 +16,7 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/material": "^5.14.15", + "@mui/icons-material": "^5.14.15", "framer-motion": "^10.16.4", "next": "14.0.0", "react": "^18", diff --git a/client/src/app/auth/login/page.tsx b/client/src/app/auth/login/page.tsx new file mode 100644 index 0000000..0cd2b73 --- /dev/null +++ b/client/src/app/auth/login/page.tsx @@ -0,0 +1,65 @@ +import { Avatar, Box, Grid, Paper, Typography } from "@mui/material"; +import SigninForm from "@/components/user/signin/SigninForm"; +import Link from "next/link"; +import { SIGNUP, FORGOTPASSWORD } from "@/const/clientPath"; +import { Metadata } from "next"; +import { nameOfApp } from "@/const/brand"; +import { LockOutlined as LockOutlinedIcon } from "@mui/icons-material"; + +export const metadata: Metadata = { + title: `${nameOfApp} | 로그인`, +}; + +const LoginPage = () => { + return ( + + + + + {/* heading */} + + + + + Sign in + + {/* form */} + + + + + Forgot password? + + + + + 계정이 없으신가요? 회원가입 + + + + + + + ); +}; + +export default LoginPage; diff --git a/client/src/app/hi/page.tsx b/client/src/app/hi/page.tsx deleted file mode 100644 index eb5dd3d..0000000 --- a/client/src/app/hi/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Button } from "@mui/material"; -import React from "react"; - -type Props = {}; - -const HiPage = (props: Props) => { - return ( - - ); -}; - -export default HiPage; diff --git a/client/src/components/user/signin/SigninForm.tsx b/client/src/components/user/signin/SigninForm.tsx new file mode 100644 index 0000000..9a0c2d7 --- /dev/null +++ b/client/src/components/user/signin/SigninForm.tsx @@ -0,0 +1,62 @@ +"use client"; +import useLogin from "@/hooks/useLogin"; +import { + Box, + Button, + Checkbox, + FormControlLabel, + TextField, +} from "@mui/material"; + +import { useState } from "react"; + +const SigninForm = () => { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const handleSubmit = useLogin(); + + return ( + { + event.preventDefault(); + handleSubmit({ email, password }); + }} + sx={{ mt: 1 }} + > + setEmail(target.value)} + margin="normal" + required + fullWidth + id="email" + label="Email Address" + name="email" + autoComplete="email" + autoFocus + /> + setPassword(target.value)} + margin="normal" + required + fullWidth + name="password" + label="Password" + type="password" + id="password" + autoComplete="current-password" + /> + } + label="Remember me" + /> + + + ); +}; + +export default SigninForm; diff --git a/client/src/hooks/useLogin.ts b/client/src/hooks/useLogin.ts new file mode 100644 index 0000000..f4873e9 --- /dev/null +++ b/client/src/hooks/useLogin.ts @@ -0,0 +1,13 @@ +import { SigninRequirement } from "@/types/auth/signin" + +/** + * 로그인 관련 로직들이 모여있는 Hook + * @returns login Handler + */ +export default function useLogin () { + const loginHandler = (props:SigninRequirement)=>{ + const {email,password} = props + console.log(`email : ${email}, password : ${password}`) + } + return loginHandler +} diff --git a/client/src/stories/Components/Auth/LoginForm.stories.tsx b/client/src/stories/Components/Auth/LoginForm.stories.tsx new file mode 100644 index 0000000..abb5f4d --- /dev/null +++ b/client/src/stories/Components/Auth/LoginForm.stories.tsx @@ -0,0 +1,35 @@ +import SigninForm from "@/components/user/signin/SigninForm"; +import { Box, Paper } from "@mui/material"; +import { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Components/Auth/LoginForm", + component: SigninForm, + tags: ["autodocs"], + decorators: [ + (Story) => { + return ( + + + + + + ); + }, + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoginForm: Story = { + args: {}, +}; diff --git a/client/src/types/auth/signin.ts b/client/src/types/auth/signin.ts new file mode 100644 index 0000000..0a8dcd0 --- /dev/null +++ b/client/src/types/auth/signin.ts @@ -0,0 +1,4 @@ +export interface SigninRequirement { + email: string; + password: string; +}