Files
reactShop/src/components/AddToCartButton.js

461 lines
15 KiB
JavaScript

import React, { Component } from "react";
import Button from "@mui/material/Button";
import ButtonGroup from "@mui/material/ButtonGroup";
import IconButton from "@mui/material/IconButton";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import Tooltip from "@mui/material/Tooltip";
import TextField from "@mui/material/TextField";
import AddIcon from "@mui/icons-material/Add";
import RemoveIcon from "@mui/icons-material/Remove";
import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
import DeleteIcon from "@mui/icons-material/Delete";
import { withI18n } from "../i18n/withTranslation.js";
if (!Array.isArray(window.cart)) window.cart = [];
class AddToCartButton extends Component {
constructor(props) {
super(props);
if (!Array.isArray(window.cart)) window.cart = [];
this.state = {
quantity: window.cart.find((i) => i.id === this.props.id)
? window.cart.find((i) => i.id === this.props.id).quantity
: 0,
isEditing: false,
editValue: "",
};
}
componentDidMount() {
this.cart = () => {
if (!Array.isArray(window.cart)) window.cart = [];
const item = window.cart.find((i) => i.id === this.props.id);
const newQuantity = item ? item.quantity : 0;
if (this.state.quantity !== newQuantity)
this.setState({ quantity: newQuantity });
};
window.addEventListener("cart", this.cart);
}
componentWillUnmount() {
window.removeEventListener("cart", this.cart);
}
handleIncrement = () => {
if (!window.cart) window.cart = [];
const idx = window.cart.findIndex((item) => item.id === this.props.id);
if (idx === -1) {
window.cart.push({
id: this.props.id,
name: this.props.name,
seoName: this.props.seoName,
pictureList: this.props.pictureList,
price: this.props.price,
fGrundPreis: this.props.fGrundPreis,
cGrundEinheit: this.props.cGrundEinheit,
quantity: 1,
weight: this.props.weight,
vat: this.props.vat,
versandklasse: this.props.versandklasse,
availableSupplier: this.props.availableSupplier,
komponenten: this.props.komponenten,
available: this.props.available
});
} else {
window.cart[idx].quantity++;
}
window.dispatchEvent(new CustomEvent("cart"));
};
handleDecrement = () => {
if (!window.cart) window.cart = [];
const idx = window.cart.findIndex((item) => item.id === this.props.id);
if (idx !== -1) {
if (window.cart[idx].quantity > 1) {
window.cart[idx].quantity--;
} else {
window.cart.splice(idx, 1);
}
window.dispatchEvent(new CustomEvent("cart"));
}
};
handleClearCart = () => {
if (!window.cart) window.cart = [];
const idx = window.cart.findIndex((item) => item.id === this.props.id);
if (idx !== -1) {
window.cart.splice(idx, 1);
window.dispatchEvent(new CustomEvent("cart"));
}
};
handleEditStart = () => {
this.setState({
isEditing: true,
editValue: this.state.quantity > 0 ? this.state.quantity.toString() : "",
});
};
handleEditChange = (event) => {
// Only allow numbers
const value = event.target.value.replace(/[^0-9]/g, "");
this.setState({ editValue: value });
};
handleEditComplete = () => {
let newQuantity = parseInt(this.state.editValue, 10);
if (isNaN(newQuantity) || newQuantity < 0) {
newQuantity = 0;
}
if (!window.cart) window.cart = [];
const idx = window.cart.findIndex((item) => item.id === this.props.id);
if (idx !== -1) {
window.cart[idx].quantity = newQuantity;
window.dispatchEvent(
new CustomEvent("cart", {
detail: { id: this.props.id, quantity: newQuantity },
})
);
}
this.setState({ isEditing: false });
};
handleKeyPress = (event) => {
if (event.key === "Enter") {
this.handleEditComplete();
}
};
toggleCart = () => {
// Dispatch an event that Header.js can listen for to toggle the cart
window.dispatchEvent(new CustomEvent("toggle-cart"));
};
render() {
const { quantity, isEditing, editValue } = this.state;
const { available, size, incoming, availableSupplier } = this.props;
// Button is disabled if product is not available
if (!available) {
if (incoming) {
return (
<Button
fullWidth
variant="contained"
size={size || "medium"}
sx={{
borderRadius: 2,
fontWeight: "bold",
backgroundColor: "#ffeb3b",
color: "#000000",
"&:hover": {
backgroundColor: "#fdd835",
},
}}
>
{this.props.t ? this.props.t('cart.availableFrom', {
date: new Date(incoming).toLocaleDateString("de-DE", {
year: "numeric",
month: "long",
day: "numeric",
})
}) : `Ab ${new Date(incoming).toLocaleDateString("de-DE", {
year: "numeric",
month: "long",
day: "numeric",
})}`}
</Button>
);
}
// If availableSupplier is 1, handle both quantity cases
if (availableSupplier === 1) {
// If no items in cart, show simple "Add to Cart" button with yellowish green
if (quantity === 0) {
return (
<Button
fullWidth
variant="contained"
size={size || "medium"}
onClick={this.handleIncrement}
startIcon={<ShoppingCartIcon />}
sx={{
borderRadius: 2,
fontWeight: "bold",
backgroundColor: "#9ccc65", // yellowish green
color: "#000000",
"&:hover": {
backgroundColor: "#8bc34a",
},
}}
>
{this.props.steckling ?
(this.props.t ? this.props.t('cart.preorderCutting') : "Als Steckling vorbestellen") :
(this.props.t ? this.props.t('cart.addToCart') : "In den Korb")}
</Button>
);
}
// If items are in cart, show quantity controls with yellowish green
if (quantity > 0) {
return (
<Box sx={{ width: "100%" }}>
<ButtonGroup
fullWidth
variant="contained"
color="primary"
size={size || "medium"}
sx={{
borderRadius: 2,
"& .MuiButtonGroup-grouped:not(:last-of-type)": {
borderRight: "1px solid rgba(255,255,255,0.3)",
},
}}
>
<IconButton
color="inherit"
onClick={this.handleDecrement}
aria-label="Menge verringern"
sx={{ width: "28px", borderRadius: 0, flexGrow: 1 }}
>
<RemoveIcon />
</IconButton>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
px: 2,
flexGrow: 2,
position: "relative",
cursor: "pointer",
}}
onClick={this.handleEditStart}
>
{isEditing ? (
<TextField
autoFocus
value={editValue}
onChange={this.handleEditChange}
onBlur={this.handleEditComplete}
onKeyPress={this.handleKeyPress}
onFocus={(e) => e.target.select()}
size="small"
variant="standard"
inputProps={{
style: {
textAlign: "center",
width: "30px",
fontSize: "14px",
padding: "2px",
fontWeight: "bold",
},
"aria-label": "quantity",
}}
sx={{ my: -0.5 }}
/>
) : (
<Typography variant="button" sx={{ fontWeight: "bold" }}>
{quantity}
</Typography>
)}
</Box>
<IconButton
color="inherit"
onClick={this.handleIncrement}
aria-label="Menge erhöhen"
sx={{ width: "28px", borderRadius: 0, flexGrow: 1 }}
>
<AddIcon />
</IconButton>
<Tooltip title={this.props.t ? this.props.t('cart.removeFromCart') : 'Aus dem Warenkorb entfernen'} arrow>
<IconButton
color="inherit"
onClick={this.handleClearCart}
aria-label={this.props.t ? this.props.t('cart.removeFromCart') : 'Aus dem Warenkorb entfernen'}
sx={{
borderRadius: 0,
"&:hover": { color: "error.light" },
}}
>
<DeleteIcon />
</IconButton>
</Tooltip>
{this.props.cartButton && (
<Tooltip title={this.props.t ? this.props.t('cart.openCart') : 'Warenkorb öffnen'} arrow>
<IconButton
color="inherit"
onClick={this.toggleCart}
aria-label={this.props.t ? this.props.t('cart.openCart') : 'Warenkorb öffnen'}
sx={{
borderRadius: 0,
"&:hover": { color: "primary.light" },
}}
>
<ShoppingCartIcon />
</IconButton>
</Tooltip>
)}
</ButtonGroup>
</Box>
);
}
}
return (
<Button
disabled
fullWidth
variant="contained"
size={size || "medium"}
sx={{
borderRadius: 2,
fontWeight: "bold",
}}
>
{this.props.t ? this.props.t('product.outOfStock') : 'Out of Stock'}
</Button>
);
}
// If no items in cart, show simple "Add to Cart" button
if (quantity === 0) {
return (
<Button
fullWidth
variant="contained"
color="primary"
size={size || "medium"}
onClick={this.handleIncrement}
startIcon={<ShoppingCartIcon />}
sx={{
borderRadius: 2,
fontWeight: "bold",
"&:hover": {
backgroundColor: "primary.dark",
},
}}
>
{this.props.steckling ?
(this.props.t ? this.props.t('cart.preorderCutting') : "Als Steckling vorbestellen") :
(this.props.t ? this.props.t('cart.addToCart') : "In den Korb")}
</Button>
);
}
// If items are in cart, show quantity controls
return (
<Box sx={{ width: "100%" }}>
<ButtonGroup
fullWidth
variant="contained"
color="primary"
size={size || "medium"}
sx={{
borderRadius: 2,
"& .MuiButtonGroup-grouped:not(:last-of-type)": {
borderRight: "1px solid rgba(255,255,255,0.3)",
},
}}
>
<IconButton
color="inherit"
onClick={this.handleDecrement}
aria-label="Menge verringern"
sx={{ width: "28px", borderRadius: 0, flexGrow: 1 }}
>
<RemoveIcon />
</IconButton>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
px: 2,
flexGrow: 2,
position: "relative",
cursor: "pointer",
}}
onClick={this.handleEditStart}
>
{isEditing ? (
<TextField
autoFocus
value={editValue}
onChange={this.handleEditChange}
onBlur={this.handleEditComplete}
onKeyPress={this.handleKeyPress}
onFocus={(e) => e.target.select()}
size="small"
variant="standard"
inputProps={{
style: {
textAlign: "center",
width: "30px",
fontSize: "14px",
padding: "2px",
fontWeight: "bold",
},
"aria-label": "quantity",
}}
sx={{ my: -0.5 }}
/>
) : (
<Typography variant="button" sx={{ fontWeight: "bold" }}>
{quantity}
</Typography>
)}
</Box>
<IconButton
color="inherit"
onClick={this.handleIncrement}
aria-label="Menge erhöhen"
sx={{ width: "28px", borderRadius: 0, flexGrow: 1 }}
>
<AddIcon />
</IconButton>
<Tooltip title={this.props.t ? this.props.t('cart.removeFromCart') : 'Aus dem Warenkorb entfernen'} arrow>
<IconButton
color="inherit"
onClick={this.handleClearCart}
aria-label={this.props.t ? this.props.t('cart.removeFromCart') : 'Aus dem Warenkorb entfernen'}
sx={{
borderRadius: 0,
"&:hover": { color: "error.light" },
}}
>
<DeleteIcon />
</IconButton>
</Tooltip>
{this.props.cartButton && (
<Tooltip title={this.props.t ? this.props.t('cart.openCart') : 'Warenkorb öffnen'} arrow>
<IconButton
color="inherit"
onClick={this.toggleCart}
aria-label={this.props.t ? this.props.t('cart.openCart') : 'Warenkorb öffnen'}
sx={{
borderRadius: 0,
"&:hover": { color: "primary.light" },
}}
>
<ShoppingCartIcon />
</IconButton>
</Tooltip>
)}
</ButtonGroup>
</Box>
);
}
}
export default withI18n()(AddToCartButton);