119 lines
3.7 KiB
TypeScript
119 lines
3.7 KiB
TypeScript
'use client';
|
|
|
|
import { Button } from "@/components/ui/Button";
|
|
import { useAppDispatch, useAppSelector } from "@/lib/redux/hooks";
|
|
import { addToBox, removeFromBox, selectBoxItems } from "@/lib/redux/slices/boxSlice";
|
|
import Image from "next/image";
|
|
import { useEffect, useState } from "react";
|
|
|
|
// Box option interface
|
|
export interface BoxOption {
|
|
id: string;
|
|
title: string;
|
|
price: number;
|
|
image: string;
|
|
}
|
|
|
|
interface BoxCustomizeProps {
|
|
boxes: BoxOption[];
|
|
}
|
|
|
|
export function BuildBoxCustomizeClient({ boxes }: BoxCustomizeProps) {
|
|
const [selectedBoxId, setSelectedBoxId] = useState<string | null>(null);
|
|
const dispatch = useAppDispatch();
|
|
const items = useAppSelector(selectBoxItems);
|
|
|
|
// Check if there's already a box in the items and set it as selected on load
|
|
useEffect(() => {
|
|
const existingBox = items.find(item => item.variantId === 'box-container');
|
|
if (existingBox) {
|
|
setSelectedBoxId(existingBox.id);
|
|
}
|
|
}, [items]);
|
|
|
|
// When a box is selected, replace any existing box with the new one
|
|
const handleSelectBox = (box: BoxOption) => {
|
|
// If the same box is already selected, do nothing
|
|
if (selectedBoxId === box.id) return;
|
|
|
|
// Set this box as selected
|
|
setSelectedBoxId(box.id);
|
|
|
|
// Remove any existing box containers first
|
|
const existingBoxes = items.filter(item => item.variantId === 'box-container');
|
|
existingBoxes.forEach(existingBox => {
|
|
dispatch(removeFromBox({ id: existingBox.id, color: existingBox.color }));
|
|
});
|
|
|
|
// Add the new box
|
|
dispatch(addToBox({
|
|
id: box.id,
|
|
name: box.title,
|
|
price: box.price,
|
|
image: box.image,
|
|
quantity: 1,
|
|
variantId: 'box-container', // Mark this as a box container, not a product
|
|
}));
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
|
{boxes.map((box) => (
|
|
<BoxOption
|
|
key={box.id}
|
|
box={box}
|
|
isSelected={selectedBoxId === box.id}
|
|
onSelect={() => handleSelectBox(box)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Box option component
|
|
function BoxOption({
|
|
box,
|
|
isSelected,
|
|
onSelect
|
|
}: {
|
|
box: BoxOption;
|
|
isSelected: boolean;
|
|
onSelect: () => void;
|
|
}) {
|
|
return (
|
|
<div className={`border rounded-md overflow-hidden ${isSelected ? 'ring-2 ring-primary' : ''}`}>
|
|
<div className="relative h-60 overflow-hidden">
|
|
<Image
|
|
src={box.image}
|
|
alt={box.title}
|
|
fill
|
|
className="object-cover transition-transform duration-300"
|
|
/>
|
|
{/* Overlay with "Dodaj u box" button - always visible for selected, only on hover for others */}
|
|
<div className={`absolute inset-0 flex items-center justify-center ${isSelected ? 'bg-black/40' : 'bg-black/40 opacity-0 hover:opacity-100 transition-opacity duration-300'}`}>
|
|
<Button
|
|
variant="custom"
|
|
onClick={onSelect}
|
|
>
|
|
Dodaj u box
|
|
</Button>
|
|
</div>
|
|
{isSelected && (
|
|
<div className="absolute top-2 right-2 bg-primary text-white rounded-full p-1 w-6 h-6 flex items-center justify-center">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<polyline points="20 6 9 17 4 12"></polyline>
|
|
</svg>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="p-4">
|
|
<div className="flex justify-between items-start">
|
|
<h3 className="font-medium">{box.title}</h3>
|
|
<span className="font-medium">${box.price.toFixed(2)}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|