Skip to content

Commit 7e037d2

Browse files
authored
Merge pull request #10 from Bibimbap-Team/6-create-login-page
Create login page
2 parents 75b1bb2 + 2315e4f commit 7e037d2

File tree

8 files changed

+215
-55
lines changed

8 files changed

+215
-55
lines changed

__tests__/pages/landing.test.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import '@testing-library/jest-dom';
22
import { render, screen } from '@testing-library/react';
33
import Home from '@/app/page';
44

5-
it('renders main page with the text "Get started by editing"', () => {
5+
it('renders 6 change logs', () => {
66
render(<Home />);
7-
const login = screen.getAllByText(/\bLogin\b/i).length;
8-
expect(login).toBe(2);
9-
10-
const register = screen.getAllByText(/\bRegister\b/i).length;
11-
expect(register).toBe(2);
7+
// Finds all p tags with date logs
8+
const numListItems = screen
9+
.getByTestId('changelog')
10+
.querySelectorAll('p').length;
11+
expect(numListItems).toBe(6);
1212
});

src/app/layout.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { Metadata } from 'next';
22
import { AppRouterCacheProvider } from '@mui/material-nextjs/v13-appRouter';
3-
import { ThemeProvider } from '@mui/material';
3+
import { Container, ThemeProvider } from '@mui/material';
44
import theme from '../theme';
55
import './globals.css';
6+
import Navigation from '@/components/Navigation';
67

78
export const metadata: Metadata = {
89
title: 'Bibimbap',
@@ -18,7 +19,12 @@ export default function RootLayout({
1819
<html lang='en'>
1920
<body>
2021
<AppRouterCacheProvider>
21-
<ThemeProvider theme={theme}>{children}</ThemeProvider>
22+
<ThemeProvider theme={theme}>
23+
<Container component='main'>
24+
<Navigation />
25+
{children}
26+
</Container>
27+
</ThemeProvider>
2228
</AppRouterCacheProvider>
2329
</body>
2430
</html>

src/app/login/SubmitBox.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use client';
2+
import { FormEvent } from 'react';
3+
import { Box } from '@mui/material';
4+
5+
// This file holds the handling logic for the login form submission.
6+
export default function LoginSubmitBox({
7+
children,
8+
}: {
9+
children: React.ReactNode;
10+
}) {
11+
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
12+
event.preventDefault();
13+
const data = new FormData(event.currentTarget);
14+
console.log({
15+
email: data.get('email'),
16+
password: data.get('password'),
17+
});
18+
};
19+
20+
return (
21+
<Box component='form' onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
22+
{children}
23+
</Box>
24+
);
25+
}

src/app/login/page.tsx

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import {
2+
Avatar,
3+
Box,
4+
Button,
5+
Checkbox,
6+
FormControlLabel,
7+
Grid,
8+
TextField,
9+
Typography,
10+
} from '@mui/material';
11+
import { LockOutlined } from '@mui/icons-material';
12+
import Copyright from '@/components/Copyright';
13+
import CustomLink from '@/components/CustomLink';
14+
import LoginSubmitBox from './SubmitBox';
15+
16+
export default function Login() {
17+
return (
18+
<>
19+
<Box
20+
sx={{
21+
mt: 8,
22+
display: 'flex',
23+
flexDirection: 'column',
24+
alignItems: 'center',
25+
}}
26+
>
27+
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
28+
<LockOutlined />
29+
</Avatar>
30+
<Typography component='h1' variant='h5'>
31+
Login
32+
</Typography>
33+
<LoginSubmitBox>
34+
<TextField
35+
margin='normal'
36+
required
37+
fullWidth
38+
id='email'
39+
label='Email Address'
40+
name='email'
41+
autoComplete='email'
42+
autoFocus
43+
/>
44+
<TextField
45+
margin='normal'
46+
required
47+
fullWidth
48+
name='password'
49+
label='Password'
50+
type='password'
51+
id='password'
52+
autoComplete='current-password'
53+
/>
54+
<FormControlLabel
55+
control={<Checkbox value='remember' color='primary' />}
56+
label='Remember me'
57+
/>
58+
<Button
59+
type='submit'
60+
fullWidth
61+
variant='contained'
62+
sx={{ mt: 3, mb: 2 }}
63+
>
64+
Login
65+
</Button>
66+
<Grid container>
67+
<Grid item xs>
68+
<CustomLink href='#' variant='body2'>
69+
Forgot password?
70+
</CustomLink>
71+
</Grid>
72+
<Grid item>
73+
<CustomLink href='/register' variant='body2'>
74+
{"Don't have an account? Sign Up"}
75+
</CustomLink>
76+
</Grid>
77+
</Grid>
78+
</LoginSubmitBox>
79+
</Box>
80+
<Copyright sx={{ mt: 8, mb: 4 }} />
81+
</>
82+
);
83+
}

src/app/page.tsx

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import Navigation from '@/components/Navigation';
2-
import { Container, Paper, Stack, Typography } from '@mui/material';
1+
import { Paper, Stack, Typography } from '@mui/material';
32

43
export default function Home() {
54
const serviceSummary = {
@@ -17,45 +16,41 @@ export default function Home() {
1716
];
1817

1918
return (
20-
<Container component='main'>
21-
<Navigation />
22-
<Stack direction={{ sm: 'column', md: 'row' }} gap={2} mt={2}>
19+
<Stack direction={{ sm: 'column', md: 'row' }} gap={2} mt={2}>
20+
<Paper sx={{ p: 2 }} elevation={3}>
21+
<Typography variant='body1'>
22+
The mission of Polygon is to provide platform for creation of
23+
programming contest problems. Polygon supports the whole development
24+
cycle:
25+
</Typography>
26+
<ul className='list-disc list-inside'>
27+
<li>problem statement writing</li>
28+
<li>test data preparing (generators supported)</li>
29+
<li>model solutions (including correct and wittingly incorrect)</li>
30+
<li>judging</li>
31+
<li>automatic validation</li>
32+
</ul>
33+
</Paper>
34+
<Stack direction='column' gap={2}>
2335
<Paper sx={{ p: 2 }} elevation={3}>
24-
<Typography variant='body1'>
25-
The mission of Polygon is to provide platform for creation of
26-
programming contest problems. Polygon supports the whole development
27-
cycle:
36+
<Typography variant='body2'>
37+
Registered users: {serviceSummary.numUsers}
38+
</Typography>
39+
<Typography variant='body2'>
40+
Problems total: {serviceSummary.numProblems}
41+
</Typography>
42+
<Typography variant='body2'>
43+
Invokers waiting: {serviceSummary.numInvokers}
2844
</Typography>
29-
{/* The following has to have a list using Tailwind CSS */}
30-
<ul className='list-disc list-inside'>
31-
<li>problem statement writing</li>
32-
<li>test data preparing (generators supported)</li>
33-
<li>model solutions (including correct and wittingly incorrect)</li>
34-
<li>judging</li>
35-
<li>automatic validation</li>
36-
</ul>
3745
</Paper>
38-
<Stack direction='column' gap={2}>
39-
<Paper sx={{ p: 2 }} elevation={3}>
40-
<Typography variant='body2'>
41-
Registered users: {serviceSummary.numUsers}
42-
</Typography>
43-
<Typography variant='body2'>
44-
Problems total: {serviceSummary.numProblems}
46+
<Paper sx={{ p: 2 }} elevation={3} data-testid='changelog'>
47+
{changeLogs.map((log, index) => (
48+
<Typography key={index} variant='body2'>
49+
{log}
4550
</Typography>
46-
<Typography variant='body2'>
47-
Invokers waiting: {serviceSummary.numInvokers}
48-
</Typography>
49-
</Paper>
50-
<Paper sx={{ p: 2 }} elevation={3}>
51-
{changeLogs.map((log, index) => (
52-
<Typography key={index} variant='body2'>
53-
{log}
54-
</Typography>
55-
))}
56-
</Paper>
57-
</Stack>
51+
))}
52+
</Paper>
5853
</Stack>
59-
</Container>
54+
</Stack>
6055
);
6156
}

src/components/Copyright.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Typography } from '@mui/material';
2+
import CustomLink from '@/components/CustomLink';
3+
4+
export default function Copyright(props: any) {
5+
return (
6+
<Typography
7+
variant='body2'
8+
color='text.secondary'
9+
align='center'
10+
{...props}
11+
>
12+
{'Copyright © '}
13+
<CustomLink color='inherit' href='https://mui.com/'>
14+
Bibimbap
15+
</CustomLink>{' '}
16+
{new Date().getFullYear()}
17+
{'.'}
18+
</Typography>
19+
);
20+
}

src/components/CustomLink.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import NextLink, { LinkProps as NextLinkProps } from 'next/link';
2+
import { Link as MUILink, LinkProps as MUILinkProps } from '@mui/material';
3+
4+
type CustomLinkProps = NextLinkProps & MUILinkProps;
5+
6+
export default function CustomLink(props: CustomLinkProps) {
7+
const { href, ...others } = props;
8+
9+
return (
10+
<MUILink
11+
color='inherit'
12+
underline='none'
13+
component={NextLink}
14+
href={href}
15+
{...others}
16+
/>
17+
);
18+
}

src/components/Navigation.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from '@mui/material';
1717
import Image from 'next/image';
1818
import { useState } from 'react';
19+
import CustomLink from './CustomLink';
1920

2021
interface Props {
2122
/**
@@ -26,7 +27,11 @@ interface Props {
2627
}
2728

2829
const drawerWidth = 240;
29-
const navItems = ['Login', 'Register', 'Help'];
30+
const navItems = [
31+
{ name: 'Login', link: '/login' },
32+
{ name: 'Register', link: '/register' },
33+
{ name: 'Help', link: '/help' },
34+
];
3035

3136
export default function Navigation(props: Props) {
3237
const { window } = props;
@@ -44,9 +49,13 @@ export default function Navigation(props: Props) {
4449
<Divider />
4550
<List>
4651
{navItems.map((item) => (
47-
<ListItem key={item} disablePadding>
48-
<ListItemButton sx={{ textAlign: 'center' }}>
49-
<ListItemText primary={item} />
52+
<ListItem key={item.name} disablePadding>
53+
<ListItemButton
54+
component='a'
55+
href={item.link}
56+
sx={{ textAlign: 'center' }}
57+
>
58+
<ListItemText primary={item.name} />
5059
</ListItemButton>
5160
</ListItem>
5261
))}
@@ -70,18 +79,22 @@ export default function Navigation(props: Props) {
7079
>
7180
<Menu />
7281
</IconButton>
73-
<Image src='/logo.png' alt='logo' width={64} height={64} />
74-
<Typography
82+
83+
<CustomLink href='/'>
84+
{' '}
85+
<Image src='/logo.png' alt='logo' width={64} height={64} />
86+
</CustomLink>
87+
<CustomLink
88+
href='/'
7589
variant='h6'
76-
component='div'
7790
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' }, ml: 2 }}
7891
>
7992
Bibimbap
80-
</Typography>
93+
</CustomLink>
8194
<Box sx={{ display: { xs: 'none', sm: 'block' } }}>
8295
{navItems.map((item) => (
83-
<Button key={item} sx={{ color: '#fff' }}>
84-
{item}
96+
<Button key={item.name} sx={{ color: '#fff' }} href={item.link}>
97+
{item.name}
8598
</Button>
8699
))}
87100
</Box>

0 commit comments

Comments
 (0)