chore: transfer repo

This commit is contained in:
Danijel
2026-01-19 20:21:14 +01:00
commit 7d2fb0c737
213 changed files with 18085 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
'use client';
import { colorHexMap } from '@/components/products/utils/colorUtils';
import { Button } from '@/components/ui/Button';
import { Text } from '@/components/ui/Typography';
import { useTranslation } from '@/lib/hooks/useTranslation';
import { useCart } from 'components/cart/cart-context';
import Price from 'components/price';
import { CartItem } from 'lib/shopify/types';
import { Trash2 } from 'lucide-react';
import Image from 'next/image';
import { QuantityControls } from './QuantityControls';
interface CartProductItemProps {
item: CartItem;
onUpdate: (merchandiseId: string, updateType: 'plus' | 'minus' | 'delete', itemId?: string) => void;
isPending: boolean;
isInBox?: boolean;
boxGroupId?: string;
}
export function CartProductItem({ item, onUpdate, isPending, isInBox = false, boxGroupId }: CartProductItemProps) {
const { t } = useTranslation();
const { cart } = useCart();
// Check if this item has a color option
const colorOption = item.merchandise.selectedOptions.find(option =>
option.name.toLowerCase() === 'color' ||
option.name.toLowerCase() === 'colour' ||
option.name.toLowerCase() === 'boja'
);
// Get the color hex code from the color name if it exists
const colorHex = colorOption
? colorHexMap[colorOption.value.toLowerCase()] || colorOption.value
: null;
// Get the unique ID of this cart item
const itemId = item.id;
// Handle quantity changes
const handleIncrease = () => onUpdate(item.merchandise.id, 'plus', itemId);
const handleDecrease = () => onUpdate(item.merchandise.id, 'minus', itemId);
// Enhanced delete handler
const handleDelete = () => {
// Basic delete operation for this item
onUpdate(item.merchandise.id, 'delete', itemId);
// Special handling for box items
if (isInBox && boxGroupId && cart) {
// Find all items in this box group
const boxItems = cart.lines.filter(line => {
const attrs = line.attributes || [];
const itemBoxGroupId = attrs.find(attr => attr.key === '_box_group_id')?.value;
const itemBoxType = attrs.find(attr => attr.key === '_box_type')?.value;
return itemBoxGroupId === boxGroupId && itemBoxType === 'item' && line.id !== itemId;
});
// If this is the last item (only 1 left - the one we're deleting), also delete the box container
if (boxItems.length === 0) {
// Find the box container
const boxContainer = cart.lines.find(line => {
const attrs = line.attributes || [];
const containerBoxGroupId = attrs.find(attr => attr.key === '_box_group_id')?.value;
const containerBoxType = attrs.find(attr => attr.key === '_box_type')?.value;
return containerBoxGroupId === boxGroupId && containerBoxType === 'container';
});
// Delete the box container too
if (boxContainer && boxContainer.id) {
onUpdate(boxContainer.merchandise.id, 'delete', boxContainer.id);
}
}
}
};
return (
<div className={`flex flex-wrap md:flex-nowrap items-start ${!isInBox ? 'border-b pb-6' : 'pb-4'}`}>
{/* Product Image */}
<div className="relative h-20 w-20 flex-shrink-0 overflow-hidden">
<Image
src={item.merchandise.product.featuredImage?.url || ''}
alt={item.merchandise.product.title}
fill
className="object-cover"
/>
</div>
{/* Product Details */}
<div className="flex-1 pl-4 min-w-0">
<div className="flex flex-col">
<Text weight={isInBox ? 'regular' : 'semibold'} className="pr-2 break-words">
{item.merchandise.product.title}
</Text>
{/* Show color indicator if color is available */}
{colorHex && (
<div className="flex items-center mt-1">
<div
className="w-4 h-4 rounded-full"
style={{ backgroundColor: colorHex }}
aria-label={`${colorOption?.value || 'Unknown'}`}
/>
<Text size="xs" color="muted" as="span" className="ml-2">
{colorOption?.value || ''}
</Text>
</div>
)}
<Price
amount={item.cost.totalAmount.amount}
currencyCode={item.cost.totalAmount.currencyCode}
className="text-sm mt-1"
/>
</div>
</div>
{/* Quantity Controls */}
<div className="flex items-center ml-auto mt-2 md:mt-0">
<div className="mr-4">
<QuantityControls
quantity={item.quantity}
onIncrease={handleIncrease}
onDecrease={handleDecrease}
isDisabled={isPending}
minQuantity={1}
/>
</div>
<Button
onClick={handleDelete}
variant="default"
className="p-0 h-auto border-0 bg-transparent hover:bg-transparent text-gray-500 hover:text-red-500"
disabled={isPending}
aria-label={t('cart.remove')}
>
<Trash2 size={20} />
</Button>
</div>
</div>
);
}