Add variable ItemCard count. First UI structure impl.
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
#root {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom'
|
||||
import './App.css'
|
||||
import Home from './pages/Home'
|
||||
import NoPage from './pages/NoPage';
|
||||
import NavBar from './helper/NavBar';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||
import './App.css';
|
||||
import NavBar from './helper/NavBar';
|
||||
import Home from './pages/Home';
|
||||
import NoPage from './pages/NoPage';
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<NavBar />
|
||||
<BrowserRouter>
|
||||
<BrowserRouter>
|
||||
<NavBar />
|
||||
<Routes>
|
||||
<Route path="/">
|
||||
<Route index element={<Home />} />
|
||||
<Route path="*" element={<NoPage />} />
|
||||
</Route>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="*" element={<NoPage />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
BIN
01-frontend/src/assets/HTW.jpg
Normal file
BIN
01-frontend/src/assets/HTW.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
12
01-frontend/src/components/Item.tsx
Normal file
12
01-frontend/src/components/Item.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
type Item = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
price: number;
|
||||
stock: number;
|
||||
category: string;
|
||||
rating: number;
|
||||
discount: number;
|
||||
};
|
||||
|
||||
export default Item;
|
||||
@@ -1,6 +1,32 @@
|
||||
export default function ItemCard() {
|
||||
import { AddShoppingCart } from "@mui/icons-material";
|
||||
import { Card, CardActionArea, CardContent, CardMedia, IconButton, Paper, Rating, Typography } from "@mui/material";
|
||||
import Item from "../components/Item";
|
||||
|
||||
export default function ItemCard({item}: {item: Item}) {
|
||||
return (
|
||||
<div >
|
||||
</div>
|
||||
<Paper elevation={3}>
|
||||
<Card>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="140"
|
||||
image="src//assets/HTW.jpg"
|
||||
alt="HTW Logo"
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
{item.name}
|
||||
</Typography>
|
||||
<Rating name="half-rating" defaultValue={item.rating} precision={0.5} />
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
{item.description}
|
||||
</Typography>
|
||||
<IconButton color="primary" aria-label="add to shopping cart">
|
||||
<AddShoppingCart />
|
||||
</IconButton>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
@@ -1,11 +1,212 @@
|
||||
import * as 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 Menu from '@mui/material/Menu';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import Container from '@mui/material/Container';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Button from '@mui/material/Button';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import AdbIcon from '@mui/icons-material/Adb';
|
||||
import { alpha, InputBase, styled } from '@mui/material';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
|
||||
const pages = ['Products', 'Pricing', 'Contact'];
|
||||
const settings = ['Profile', 'Account', 'Dashboard', 'Logout'];
|
||||
|
||||
const Search = styled('div')(({ theme }) => ({
|
||||
position: 'relative',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: alpha(theme.palette.common.white, 0.15),
|
||||
'&:hover': {
|
||||
backgroundColor: alpha(theme.palette.common.white, 0.25),
|
||||
},
|
||||
marginLeft: 0,
|
||||
width: '100%',
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
marginLeft: theme.spacing(1),
|
||||
width: 'auto',
|
||||
},
|
||||
}));
|
||||
|
||||
const SearchIconWrapper = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(0, 2),
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
pointerEvents: 'none',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}));
|
||||
|
||||
const StyledInputBase = styled(InputBase)(({ theme }) => ({
|
||||
color: 'inherit',
|
||||
width: '100%',
|
||||
'& .MuiInputBase-input': {
|
||||
padding: theme.spacing(1, 1, 1, 0),
|
||||
// vertical padding + font size from searchIcon
|
||||
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
|
||||
transition: theme.transitions.create('width'),
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
width: '12ch',
|
||||
'&:focus': {
|
||||
width: '20ch',
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default function NavBar() {
|
||||
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 (
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
<AppBar>
|
||||
<Container maxWidth="xl">
|
||||
<Toolbar disableGutters>
|
||||
<AdbIcon sx={{ display: { xs: 'none', md: 'flex' }, mr: 1 }} />
|
||||
<Typography
|
||||
variant="h6"
|
||||
noWrap
|
||||
component="a"
|
||||
href="/"
|
||||
sx={{
|
||||
mr: 2,
|
||||
display: { xs: 'none', md: 'flex' },
|
||||
fontFamily: 'monospace',
|
||||
fontWeight: 700,
|
||||
letterSpacing: '.3rem',
|
||||
color: 'inherit',
|
||||
textDecoration: 'none',
|
||||
}}
|
||||
>
|
||||
Digitaler Produktionsshop
|
||||
</Typography>
|
||||
|
||||
<Search>
|
||||
<SearchIconWrapper>
|
||||
<SearchIcon />
|
||||
</SearchIconWrapper>
|
||||
<StyledInputBase
|
||||
placeholder="Search…"
|
||||
inputProps={{ 'aria-label': 'search' }}
|
||||
/>
|
||||
</Search>
|
||||
|
||||
<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 sx={{ textAlign: 'center' }}>{page}</Typography>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</Box>
|
||||
<AdbIcon sx={{ display: { xs: 'flex', md: 'none' }, mr: 1 }} />
|
||||
<Typography
|
||||
variant="h5"
|
||||
noWrap
|
||||
component="a"
|
||||
href="/"
|
||||
sx={{
|
||||
mr: 2,
|
||||
display: { xs: 'flex', md: 'none' },
|
||||
flexGrow: 1,
|
||||
fontFamily: 'monospace',
|
||||
fontWeight: 700,
|
||||
letterSpacing: '.3rem',
|
||||
color: 'inherit',
|
||||
textDecoration: 'none',
|
||||
}}
|
||||
>
|
||||
LOGO
|
||||
</Typography>
|
||||
<Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
|
||||
{pages.map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
onClick={handleCloseNavMenu}
|
||||
sx={{ my: 2, color: 'white', display: 'block' }}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
<Box sx={{ flexGrow: 0 }}>
|
||||
<Tooltip title="Open settings">
|
||||
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
|
||||
<Avatar alt="Florian Speicher" 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 sx={{ textAlign: 'center' }}>{setting}</Typography>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</Box>
|
||||
</Toolbar>
|
||||
</Container>
|
||||
</AppBar>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,37 @@
|
||||
import { Pagination } from "@mui/material";
|
||||
import ItemCard from "../helper/ItemCard";
|
||||
import Item from "../components/Item";
|
||||
|
||||
export default function Home() {
|
||||
const items: Item[] = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Item 1",
|
||||
description: "Description 1",
|
||||
price: 10,
|
||||
stock: 100,
|
||||
category: "Category 1",
|
||||
rating: 4.5,
|
||||
discount: 10,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Item 2",
|
||||
description: "Description 2",
|
||||
price: 20,
|
||||
stock: 200,
|
||||
category: "Category 2",
|
||||
rating: 4.0,
|
||||
discount: 20,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Home</h1>
|
||||
<p>Welcome to the home page!</p>
|
||||
{items.map((item) => (
|
||||
<ItemCard item={item} />
|
||||
))}
|
||||
<Pagination count={10} variant="outlined" shape="rounded" />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user