Added snackbars on product page. Refactored folder structure
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import NavBar from './helper/NavBar';
|
import NavBar from './helper/navbar/NavBar';
|
||||||
import Home from './pages/Home';
|
import Home from './pages/Home';
|
||||||
import NoPage from './pages/NoPage';
|
import NoPage from './pages/NoPage';
|
||||||
import Product from './pages/Product';
|
import Product from './pages/Product';
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
import { Box, Button, Divider, Rating, TextField, Typography } from "@mui/material";
|
|
||||||
import RatingCard from "./RatingCard";
|
|
||||||
import RatingType from "../components/Rating";
|
|
||||||
|
|
||||||
export default function Ratings() {
|
|
||||||
|
|
||||||
const ratings: RatingType[] = [
|
|
||||||
{
|
|
||||||
id: "1",
|
|
||||||
rating: 4.5,
|
|
||||||
text: "Great product!",
|
|
||||||
date: "2023-10-01",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "2",
|
|
||||||
rating: 3.0,
|
|
||||||
text: "Average quality.",
|
|
||||||
date: "2023-10-02",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "3",
|
|
||||||
rating: 5.0,
|
|
||||||
text: "Excellent value for money!",
|
|
||||||
date: "2023-10-03",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className='contact-divider-box'>
|
|
||||||
<Divider className='contact-divider' />
|
|
||||||
</div>
|
|
||||||
<div className="rating-card-body">
|
|
||||||
<Typography variant="h5">
|
|
||||||
Rate this product:</Typography>
|
|
||||||
<Rating name="half-rating" defaultValue={2.5} precision={0.5}/>
|
|
||||||
<TextField
|
|
||||||
label="Rating text (optional)"
|
|
||||||
multiline
|
|
||||||
minRows={4}
|
|
||||||
maxRows={16}
|
|
||||||
className="rating-text-field"
|
|
||||||
/>
|
|
||||||
<Button variant="contained" color="primary" className="rating-button">
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className='contact-divider-box'>
|
|
||||||
<Divider className='contact-divider' />
|
|
||||||
</div>
|
|
||||||
<Box className="rating-card-box">
|
|
||||||
{ratings.map((ratingType: RatingType) => (
|
|
||||||
<RatingCard key={ratingType.id} {...ratingType} />
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { AddShoppingCart } from "@mui/icons-material";
|
import { AddShoppingCart } from "@mui/icons-material";
|
||||||
import { Card, CardActionArea, CardContent, CardMedia, IconButton, Paper, Rating, Typography } from "@mui/material";
|
import { Card, CardActionArea, CardContent, CardMedia, IconButton, Paper, Rating, Typography } from "@mui/material";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Item from "../components/Item";
|
import Item from "../../components/Item";
|
||||||
import { useBasket } from "./BasketProvider";
|
import { useBasket } from "../BasketProvider";
|
||||||
import "./helper.css";
|
import "../helper.css";
|
||||||
|
|
||||||
export default function ItemCard({ item }: { item: Item }) {
|
export default function ItemCard({ item }: { item: Item }) {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
165
01-frontend/src/helper/productpage/ProductInfo.tsx
Normal file
165
01-frontend/src/helper/productpage/ProductInfo.tsx
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import { Alert, Box, Button, Card, Divider, Grid, IconButton, Rating, Snackbar, SnackbarCloseReason, Stack, TextField, Typography } from "@mui/material";
|
||||||
|
import Item from "../../components/Item";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Close, LocalShipping, ShoppingCart } from "@mui/icons-material";
|
||||||
|
import { useBasket } from "../BasketProvider";
|
||||||
|
|
||||||
|
export default function ProductInfo({ item }: { item: Item }) {
|
||||||
|
const [quantity, setQuantity] = useState<number>(1);
|
||||||
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
|
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
|
||||||
|
|
||||||
|
|
||||||
|
const { addToBasket } = useBasket();
|
||||||
|
|
||||||
|
const handleClose = (
|
||||||
|
event: React.SyntheticEvent | Event,
|
||||||
|
reason?: SnackbarCloseReason,
|
||||||
|
) => {
|
||||||
|
if (reason === 'clickaway') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const action = (
|
||||||
|
<React.Fragment>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
aria-label="close"
|
||||||
|
color="inherit"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
<Close fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const handleAddToCart = () => {
|
||||||
|
addToBasket(item.id, quantity);
|
||||||
|
setOpen(true);
|
||||||
|
console.log(`Added {quantity} of €{item.name} to basket`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const discountedPrice = item.price * (1 - item.discount / 100);
|
||||||
|
|
||||||
|
const handleImageLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {
|
||||||
|
const { naturalWidth, naturalHeight } = event.currentTarget;
|
||||||
|
setImageDimensions({ width: naturalWidth, height: naturalHeight });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container spacing={4}>
|
||||||
|
{/* Left Column - Image */}
|
||||||
|
|
||||||
|
<Card elevation={2} sx={{ width: '100%', maxWidth: 400 }}>
|
||||||
|
<Box
|
||||||
|
component="img"
|
||||||
|
src="/src/assets/HTW.jpg"
|
||||||
|
alt={item.name}
|
||||||
|
onLoad={handleImageLoad} // Event-Handler zum Ermitteln der Bildgröße
|
||||||
|
sx={{
|
||||||
|
maxWidth: imageDimensions.width > imageDimensions.height ? "100%" : "auto",
|
||||||
|
maxHeight: imageDimensions.height >= imageDimensions.width ? 400 : "auto",
|
||||||
|
width: "auto",
|
||||||
|
height: "auto",
|
||||||
|
objectFit: "contain",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
|
||||||
|
{/* Right Column - Product Details */}
|
||||||
|
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<Typography variant="h4" component="h1">
|
||||||
|
{item.name}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Box display="flex" alignItems="center" gap={1}>
|
||||||
|
<Rating value={item.rating} precision={0.5} readOnly />
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
({item.rating} / 5)
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Stack direction="row" alignItems="center" spacing={2}>
|
||||||
|
{item.discount > 0 ? (
|
||||||
|
<>
|
||||||
|
<Typography variant="h4" color="green">
|
||||||
|
€{discountedPrice.toFixed(2)}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
color="text.secondary"
|
||||||
|
sx={{ textDecoration: 'line-through' }}
|
||||||
|
>
|
||||||
|
€{item.price.toFixed(2)}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="h6" color="error">
|
||||||
|
-{item.discount}%
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Typography variant="h4" color="green">
|
||||||
|
€{item.price.toFixed(2)}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
{item.stock > 10 ? (
|
||||||
|
<Alert severity="success" variant='outlined'>
|
||||||
|
In Stock ({item.stock} available)
|
||||||
|
</Alert>
|
||||||
|
) : item.stock > 0 ? (
|
||||||
|
<Alert severity="warning" variant='outlined'>Almost sold out ({item.stock} available)</Alert>
|
||||||
|
) : (
|
||||||
|
<Alert severity="error" variant='filled'>Out of Stock</Alert>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Stack direction="row" spacing={2} alignItems="center">
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
label="Quantity"
|
||||||
|
value={quantity}
|
||||||
|
onChange={(e) => setQuantity(Math.max(1, parseInt(e.target.value)))}
|
||||||
|
InputProps={{ inputProps: { min: 1, max: item.stock } }}
|
||||||
|
sx={{ width: 100 }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="large"
|
||||||
|
startIcon={<ShoppingCart />}
|
||||||
|
onClick={handleAddToCart}
|
||||||
|
disabled={item.stock <= 0}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
Add to Cart
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Box sx={{ mt: 2 }}>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
<LocalShipping sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||||
|
Free shipping on orders over €50
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
</Stack>
|
||||||
|
<Snackbar
|
||||||
|
open={open}
|
||||||
|
autoHideDuration={3000}
|
||||||
|
onClose={handleClose}
|
||||||
|
message="Successfully added to basket"
|
||||||
|
action={action}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Card, CardActionArea, CardContent, Paper, Rating, Typography } from "@mui/material";
|
import { Card, CardActionArea, CardContent, Paper, Rating, Typography } from "@mui/material";
|
||||||
import RatingType from "../components/Rating";
|
import RatingType from "../../components/Rating";
|
||||||
|
|
||||||
export default function RatingCard(ratingType: RatingType) {
|
export default function RatingCard(ratingType: RatingType) {
|
||||||
|
|
||||||
99
01-frontend/src/helper/productpage/Ratings.tsx
Normal file
99
01-frontend/src/helper/productpage/Ratings.tsx
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { Box, Button, Divider, IconButton, Rating, Snackbar, SnackbarCloseReason, TextField, Typography } from "@mui/material";
|
||||||
|
import RatingCard from "./RatingCard";
|
||||||
|
import RatingType from "../../components/Rating";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Close } from "@mui/icons-material";
|
||||||
|
|
||||||
|
export default function Ratings() {
|
||||||
|
|
||||||
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const handleClose = (
|
||||||
|
event: React.SyntheticEvent | Event,
|
||||||
|
reason?: SnackbarCloseReason,
|
||||||
|
) => {
|
||||||
|
if (reason === 'clickaway') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRatingSubmit = () => {
|
||||||
|
// Handle the rating submission logic here
|
||||||
|
setOpen(true);
|
||||||
|
console.log("Rating submitted");
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = (
|
||||||
|
<React.Fragment>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
aria-label="close"
|
||||||
|
color="inherit"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
<Close fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
const ratings: RatingType[] = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
rating: 4.5,
|
||||||
|
text: "Great product!",
|
||||||
|
date: "2023-10-01",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
rating: 3.0,
|
||||||
|
text: "Average quality.",
|
||||||
|
date: "2023-10-02",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
rating: 5.0,
|
||||||
|
text: "Excellent value for money!",
|
||||||
|
date: "2023-10-03",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='contact-divider-box'>
|
||||||
|
<Divider className='contact-divider' />
|
||||||
|
</div>
|
||||||
|
<div className="rating-card-body">
|
||||||
|
<Typography variant="h5">
|
||||||
|
Rate this product:</Typography>
|
||||||
|
<Rating name="half-rating" defaultValue={2.5} precision={0.5} />
|
||||||
|
<TextField
|
||||||
|
label="Rating text (optional)"
|
||||||
|
multiline
|
||||||
|
minRows={4}
|
||||||
|
maxRows={16}
|
||||||
|
className="rating-text-field"
|
||||||
|
/>
|
||||||
|
<Button variant="contained" color="primary" className="rating-button" onClick={handleRatingSubmit}>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className='contact-divider-box'>
|
||||||
|
<Divider className='contact-divider' />
|
||||||
|
</div>
|
||||||
|
<Box className="rating-card-box">
|
||||||
|
{ratings.map((ratingType: RatingType) => (
|
||||||
|
<RatingCard key={ratingType.id} {...ratingType} />
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
<Snackbar
|
||||||
|
open={open}
|
||||||
|
autoHideDuration={3000}
|
||||||
|
onClose={handleClose}
|
||||||
|
message="Thanks for your rating!"
|
||||||
|
action={action}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Box, Pagination } from "@mui/material";
|
import { Box, Pagination } from "@mui/material";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Item from "../components/Item";
|
import Item from "../components/Item";
|
||||||
import FilterItem from "../helper/FilterItem";
|
import FilterItem from "../helper/homepage/FilterItem";
|
||||||
import ItemCard from "../helper/ItemCard";
|
import ItemCard from "../helper/homepage/ItemCard";
|
||||||
import "./pages.css"; // Import der CSS-Datei
|
import "./pages.css"; // Import der CSS-Datei
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
|||||||
@@ -1,31 +1,19 @@
|
|||||||
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
|
|
||||||
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
|
|
||||||
import {
|
import {
|
||||||
Alert,
|
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
|
||||||
Container,
|
Container,
|
||||||
Divider,
|
Divider,
|
||||||
Grid,
|
Typography
|
||||||
Rating,
|
|
||||||
Stack,
|
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useState } from 'react';
|
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import Item from '../components/Item';
|
import Item from '../components/Item';
|
||||||
import { useBasket } from '../helper/BasketProvider';
|
import ProductInfo from '../helper/productpage/ProductInfo';
|
||||||
import Ratings from '../helper/Ratings';
|
import Ratings from '../helper/productpage/Ratings';
|
||||||
|
|
||||||
|
|
||||||
export default function Product() {
|
export default function Product() {
|
||||||
const [quantity, setQuantity] = useState(1);
|
|
||||||
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const item = location.state?.item as Item;
|
const item = location.state?.item as Item;
|
||||||
const { addToBasket } = useBasket();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleGoHome = () => {
|
const handleGoHome = () => {
|
||||||
@@ -55,125 +43,10 @@ export default function Product() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const handleAddToCart = () => {
|
|
||||||
addToBasket(item.id, quantity);
|
|
||||||
console.log(`Added {quantity} of €{item.name} to basket`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const discountedPrice = item.price * (1 - item.discount / 100);
|
|
||||||
|
|
||||||
const handleImageLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {
|
|
||||||
const { naturalWidth, naturalHeight } = event.currentTarget;
|
|
||||||
setImageDimensions({ width: naturalWidth, height: naturalHeight });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='product-page-background'>
|
<div className='product-page-background'>
|
||||||
<Container maxWidth="lg" sx={{ py: 4 }} >
|
<Container maxWidth="lg" sx={{ py: 4 }} >
|
||||||
<Grid container spacing={4}>
|
<ProductInfo item={item}/>
|
||||||
{/* Left Column - Image */}
|
|
||||||
|
|
||||||
<Card elevation={2} sx={{ width: '100%', maxWidth: 400 }}>
|
|
||||||
<Box
|
|
||||||
component="img"
|
|
||||||
src="/src/assets/HTW.jpg"
|
|
||||||
alt={item.name}
|
|
||||||
onLoad={handleImageLoad} // Event-Handler zum Ermitteln der Bildgröße
|
|
||||||
sx={{
|
|
||||||
maxWidth: imageDimensions.width > imageDimensions.height ? "100%" : "auto",
|
|
||||||
maxHeight: imageDimensions.height >= imageDimensions.width ? 400 : "auto",
|
|
||||||
width: "auto",
|
|
||||||
height: "auto",
|
|
||||||
objectFit: "contain",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
|
|
||||||
{/* Right Column - Product Details */}
|
|
||||||
|
|
||||||
<Stack spacing={3}>
|
|
||||||
<Typography variant="h4" component="h1">
|
|
||||||
{item.name}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Box display="flex" alignItems="center" gap={1}>
|
|
||||||
<Rating value={item.rating} precision={0.5} readOnly />
|
|
||||||
<Typography variant="body2" color="text.secondary">
|
|
||||||
({item.rating} / 5)
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Stack direction="row" alignItems="center" spacing={2}>
|
|
||||||
{item.discount > 0 ? (
|
|
||||||
<>
|
|
||||||
<Typography variant="h4" color="green">
|
|
||||||
€{discountedPrice.toFixed(2)}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
variant="h6"
|
|
||||||
color="text.secondary"
|
|
||||||
sx={{ textDecoration: 'line-through' }}
|
|
||||||
>
|
|
||||||
€{item.price.toFixed(2)}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="h6" color="error">
|
|
||||||
-{item.discount}%
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Typography variant="h4" color="green">
|
|
||||||
€{item.price.toFixed(2)}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<Box>
|
|
||||||
{item.stock > 10 ? (
|
|
||||||
<Alert severity="success" variant='outlined'>
|
|
||||||
In Stock ({item.stock} available)
|
|
||||||
</Alert>
|
|
||||||
) : item.stock > 0 ? (
|
|
||||||
<Alert severity="warning" variant='outlined'>Almost sold out ({item.stock} available)</Alert>
|
|
||||||
) : (
|
|
||||||
<Alert severity="error" variant='filled'>Out of Stock</Alert>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Stack direction="row" spacing={2} alignItems="center">
|
|
||||||
<TextField
|
|
||||||
type="number"
|
|
||||||
label="Quantity"
|
|
||||||
value={quantity}
|
|
||||||
onChange={(e) => setQuantity(Math.max(1, parseInt(e.target.value)))}
|
|
||||||
InputProps={{ inputProps: { min: 1, max: item.stock } }}
|
|
||||||
sx={{ width: 100 }}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
size="large"
|
|
||||||
startIcon={<ShoppingCartIcon />}
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
disabled={item.stock <= 0}
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
Add to Cart
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Box sx={{ mt: 2 }}>
|
|
||||||
<Typography variant="body2" color="text.secondary">
|
|
||||||
<LocalShippingIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
|
|
||||||
Free shipping on orders over €50
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
<div className='contact-divider-box'>
|
<div className='contact-divider-box'>
|
||||||
<Divider className='contact-divider' />
|
<Divider className='contact-divider' />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -128,6 +128,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
height: calc(100vh - 3rem); /* Damit der Hintergrund die gesamte Seite abdeckt */
|
||||||
|
min-height: 600px;
|
||||||
|
padding: 20px 0; /* Abstand oben und unten */
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-container {
|
.filter-container {
|
||||||
|
|||||||
Reference in New Issue
Block a user