173 lines
5.9 KiB
TypeScript
173 lines
5.9 KiB
TypeScript
'use client';
|
|
|
|
import { Button } from "@/components/ui/Button";
|
|
import { useAppDispatch, useAppSelector } from "@/lib/redux/hooks";
|
|
import { clearBox, selectBoxItems, selectEditingBoxGroupId } from "@/lib/redux/slices/boxSlice";
|
|
import { addItem, removeItem } from "components/cart/actions";
|
|
import { useCart } from "components/cart/cart-context";
|
|
import { Product, ProductVariant } from "lib/shopify/types";
|
|
import { useRouter } from "next/navigation";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export function AddBoxToCartClient() {
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [isLoadingProducts, setIsLoadingProducts] = useState(true);
|
|
const [allProducts, setAllProducts] = useState<Product[]>([]);
|
|
const [boxProducts, setBoxProducts] = useState<Product[]>([]);
|
|
const items = useAppSelector(selectBoxItems);
|
|
const editingBoxGroupId = useAppSelector(selectEditingBoxGroupId);
|
|
const { addCartItem, cart } = useCart();
|
|
const dispatch = useAppDispatch();
|
|
const router = useRouter();
|
|
|
|
// Fetch products on mount
|
|
useEffect(() => {
|
|
async function fetchProducts() {
|
|
setIsLoadingProducts(true);
|
|
try {
|
|
// Fetch regular products
|
|
const regularResponse = await fetch('/api/products');
|
|
const regularData = await regularResponse.json();
|
|
|
|
// Fetch box products
|
|
const boxesResponse = await fetch('/api/products?type=boxes');
|
|
const boxesData = await boxesResponse.json();
|
|
|
|
if (regularData.products) setAllProducts(regularData.products);
|
|
if (boxesData.products) setBoxProducts(boxesData.products);
|
|
} catch (error) {
|
|
console.error("Failed to fetch products:", error);
|
|
} finally {
|
|
setIsLoadingProducts(false);
|
|
}
|
|
}
|
|
|
|
fetchProducts();
|
|
}, []);
|
|
|
|
// Check if we have a box
|
|
const boxItems = items.filter(item => item.variantId === 'box-container');
|
|
const productItems = items.filter(item => item.variantId !== 'box-container');
|
|
|
|
const isEnabled = boxItems.length > 0 && !isLoadingProducts;
|
|
|
|
const handleAddToCart = async () => {
|
|
if (isLoading || !isEnabled) return;
|
|
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
// Save the current box state to localStorage for potential editing later
|
|
try {
|
|
const boxState = {
|
|
boxItems: boxItems,
|
|
productItems: productItems,
|
|
boxGroupId: `box-${Date.now()}`
|
|
};
|
|
localStorage.setItem('lastBoxState', JSON.stringify(boxState));
|
|
} catch (error) {
|
|
console.error("Failed to save box state:", error);
|
|
}
|
|
|
|
// Generate a unique box ID to group all items together
|
|
const boxGroupId = `box-${Date.now()}`;
|
|
|
|
// Ako je ovo uređivanje postojećeg boxa, prvo ukloni stari box i sve njegove proizvode
|
|
if (editingBoxGroupId && cart) {
|
|
// Pronađi sve proizvode i kontejner koji pripadaju ovom boxu
|
|
const itemsToRemove = cart.lines.filter(line => {
|
|
const attrs = line.attributes || [];
|
|
const itemBoxGroupId = attrs.find(attr => attr.key === 'box_group_id')?.value;
|
|
return itemBoxGroupId === editingBoxGroupId;
|
|
});
|
|
|
|
// Ukloni sve pronađene proizvode
|
|
for (const item of itemsToRemove) {
|
|
if (item.id && item.merchandise.id) {
|
|
await removeItem(null, item.merchandise.id, item.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add box items first
|
|
for (const boxItem of boxItems) {
|
|
// Find the actual box product from our pre-loaded products
|
|
const boxProduct = boxProducts.find(p => p.id === boxItem.id);
|
|
|
|
if (boxProduct) {
|
|
// Get the variant to use
|
|
const boxVariant = boxProduct.variants[0];
|
|
|
|
if (boxVariant) {
|
|
// Add box with attribute marking it as a box container and the box group ID
|
|
await addItem(
|
|
null,
|
|
boxVariant.id,
|
|
boxItem.quantity,
|
|
[
|
|
{ key: "_box_type", value: "container" },
|
|
{ key: "_box_group_id", value: boxGroupId }
|
|
]
|
|
);
|
|
|
|
// Update local cart state
|
|
addCartItem(boxVariant, boxProduct, boxItem.quantity);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add product items
|
|
for (const productItem of productItems) {
|
|
// Find the actual product from our pre-loaded products
|
|
const product = allProducts.find(p => p.id === productItem.id);
|
|
|
|
if (product) {
|
|
// Find the variant
|
|
let selectedVariant: ProductVariant | undefined;
|
|
|
|
if (productItem.variantId && productItem.variantId !== 'undefined') {
|
|
selectedVariant = product.variants.find(v => v.id === productItem.variantId);
|
|
}
|
|
|
|
// If no variant found, use the first one (exactly like AddToCartButton.tsx)
|
|
if (!selectedVariant) {
|
|
selectedVariant = product.variants[0];
|
|
}
|
|
|
|
if (selectedVariant && selectedVariant.id) {
|
|
// Add product with attribute marking it as a box item and the box group ID
|
|
await addItem(
|
|
null,
|
|
selectedVariant.id,
|
|
productItem.quantity,
|
|
[
|
|
{ key: "_box_type", value: "item" },
|
|
{ key: "_box_group_id", value: boxGroupId }
|
|
]
|
|
);
|
|
|
|
// Update local cart state
|
|
addCartItem(selectedVariant, product, productItem.quantity);
|
|
}
|
|
}
|
|
}
|
|
|
|
dispatch(clearBox());
|
|
} catch (error) {
|
|
console.error("Failed to add box to cart:", error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Button
|
|
onClick={handleAddToCart}
|
|
disabled={isLoading || !isEnabled}
|
|
variant="primary"
|
|
className="w-full py-3"
|
|
>
|
|
{isLoading ? "Dodaje se..." : isLoadingProducts ? "Učitavanje..." : "Dodaj u košaricu"}
|
|
</Button>
|
|
);
|
|
}
|