fixed logo
BIN
app/favicon.ico
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 15 KiB |
@@ -67,7 +67,7 @@ export default function Header({ locale = "ru" }: HeaderProps) {
|
|||||||
src={Logo}
|
src={Logo}
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
fill
|
fill
|
||||||
className="object-contain"
|
className="object-contain mt-2"
|
||||||
priority
|
priority
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -289,13 +289,12 @@ export default function CartItemCard({ item, onUpdate }: CartItemCardProps) {
|
|||||||
className="object-contain p-2"
|
className="object-contain p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start gap-2 pt-2">
|
<div className="flex items-start gap-2 pt-2">
|
||||||
<h3 className="font-bold text-base text-gray-900 line-clamp-2">
|
<h3 className="font-bold text-base text-gray-900 line-clamp-2">
|
||||||
{item.product.name}
|
{item.product.name}
|
||||||
</h3>
|
</h3>
|
||||||
{/* <div
|
{/* <div
|
||||||
className="text-gray-700 leading-relaxed prose prose-sm max-w-none
|
className="text-gray-700 leading-relaxed prose prose-sm max-w-none
|
||||||
prose-headings:text-gray-900 prose-headings:font-bold
|
prose-headings:text-gray-900 prose-headings:font-bold
|
||||||
prose-p:text-gray-700 prose-p:leading-relaxed
|
prose-p:text-gray-700 prose-p:leading-relaxed
|
||||||
@@ -312,7 +311,7 @@ export default function CartItemCard({ item, onUpdate }: CartItemCardProps) {
|
|||||||
}}
|
}}
|
||||||
/> */}
|
/> */}
|
||||||
|
|
||||||
{/* {availableStock <= 5 && (
|
{/* {availableStock <= 5 && (
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<div className="h-2 w-2 rounded-full bg-amber-500 animate-pulse" />
|
<div className="h-2 w-2 rounded-full bg-amber-500 animate-pulse" />
|
||||||
<p className="text-xs text-amber-600 font-semibold">
|
<p className="text-xs text-amber-600 font-semibold">
|
||||||
@@ -321,16 +320,16 @@ export default function CartItemCard({ item, onUpdate }: CartItemCardProps) {
|
|||||||
</div>
|
</div>
|
||||||
)} */}
|
)} */}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={handleDelete}
|
onClick={handleDelete}
|
||||||
disabled={isRemoving}
|
disabled={isRemoving}
|
||||||
className="w-fit cursor-pointer pt-1 h-auto hover:bg-transparent text-gray-600 hover:text-red-500 transition-colors group"
|
className="w-fit cursor-pointer pt-1 h-auto hover:bg-transparent text-gray-600 hover:text-red-500 transition-colors group"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-5 w-5 group-hover:scale-110 transition-transform" />
|
<Trash2 className="h-5 w-5 group-hover:scale-110 transition-transform" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Price & Quantity */}
|
{/* Price & Quantity */}
|
||||||
<div className="flex flex-col items-start gap-2">
|
<div className="flex flex-col items-start gap-2">
|
||||||
@@ -396,15 +395,15 @@ export default function CartItemCard({ item, onUpdate }: CartItemCardProps) {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={handleQuantityIncrease}
|
onClick={handleQuantityIncrease}
|
||||||
disabled={isSyncing || localQuantity >= availableStock}
|
disabled={isSyncing}
|
||||||
className={`rounded-[10px] h-10 w-10 cursor-pointer border-2 transition-all duration-200 ${
|
className={`rounded-[10px] h-10 w-10 cursor-pointer border-2 transition-all duration-200 ${
|
||||||
localQuantity >= availableStock
|
localQuantity >= availableStock
|
||||||
? "opacity-30 cursor-not-allowed border-gray-200"
|
? "opacity-60 border-gray-200"
|
||||||
: "border-gray-900 bg-gray-900 hover:bg-gray-800"
|
: "border-gray-900 bg-gray-900 hover:bg-gray-800"
|
||||||
} ${isSyncing ? "opacity-50" : ""}`}
|
} ${isSyncing ? "opacity-50" : ""}`}
|
||||||
>
|
>
|
||||||
<Plus
|
<Plus
|
||||||
className={`h-4 w-4 ${localQuantity >= availableStock ? "text-gray-400" : "text-white"}`}
|
className={`h-4 w-4 ${localQuantity >= availableStock ? "text-gray-900" : "text-white"}`}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { useToggleFavorite, useIsFavorite } from "@/lib/hooks";
|
|||||||
import {
|
import {
|
||||||
useAddToCart,
|
useAddToCart,
|
||||||
useUpdateCartItemQuantity,
|
useUpdateCartItemQuantity,
|
||||||
|
useRemoveFromCart,
|
||||||
useCart,
|
useCart,
|
||||||
} from "@/features/cart/hooks/useCart";
|
} from "@/features/cart/hooks/useCart";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
@@ -73,6 +74,7 @@ export default function ProductCard({
|
|||||||
useToggleFavorite();
|
useToggleFavorite();
|
||||||
const addToCartMutation = useAddToCart();
|
const addToCartMutation = useAddToCart();
|
||||||
const updateCartMutation = useUpdateCartItemQuantity();
|
const updateCartMutation = useUpdateCartItemQuantity();
|
||||||
|
const removeFromCartMutation = useRemoveFromCart();
|
||||||
const { data: cartData, refetch: refetchCart } = useCart();
|
const { data: cartData, refetch: refetchCart } = useCart();
|
||||||
|
|
||||||
const [api, setApi] = useState<CarouselApi>();
|
const [api, setApi] = useState<CarouselApi>();
|
||||||
@@ -91,7 +93,7 @@ export default function ProductCard({
|
|||||||
const cartItem = cartData?.data?.find((item: any) => item.product?.id === id);
|
const cartItem = cartData?.data?.find((item: any) => item.product?.id === id);
|
||||||
const isInCart = !!cartItem;
|
const isInCart = !!cartItem;
|
||||||
const isOutOfStock = stock === 0;
|
const isOutOfStock = stock === 0;
|
||||||
const availableStock = stock || 999;
|
const availableStock = stock || 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!api) return;
|
if (!api) return;
|
||||||
@@ -118,7 +120,11 @@ export default function ProductCard({
|
|||||||
setIsSyncing(true);
|
setIsSyncing(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateCartMutation.mutateAsync({ productId: id, quantity });
|
if (quantity === 0) {
|
||||||
|
await removeFromCartMutation.mutateAsync(id);
|
||||||
|
} else {
|
||||||
|
await updateCartMutation.mutateAsync({ productId: id, quantity });
|
||||||
|
}
|
||||||
await refetchCart();
|
await refetchCart();
|
||||||
|
|
||||||
if (pendingQuantityRef.current !== null) {
|
if (pendingQuantityRef.current !== null) {
|
||||||
@@ -213,7 +219,7 @@ export default function ProductCard({
|
|||||||
|
|
||||||
const newQuantity = localQuantity + delta;
|
const newQuantity = localQuantity + delta;
|
||||||
|
|
||||||
if (newQuantity < 1) return;
|
if (newQuantity < 0) return;
|
||||||
|
|
||||||
if (newQuantity > availableStock) {
|
if (newQuantity > availableStock) {
|
||||||
setShowStockModal(true);
|
setShowStockModal(true);
|
||||||
@@ -222,7 +228,7 @@ export default function ProductCard({
|
|||||||
|
|
||||||
setLocalQuantity(newQuantity);
|
setLocalQuantity(newQuantity);
|
||||||
},
|
},
|
||||||
[localQuantity, availableStock],
|
[localQuantity, availableStock, setShowStockModal],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCardClick = useCallback(
|
const handleCardClick = useCallback(
|
||||||
@@ -425,7 +431,7 @@ export default function ProductCard({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={(e) => handleQuantityChange(e, -1)}
|
onClick={(e) => handleQuantityChange(e, -1)}
|
||||||
disabled={isSyncing || localQuantity <= 1}
|
disabled={isSyncing}
|
||||||
className="rounded-[10px] cursor-pointer h-7 md:h-9 w-7 md:w-9 border-2 border-gray-200 hover:border-gray-900 hover:bg-gray-50 transition-all duration-200 disabled:opacity-30"
|
className="rounded-[10px] cursor-pointer h-7 md:h-9 w-7 md:w-9 border-2 border-gray-200 hover:border-gray-900 hover:bg-gray-50 transition-all duration-200 disabled:opacity-30"
|
||||||
>
|
>
|
||||||
<Minus className="h-5 w-5 text-gray-700" />
|
<Minus className="h-5 w-5 text-gray-700" />
|
||||||
@@ -447,9 +453,15 @@ export default function ProductCard({
|
|||||||
size="icon"
|
size="icon"
|
||||||
onClick={(e) => handleQuantityChange(e, 1)}
|
onClick={(e) => handleQuantityChange(e, 1)}
|
||||||
disabled={isSyncing}
|
disabled={isSyncing}
|
||||||
className="rounded-[10px] cursor-pointer h-7 md:h-9 w-7 md:w-9 border-2 border-gray-900 bg-gray-900 hover:bg-gray-800 transition-all duration-200 disabled:opacity-30"
|
className={`rounded-[10px] cursor-pointer h-7 md:h-9 w-7 md:w-9 border-2 transition-all duration-200 disabled:opacity-30 ${
|
||||||
|
localQuantity >= availableStock
|
||||||
|
? "opacity-60 border-gray-200"
|
||||||
|
: "border-gray-900 bg-gray-900 hover:bg-gray-800"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<Plus className="h-5 w-5 text-white" />
|
<Plus
|
||||||
|
className={`h-5 w-5 ${localQuantity >= availableStock ? "text-gray-900" : "text-white"}`}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export default function CollectionSection({ collection, locale }: Props) {
|
|||||||
m.images_800x800 ||
|
m.images_800x800 ||
|
||||||
m.images_720x720 ||
|
m.images_720x720 ||
|
||||||
m.images_400x400 ||
|
m.images_400x400 ||
|
||||||
m.thumbnail
|
m.thumbnail,
|
||||||
)
|
)
|
||||||
.filter(Boolean) || ["/placeholder-product.jpg"];
|
.filter(Boolean) || ["/placeholder-product.jpg"];
|
||||||
|
|
||||||
@@ -95,10 +95,11 @@ export default function CollectionSection({ collection, locale }: Props) {
|
|||||||
// height={450}
|
// height={450}
|
||||||
// width={350}
|
// width={350}
|
||||||
button={true}
|
button={true}
|
||||||
|
stock={product.stock}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,10 +111,12 @@ export function ProductPurchaseCard({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={onQuantityIncrease}
|
onClick={onQuantityIncrease}
|
||||||
disabled={isSyncing || localQuantity >= availableStock}
|
disabled={isSyncing}
|
||||||
className={`rounded-[10px] h-12 w-12 border-2 border-gray-900 bg-gray-900 hover:bg-gray-800 transition-all duration-200 disabled:opacity-30 disabled:cursor-not-allowed ${
|
className={`rounded-[10px] h-12 w-12 border-2 border-gray-900 bg-gray-900 hover:bg-gray-800 transition-all duration-200 ${
|
||||||
isSyncing ? "opacity-50" : ""
|
localQuantity >= availableStock
|
||||||
}`}
|
? "opacity-60 border-gray-200"
|
||||||
|
: ""
|
||||||
|
} ${isSyncing ? "opacity-50" : ""}`}
|
||||||
>
|
>
|
||||||
<Plus className="h-5 w-5 text-white" />
|
<Plus className="h-5 w-5 text-white" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
BIN
public/logo.png
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 5.8 MiB |
|
Before Width: | Height: | Size: 3.0 MiB |
|
Before Width: | Height: | Size: 390 KiB |
|
Before Width: | Height: | Size: 17 MiB |
|
Before Width: | Height: | Size: 6.8 MiB |