151 lines
5.2 KiB
React
151 lines
5.2 KiB
React
import PageLayout from "../components/PageLayout";
|
||
import { useState, useEffect } from "react";
|
||
import { useParams } from "react-router-dom";
|
||
import { getItem, addToCart } from "../api/index";
|
||
import Arrow from "../components/Arrow";
|
||
|
||
export default function ItemPage() {
|
||
const { id } = useParams();
|
||
const [item, setItem] = useState(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [quantity, setQuantity] = useState(1);
|
||
|
||
useEffect(() => {
|
||
getItem(id)
|
||
.then((res) => setItem(res.data))
|
||
.catch(() => { })
|
||
.finally(() => setLoading(false));
|
||
}, [id]);
|
||
|
||
const isPiece = item?.unit_type === "piece";
|
||
const step = isPiece ? 1 : 0.1;
|
||
const minValue = isPiece ? 1 : 0.1;
|
||
|
||
useEffect(() => {
|
||
if (item) setQuantity(isPiece ? 1 : 0.1);
|
||
}, [item, isPiece]);
|
||
|
||
const handleIncrement = () => {
|
||
setQuantity((prev) => parseFloat((prev + step).toFixed(3)));
|
||
};
|
||
const handleDecrement = () => {
|
||
setQuantity((prev) =>
|
||
prev > minValue ? parseFloat((prev - step).toFixed(3)) : minValue,
|
||
);
|
||
};
|
||
|
||
const handleAddToCart = async () => {
|
||
try {
|
||
await addToCart({ item_id: item.id, quantity });
|
||
alert(`${item.name} добавлен в корзину`);
|
||
} catch {
|
||
alert("Не удалось добавить товар в корзину");
|
||
}
|
||
};
|
||
|
||
if (loading) {
|
||
return (
|
||
<PageLayout>
|
||
<p className="text-white p-6 md:p-16">Загрузка...</p>
|
||
</PageLayout>
|
||
);
|
||
}
|
||
|
||
if (!item) {
|
||
return (
|
||
<PageLayout>
|
||
<p className="text-white p-6 md:p-16">Товар не найден</p>
|
||
</PageLayout>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<PageLayout>
|
||
<main className="px-6 md:px-16 grow w-full mb-10 text-white">
|
||
<div className="flex flex-col md:flex-row gap-8 md:gap-12 mt-6">
|
||
{/* ЛЕВО — фото */}
|
||
<div className="md:w-1/2">
|
||
<img
|
||
src={item.avatar_url}
|
||
alt={item.name}
|
||
className="w-full h-[300px] md:h-[500px] object-cover rounded-lg"
|
||
/>
|
||
</div>
|
||
|
||
{/* ПРАВО — всё инфо в одной колонке */}
|
||
<div className="md:w-1/2 flex flex-col">
|
||
<h1 className="text-2xl md:text-4xl font-medium uppercase mb-3">
|
||
{item.name}
|
||
</h1>
|
||
|
||
<p className="text-2xl md:text-3xl font-medium mb-6">
|
||
{item.price} ₽
|
||
<span className="text-base text-white/50"> / {item.unit}</span>
|
||
</p>
|
||
|
||
<div className="flex flex-col gap-2 text-white/70 text-sm md:text-base mb-8">
|
||
<div className="flex justify-between border-b border-white/10 pb-2">
|
||
<span className="text-white/50">Категория</span>
|
||
<span>{item.category}</span>
|
||
</div>
|
||
<div className="flex justify-between border-b border-white/10 pb-2">
|
||
<span className="text-white/50">Город</span>
|
||
<span>{item.city}</span>
|
||
</div>
|
||
<div className="flex justify-between border-b border-white/10 pb-2">
|
||
<span className="text-white/50">Тип</span>
|
||
<span>{isPiece ? "Поштучно" : "На вес"}</span>
|
||
</div>
|
||
<div className="flex justify-between border-b border-white/10 pb-2">
|
||
<span className="text-white/50">В наличии</span>
|
||
<span
|
||
className={item.stock > 0 ? "text-green-400" : "text-red-400"}
|
||
>
|
||
{item.stock > 0 ? `${item.stock} ${item.unit}` : "нет"}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-6 mb-6">
|
||
<span className="text-white/50 text-sm">Количество:</span>
|
||
<button
|
||
onClick={handleDecrement}
|
||
className="w-10 h-10 flex items-center justify-center bg-white/10 hover:bg-white/20 rounded font-medium text-xl cursor-pointer select-none transition-colors"
|
||
>
|
||
-
|
||
</button>
|
||
<span className="mx-2 font-mono text-sm min-w-20 text-center">
|
||
{quantity} {item.unit}
|
||
</span>
|
||
<button
|
||
onClick={handleIncrement}
|
||
className="w-10 h-10 flex items-center justify-center bg-white/10 hover:bg-white/20 rounded font-medium text-xl cursor-pointer select-none transition-colors"
|
||
>
|
||
+
|
||
</button>
|
||
</div>
|
||
|
||
<p className="text-lg mb-6">
|
||
Стоимость:{" "}
|
||
<span className="font-medium">
|
||
{parseFloat((quantity * item.price).toFixed(2))} ₽
|
||
</span>
|
||
</p>
|
||
|
||
<button
|
||
onClick={handleAddToCart}
|
||
disabled={item.stock <= 0}
|
||
className="group flex items-center gap-4 text-base font-bold text-white cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"
|
||
>
|
||
<span>
|
||
{item.stock > 0 ? "Добавить в корзину" : "Нет в наличии"}
|
||
</span>
|
||
<Arrow />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</PageLayout>
|
||
);
|
||
}
|