Skip to content

Commit

Permalink
style: login page
Browse files Browse the repository at this point in the history
  • Loading branch information
pmh-only committed Aug 20, 2023
1 parent 41baa9e commit 96b1644
Show file tree
Hide file tree
Showing 13 changed files with 257 additions and 312 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@fontsource/noto-sans-kr": "^5.0.7",
"@types/node": "^20.4.9",
"axios": "^1.4.0",
"framer-motion": "^10.16.0",
"normalize.css": "^8.0.1",
"react": "^18.2.0",
"react-cookie": "^4.1.1",
Expand Down
Binary file added public/assets/images/logos/black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 3 additions & 14 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import Login from './pages/Login'
import Instances from './pages/Instances'
import { BrowserRouter } from 'react-router-dom'
import Header from './components/Header'
import Invites from './pages/Invites'
import Search from './pages/Search'
import PathProcesor from './components/PathProcessor'
import { type FC } from 'react'
import { Toaster } from 'react-hot-toast'
import Routers from './components/Routers'

const App: FC = () =>
<BrowserRouter>
<Header />
<PathProcesor />

<Routes>
<Route path='/login' element={<Login />} />
<Route path='/instances' element={<Instances />}></Route>
<Route path="/instances/search/:search" element={<Search />}></Route>
<Route path='/invites/:uuid' element={<Invites />}></Route>
</Routes>
<Routers/>

<Toaster
position="bottom-right"
Expand Down
22 changes: 22 additions & 0 deletions src/components/Container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import style from './style.module.scss'
import { motion } from 'framer-motion'
import { type ReactNode, type FC } from 'react'

interface Props {
children: ReactNode
}

const Container: FC<Props> = ({ children }) => {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ bounce: 0 }}
className={style.container}>
{children}
</motion.div>
)
}

export default Container
6 changes: 6 additions & 0 deletions src/components/Container/style.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.container {
width: 100%;
height: 100%;
position: relative;
top: 0;
}
30 changes: 0 additions & 30 deletions src/components/PathProcessor.tsx

This file was deleted.

45 changes: 45 additions & 0 deletions src/components/Routers/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import axios from 'axios'
import { type FC } from 'react'
import useSWR from 'swr'
import Login from '../../pages/Login'
import Instances from '../../pages/Instances'
import Invites from '../../pages/Invites'
import Search from '../../pages/Search'
import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'
import { AnimatePresence } from 'framer-motion'

const Routers: FC = () => {
const navigate = useNavigate()
const location = useLocation()

async function fetcher (path: string): Promise<void> {
const res = await axios(path, { method: 'GET' })
.catch(() => ({ status: 400 }))

if (res.status !== 200) {
if (location.pathname !== '/login')
navigate('/login')

return
}

if (location.pathname === '/login' || location.pathname === '/')
navigate('/instances?page=0')
}

useSWR('/api/auth/status', fetcher)

return (
<AnimatePresence mode="wait">
<Routes location={location} key={location.key}>
<Route path='/login' element={<Login />} />
<Route path='/instances' element={<Instances />}></Route>
<Route path="/instances/search/:search" element={<Search />}></Route>
<Route path='/invites/:uuid' element={<Invites />}></Route>
<Route path="*" element={<Navigate to="/instances" replace />} />
</Routes>
</AnimatePresence>
)
}

export default Routers
4 changes: 4 additions & 0 deletions src/global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
@import '@fontsource/noto-sans-kr/400.css';
@import '@fontsource/noto-sans-kr/700.css';

:root {
--color-primary: #007dbc;
}

* {
box-sizing: border-box;
}
Expand Down
253 changes: 0 additions & 253 deletions src/pages/Login.tsx

This file was deleted.

56 changes: 56 additions & 0 deletions src/pages/Login/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { type FormEvent, useState, type FC } from 'react'
import axios from 'axios'
import { useNavigate } from 'react-router-dom'
import style from './style.module.scss'
import Container from '../../components/Container'

