Skip to content
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
562 changes: 562 additions & 0 deletions e-commerce-app/package-lock.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions e-commerce-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@fontsource/roboto": "^5.0.8",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.4",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.39",
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.2",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
Expand Down
7 changes: 5 additions & 2 deletions e-commerce-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { RegistrationPage } from './pages/RegistrationPage/RegistrationPage';
import { UserPage } from './pages/UserPage/UserPage';
import { ProductPage } from './pages/ProductPage/ProductPage';
import { ProductsPage } from './pages/ProductsPage/ProductsPage';
import RootPage from './pages/RootPage/RootPage';

export const App = () => {

Expand All @@ -33,16 +34,18 @@ export const App = () => {
</header>
</div>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path={'/'} element={<RootPage />}>
<Route index element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/basket" element={<BasketPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/registration" element={<RegistrationPage />} />
<Route path="/user" element={<UserPage />} />
<Route path="/product" element={<ProductPage />} />
<Route path="/products" element={<ProductsPage />} />
</Route>
<Route path="*" element={<ErrorPage />} />
</Routes>
</Router>
);
}
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
161 changes: 161 additions & 0 deletions e-commerce-app/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import MenuIcon from '@mui/icons-material/Menu';
import Container from '@mui/material/Container';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';
import MenuItem from '@mui/material/MenuItem';
import logo from '../../assets/logo/free-icon-tree-740936.png';
import Avatar from '@mui/material/Avatar';
import Menu from '@mui/material/Menu';

const pages = ['Catalog', 'About Us', 'Login', 'Registration', 'Home'];
const settings = ['User', 'Logout'];


export const Header: React.FC = () => {
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null);
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(null);

const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorElNav(event.currentTarget);
};
const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorElUser(event.currentTarget);
};

const handleCloseNavMenu = () => {
setAnchorElNav(null);
};

const handleCloseUserMenu = () => {
setAnchorElUser(null);
};

return (
<AppBar position="sticky" color='default'>
<Container maxWidth="xl">
<Toolbar disableGutters>
<a href="/"><img src={logo} alt='logo' width={60} height={60} /></a>
<Typography
variant="h6"
noWrap
component="a"
href="/"
sx={{
mr: 2,
display: { xs: 'none', md: 'flex' },
fontFamily: 'monospace',
fontWeight: 700,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

All styles should be placed in the scss file. Check also other places.

letterSpacing: '.3rem',
color: 'green',
textDecoration: 'none',
}}
>
RSdzen
</Typography>

<Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
open={Boolean(anchorElNav)}
onClose={handleCloseNavMenu}
sx={{
display: { xs: 'block', md: 'none' },
}}
>
{pages.map((page) => (
<MenuItem key={page} onClick={handleCloseNavMenu}>
<Typography textAlign="center">{page}</Typography>
</MenuItem>
))}
Comment on lines +91 to +95
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

TODO: create a new NavBar component with navigation links

</Menu>
</Box>
<Typography
variant="h5"
noWrap
component="a"
href="/"
sx={{
mr: 2,
display: { xs: 'flex', md: 'none' },
flexGrow: 1,
fontFamily: 'monospace',
fontWeight: 700,
letterSpacing: '.3rem',
color: 'green',
textDecoration: 'none',
}}
>
RSdzen
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
{pages.map((page) => (
<Button
key={page}
onClick={handleCloseNavMenu}
sx={{ my: 2, color: 'green', display: 'block' }}
>
{page}
</Button>
))}
</Box>

<Box sx={{ flexGrow: 0 }}>
<Tooltip title="Open settings">
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
</IconButton>
</Tooltip>
<Menu
sx={{ mt: '45px' }}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
{settings.map((setting) => (
<MenuItem key={setting} onClick={handleCloseUserMenu}>
<Typography textAlign="center">{setting}</Typography>
</MenuItem>
))}
</Menu>
</Box>
</Toolbar>
</Container>
</AppBar>
);
};
8 changes: 3 additions & 5 deletions e-commerce-app/src/index.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
}
6 changes: 6 additions & 0 deletions e-commerce-app/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import './index.css';
import { App } from './App';
import reportWebVitals from './reportWebVitals';

import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
// import { readFileSync } from 'fs';

const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
Expand Down
68 changes: 66 additions & 2 deletions e-commerce-app/src/pages/LoginPage/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,69 @@
import React from 'react';
import { Grid, Box, TextField, Button, Alert, Typography } from '@mui/material';
import LoginImage from '../../assets/images/ImgLoginPage.png';
import { NavLink } from 'react-router-dom';
import { useState } from 'react';

export const LoginPage: React.FC = () => {
return <div>Login Page</div>;
const [error, setError] = useState({
status: false,
message: '',
type: ''
});
const handleSubmit=(e: React.FormEvent<HTMLFormElement>)=>{
e.preventDefault();
const data=new FormData(e.currentTarget);
const actualData = {
email: data.get('email'),
password: data.get('password'),
};
if (actualData.email && actualData.password) {
console.log(actualData);
(document.getElementById('login-form') as HTMLFormElement).reset();
setError({
status: true,
message: 'Successful!',
type: 'success'
});
} else {
setError({
status: true,
message: 'All fields are required',
type: 'error'
});
}
};
return (
<Grid container sx={{ height: '80vh'}}>
<Grid item lg={7} sm={5} sx={{
backgroundImage: `url(${LoginImage})`,
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

better to do backgroundSize to contain and backgroundPosition to top.
It'll be more attractive on small screen devices

backgroundPosition: 'center'
}}>
</Grid>
<Grid item lg={5} sm={7}>
<Box component='form' noValidate sx={{ mt: 5, ml:8, mr:8}} id='login-form' onSubmit={handleSubmit}>
<Box>
{error.status ? <Alert severity={'error'}>{error.message}</Alert> : ''}
</Box>
<TextField sx={{mt: 2}} required fullWidth id='email' name='email' label='Email Address' type='email' />
<TextField required fullWidth margin='normal' id='password' name='password' label='Password' type='password'/>
<Box textAlign='center'>
<Button type='submit' variant='contained' sx={{px:5, mt: 2, backgroundColor: 'green'}}>Login</Button>
<Typography component='p' color='gray'>Remember me</Typography>
</Box>
<Box>
<NavLink to='/'>Forgot Password?</NavLink>
</Box>
<Box sx={{mt: 10}}>
<Typography component='p' textAlign='center'>Don&apos;t have account yet? Sign up</Typography>
</Box>
<Box textAlign='center'>
<Button type='submit' variant='contained' sx={{px:2, mt: 2, backgroundColor: 'green'}}>Registration</Button>
</Box>
</Box>
</Grid>
</Grid>

);
};
15 changes: 15 additions & 0 deletions e-commerce-app/src/pages/RootPage/RootPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {JSX} from 'react';
import { Outlet } from 'react-router-dom';
import {Header} from '../../components/Header/Header';

const RootPage = (): JSX.Element => {
return (
<>
<Header />
<div className="app">
<Outlet />
</div>
</>
);
};
export default RootPage;