Fixed image preview. Fixed Price Filter.
This commit is contained in:
@@ -5,6 +5,7 @@ import Item from "../../components/Item";
|
||||
import { useBasket } from "../BasketProvider";
|
||||
import "../helper.css";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
export default function ItemCard({ item }: { item: Item }) {
|
||||
|
||||
@@ -20,13 +21,29 @@ export default function ItemCard({ item }: { item: Item }) {
|
||||
const handleClick = () => {
|
||||
navigate(`/product/${item.id}`, { state: { item } });
|
||||
}
|
||||
const [imageUrl, setImageUrl] = useState<string>("/src/assets/default.jpg"); // Fallback-Bild
|
||||
|
||||
useEffect(() => {
|
||||
const fetchImage = async () => {
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8085/image?uuid=${item.uuid}`);
|
||||
const data = await response.json();
|
||||
if (data.uri) {
|
||||
setImageUrl(data.uri); // Bild-URL setzen
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden des Bildes:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchImage();
|
||||
}, [item.uuid]);
|
||||
|
||||
const imageUrl = `http://localhost:8085/image?articleId=${item.id}`;
|
||||
|
||||
return (
|
||||
<Paper elevation={4}>
|
||||
<Card>
|
||||
<CardActionArea onClick={handleClick}>
|
||||
<Card sx={{height: "100%", width: "100%" }}>
|
||||
<CardActionArea onClick={handleClick} sx={{ height: "100%" }}>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="140"
|
||||
@@ -35,6 +52,11 @@ export default function ItemCard({ item }: { item: Item }) {
|
||||
onError={(event) => {
|
||||
event.currentTarget.src = "/src/assets/default.jpg"; // Standardbild setzen
|
||||
}}
|
||||
sx={{
|
||||
objectFit: "contain", // Bild wird skaliert, um vollständig sichtbar zu sein
|
||||
maxWidth: "100%", // Begrenze die maximale Breite auf den Container
|
||||
maxHeight: "100%", // Begrenze die maximale Höhe auf den Container
|
||||
}}
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
@@ -43,7 +65,7 @@ export default function ItemCard({ item }: { item: Item }) {
|
||||
<Rating name="half-rating" readOnly defaultValue={item.rating} precision={0.5} />
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end" }}>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }} className="item-description">
|
||||
{(item.price100 * (1 - item.discount100 / 100)).toFixed(2)} €
|
||||
{(item.price100 / 100 * (1 - item.discount100 / 100)).toFixed(2)} €
|
||||
</Typography>
|
||||
<IconButton
|
||||
aria-label={t('addToCart')}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Slider, Typography, Box } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
type PriceSliderProps = {
|
||||
@@ -8,11 +8,16 @@ type PriceSliderProps = {
|
||||
onChange?: (range: [number, number]) => void;
|
||||
};
|
||||
|
||||
export default function PriceSlider({ min = 0, max = 100, onChange }: PriceSliderProps) {
|
||||
|
||||
export default function PriceSlider({ min = 0, max = 10000, onChange }: PriceSliderProps) {
|
||||
const { t } = useTranslation();
|
||||
const [value, setValue] = useState<[number, number]>([min, max]);
|
||||
|
||||
// Synchronisiere den Zustand nur, wenn sich die Props ändern
|
||||
useEffect(() => {
|
||||
setValue([min, max]);
|
||||
onChange?.([min, max]); // Initiale Werte an die übergeordnete Komponente übergeben
|
||||
}, [min, max]);
|
||||
|
||||
const handleChange = (_: Event, newValue: number | number[]) => {
|
||||
if (Array.isArray(newValue)) {
|
||||
setValue([newValue[0], newValue[1]]);
|
||||
@@ -21,27 +26,31 @@ export default function PriceSlider({ min = 0, max = 100, onChange }: PriceSlide
|
||||
|
||||
const handleCommitted = (_: Event, newValue: number | number[]) => {
|
||||
if (Array.isArray(newValue)) {
|
||||
onChange?.([newValue[0], newValue[1]]);
|
||||
onChange?.([newValue[0], newValue[1]]); // Übergebe die neuen Werte an die übergeordnete Komponente
|
||||
}
|
||||
};
|
||||
|
||||
const formatValueToEuro = (value: number) => {
|
||||
return `${(value / 100).toFixed(2)} €`; // Umrechnung von Cent in Euro
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>{t('price')}</h3>
|
||||
<Box sx={{pl: 1, pr: 1}}>
|
||||
<Box sx={{ pl: 1, pr: 1 }}>
|
||||
<Slider
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
onChangeCommitted={handleCommitted}
|
||||
valueLabelDisplay="auto"
|
||||
valueLabelFormat={formatValueToEuro} // Formatierung der Werte in Euro
|
||||
min={min}
|
||||
max={max}
|
||||
step={1}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{display: 'flex', justifyContent: 'space-between'}}>
|
||||
<Typography>{value[0]?.toFixed(2) ?? "0.00"} €</Typography>
|
||||
<Typography>{value[1]?.toFixed(2) ?? "0.00"} €</Typography>
|
||||
<Typography>
|
||||
{formatValueToEuro(value[0])} - {formatValueToEuro(value[1])}
|
||||
</Typography>
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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 { Alert, Box, Button, Card, Divider, Grid, IconButton, Rating, Snackbar, SnackbarCloseReason, Stack, TextField, Typography } from "@mui/material";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Item from "../../components/Item";
|
||||
import { useBasket } from "../BasketProvider";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
export default function ProductInfo({ item }: { item: Item }) {
|
||||
|
||||
@@ -53,7 +53,23 @@ export default function ProductInfo({ item }: { item: Item }) {
|
||||
setImageDimensions({ width: naturalWidth, height: naturalHeight });
|
||||
};
|
||||
|
||||
const imageUrl = `http://localhost:8085/image?articleId=${item.id}`;
|
||||
const [imageUrl, setImageUrl] = useState<string>("/src/assets/default.jpg"); // Fallback-Bild
|
||||
|
||||
useEffect(() => {
|
||||
const fetchImage = async () => {
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8085/image?uuid=${item.uuid}`);
|
||||
const data = await response.json();
|
||||
if (data.uri) {
|
||||
setImageUrl(data.uri); // Bild-URL setzen
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden des Bildes:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchImage();
|
||||
}, [item.uuid]);
|
||||
|
||||
return (
|
||||
<Grid container spacing={4}>
|
||||
@@ -89,8 +105,8 @@ export default function ProductInfo({ item }: { item: Item }) {
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<Rating value={item.rating} precision={0.5} readOnly />
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{item.rating > 0 ? `(${item.rating} / 5)`: t('noRatingsYet')}
|
||||
|
||||
{item.rating > 0 ? `(${item.rating} / 5)` : t('noRatingsYet')}
|
||||
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -98,14 +114,14 @@ export default function ProductInfo({ item }: { item: Item }) {
|
||||
{item.discount100 > 0 ? (
|
||||
<>
|
||||
<Typography variant="h4" color="green">
|
||||
{discountedPrice.toFixed(2)} €
|
||||
{(discountedPrice / 100).toFixed(2)} €
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="text.secondary"
|
||||
sx={{ textDecoration: 'line-through' }}
|
||||
>
|
||||
{item.price100.toFixed(2)} €
|
||||
{(item.price100 / 100).toFixed(2)} €
|
||||
</Typography>
|
||||
<Typography variant="h6" color="error">
|
||||
-{item.discount100} %
|
||||
@@ -113,7 +129,7 @@ export default function ProductInfo({ item }: { item: Item }) {
|
||||
</>
|
||||
) : (
|
||||
<Typography variant="h4" color="green">
|
||||
{item.price100.toFixed(2)} €
|
||||
{(item.price100 / 100).toFixed(2)} €
|
||||
</Typography>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import RatingSubmitType from "../../components/RatingSubmit";
|
||||
|
||||
export const fetchItemList = async () => {
|
||||
const response = await fetch('http://localhost:8085/item/all');
|
||||
const response = await fetch('http://localhost:8085/article/all');
|
||||
console.log("API Response:", response);
|
||||
if (!response.ok) {
|
||||
throw new Error('Fehler beim Laden der Items');
|
||||
|
||||
Reference in New Issue
Block a user