const Login: FC = () => {
const [password, setPassword] = useState<string>('')
const navigate = useNavigate()

async function onSubmit (e: FormEvent<HTMLFormElement>): Promise<void> {
e.preventDefault()

await axios('/api/auth/login', {
method: 'POST',
data: {
password
}
}).then(() => { navigate('/instances?page=0') })
.catch(() => { alert('비밀번호가 일치하지 않습니다.') })
}

return (
<Container>
<div className={style.content}>
<img src="/assets/images/logos/black.png" alt="AWS Logo" className={style.logo} />
<form className={style.form} onSubmit={(e) => { void onSubmit(e) }}>
<div className={style.header}>
<h1>로그인</h1>
<p>awsmgr is not associated with Amazon Web Service.</p>
</div>

<div className={style.fields}>
<label className={style.formItem}>
<p>사용자 이름 (고정)</p>
<input type="text" placeholder="admin" value={'admin'} disabled style={{ color: 'gray' }} />
</label>

<label className={style.formItem}>
<label>비밀번호</label>
<input type="password" value={password} onChange={(e) => { setPassword(e.target.value) }} />
</label>

<button className={style.submitBtn}>로그인</button>
</div>
</form>

<div className={style.footer}>
<small>계속 진행하면 <a href="https://aws.amazon.com/agreement/" target="_blank" rel="noreferrer">AWS 이용계약</a> 또는 AWS 서비스에 대한 기타 계약 및 <a href="https://aws.amazon.com/privacy/" target="_blank" rel="noreferrer">개인정보 처리방침</a>에 동의하게 됩니다. 이 사이트는 필수 쿠키를 사용합니다. 자세한 내용은 <a href="https://aws.amazon.com/legal/cookies" target="_blank" rel="noreferrer">쿠키 고지</a>를 참조하세요.</small>
</div>
</div>
</Container>
)
}

export default Login
99 changes: 99 additions & 0 deletions src/pages/Login/style.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
.content {
width: 100%;
height: 100%;

display: flex;
justify-content: center;
align-items: center;
flex-direction: column;

background-image: url('/assets/images/signin-background.png');
background-repeat: no-repeat;
background-position: bottom;
background-size: cover;

gap: 20px;

> div, > form {
max-width: 300px;
}

.logo {
width: 87px;
}

.form {
background-color: white;
box-shadow: 0 1px 1px 0 rgba(0,28,36,0.3), 1px 1px 1px 0 rgba(0,28,36,0.15), -1px 1px 1px 0 rgba(0,28,36,0.15);
border-top: 1px solid #eaeded;
display: flex;
flex-direction: column;
gap: 20px;

.header {
background-color: #fafafa;
border-bottom: 1px solid #eaeded;
padding: .7rem 1rem;

h1 {
font-size: 20px;
font-weight: 700;
}

p {
font-size: 12px;
}
}

.fields {
padding: 0px 20px 20px 20px;
display: flex;
flex-direction: column;
gap: 20px;

.formItem {
font-size: 15px;
line-height: 1rem;
color: #16191f;
display: flex;
flex-direction: column;
gap: 5px;

> input {
width: 100%;
font-size: 14px;
padding: 0.55rem 0.5rem;
background-color: white;
border-radius: 2px;
border: 1px solid #aab7b8;
}
}

.submitBtn {
width: 100%;
padding: 5px 0px;
cursor: pointer;
border: 1px solid #ff9900;
background-color: #ff9900;

&:hover {
background-color: #ec7211;
border-color: #ec7211;
text-decoration: none;
}

&:active {
background: #eb5f07;
border-color: #eb5f07;
}
}
}
}

.footer {
a {
color: var(--color-primary);
font-weight: 700;
}
}
}
15 changes: 0 additions & 15 deletions src/utils/cookies.ts

This file was deleted.

21 changes: 21 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1198,13 +1198,25 @@
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==

"@emotion/is-prop-valid@^0.8.2":
version "0.8.8"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
dependencies:
"@emotion/memoize" "0.7.4"

"@emotion/is-prop-valid@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc"
integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==
dependencies:
"@emotion/memoize" "^0.8.1"

"@emotion/[email protected]":
version "0.7.4"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==

"@emotion/memoize@^0.8.1":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
Expand Down Expand Up @@ -2748,6 +2760,15 @@ form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"

framer-motion@^10.16.0:
version "10.16.0"
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.16.0.tgz#c8020d05d98662ba01d294b7d4c2e263073829cf"
integrity sha512-R+88Mkr/1dr7XHjacwptfJyrywRzQ1HZX3YSZtN4tFMBq1O8GGCbDEv31Nf/H08o0hUXLC87GkxsR/1bZgwXfw==
dependencies:
tslib "^2.4.0"
optionalDependencies:
"@emotion/is-prop-valid" "^0.8.2"

fs-readdir-recursive@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27"
Expand Down

0 comments on commit 96b1644

Please sign in to comment.