Files
dps-webshop/01-frontend/src/helper/productpage/ProductInfo.tsx
2025-05-25 12:56:09 +02:00

168 lines
6.1 KiB
TypeScript

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";
import {useTranslation} from "react-i18next";
export default function ProductInfo({ item }: { item: Item }) {
const { t } = useTranslation();
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={t('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'>
{t('inStock')} ({item.stock} {t('available')})
</Alert>
) : item.stock > 0 ? (
<Alert severity="warning" variant='outlined'>{t('almostSoldOut')} ({item.stock} {t('available')})</Alert>
) : (
<Alert severity="error" variant='filled'>{t('outOfStock')}</Alert>
)}
</Box>
<Stack direction="row" spacing={2} alignItems="center">
<TextField
type="number"
label={t('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
>
{t('addToCart')}
</Button>
</Stack>
<Box sx={{ mt: 2 }}>
<Typography variant="body2" color="text.secondary">
<LocalShipping sx={{ mr: 1, verticalAlign: 'middle' }} />
{t('freeShipping')}
</Typography>
</Box>
</Stack>
<Snackbar
open={open}
autoHideDuration={3000}
onClose={handleClose}
message={t('addedToCart')}
action={action}
/>
</Grid>
);
}