168 lines
6.1 KiB
TypeScript
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>
|
|
);
|
|
} |