Add variable ItemCard count. First UI structure impl.

This commit is contained in:
FlorianSpeicher
2025-05-03 17:52:19 +02:00
parent fb61a22561
commit a839f1c6ad
10 changed files with 1033 additions and 60 deletions

View File

@@ -1,8 +1,5 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
width: 100%;
}
.logo {

View File

@@ -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>
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View 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;

View File

@@ -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>
)
}

View File

@@ -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>
);
}

View File

@@ -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>
)
);
}