| 
 | 1 | +import { push } from 'notivue';  | 
 | 2 | + | 
 | 3 | +export const useCart = () => {  | 
 | 4 | +  const cart = useState<CartItem[]>('cart', () => []);  | 
 | 5 | +  const addToCartButtonStatus = ref<AddBtnStatus>('add');  | 
 | 6 | +  const removeFromCartButtonStatus = ref<RemoveBtnStatus>('remove');  | 
 | 7 | + | 
 | 8 | +  const findItem = (variationId: number) => cart.value.find(i => i.variation?.node?.databaseId === variationId);  | 
 | 9 | + | 
 | 10 | +  const updateCart = (next: CartItem[]) => {  | 
 | 11 | +    cart.value = next;  | 
 | 12 | +    if (process.client) localStorage.setItem('cart', JSON.stringify(next));  | 
 | 13 | +  };  | 
 | 14 | + | 
 | 15 | +  const handleAddToCart = async (productId: number) => {  | 
 | 16 | +    try {  | 
 | 17 | +      addToCartButtonStatus.value = 'loading';  | 
 | 18 | +      const res = await $fetch<AddToCartResponse>('/api/cart/add', { method: 'POST', body: { productId } });  | 
 | 19 | +      const incoming = res.addToCart.cartItem;  | 
 | 20 | +      const idx = cart.value.findIndex(i => i.key === incoming.key);  | 
 | 21 | + | 
 | 22 | +      if (idx > -1) {  | 
 | 23 | +        const merged = { ...cart.value[idx], ...incoming };  | 
 | 24 | +        if (typeof incoming.variation?.node?.stockQuantity === 'number') {  | 
 | 25 | +          merged.variation.node.stockQuantity = incoming.variation.node.stockQuantity;  | 
 | 26 | +        }  | 
 | 27 | +        updateCart([...cart.value.slice(0, idx), merged, ...cart.value.slice(idx + 1)]);  | 
 | 28 | +      } else {  | 
 | 29 | +        updateCart([...cart.value, incoming]);  | 
 | 30 | +      }  | 
 | 31 | + | 
 | 32 | +      addToCartButtonStatus.value = 'added';  | 
 | 33 | +      setTimeout(() => (addToCartButtonStatus.value = 'add'), 2000);  | 
 | 34 | +    } catch {  | 
 | 35 | +      addToCartButtonStatus.value = 'add';  | 
 | 36 | +      push.error('Insufficient stock');  | 
 | 37 | +    }  | 
 | 38 | +  };  | 
 | 39 | + | 
 | 40 | +  const changeQty = (key: string, quantity: number) => {  | 
 | 41 | +    try {  | 
 | 42 | +      $fetch('/api/cart/update', { method: 'POST', body: { items: [{ key, quantity }] } });  | 
 | 43 | +      if (quantity <= 0) updateCart(cart.value.filter(i => i.key !== key));  | 
 | 44 | +      else updateCart(cart.value.map(i => (i.key === key ? { ...i, quantity } : i)));  | 
 | 45 | +    } catch {  | 
 | 46 | +      push.error('Unable to update quantity');  | 
 | 47 | +    }  | 
 | 48 | +  };  | 
 | 49 | + | 
 | 50 | +  const handleRemoveFromCart = async (key: string) => {  | 
 | 51 | +    try {  | 
 | 52 | +      removeFromCartButtonStatus.value = 'loading';  | 
 | 53 | +      changeQty(key, 0);  | 
 | 54 | +    } finally {  | 
 | 55 | +      removeFromCartButtonStatus.value = 'remove';  | 
 | 56 | +    }  | 
 | 57 | +  };  | 
 | 58 | + | 
 | 59 | +  const increment = async (variationId: number) => {  | 
 | 60 | +    const item = findItem(variationId);  | 
 | 61 | +    if (!item) return handleAddToCart(variationId);  | 
 | 62 | +    const max = item.variation?.node?.stockQuantity ?? Infinity;  | 
 | 63 | +    if (item.quantity >= max) return push.error('Insufficient stock');  | 
 | 64 | +    changeQty(item.key, item.quantity + 1);  | 
 | 65 | +  };  | 
 | 66 | + | 
 | 67 | +  const decrement = async (variationId: number) => {  | 
 | 68 | +    const item = findItem(variationId);  | 
 | 69 | +    if (item) changeQty(item.key, item.quantity - 1);  | 
 | 70 | +  };  | 
 | 71 | + | 
 | 72 | +  onMounted(() => {  | 
 | 73 | +    if (!process.client) return;  | 
 | 74 | +    const stored = localStorage.getItem('cart');  | 
 | 75 | +    if (!stored) return;  | 
 | 76 | +    try {  | 
 | 77 | +      updateCart(JSON.parse(stored) as CartItem[]);  | 
 | 78 | +    } catch {  | 
 | 79 | +      updateCart([]);  | 
 | 80 | +    }  | 
 | 81 | +  });  | 
 | 82 | + | 
 | 83 | +  return {  | 
 | 84 | +    cart,  | 
 | 85 | +    addToCartButtonStatus,  | 
 | 86 | +    removeFromCartButtonStatus,  | 
 | 87 | +    handleAddToCart,  | 
 | 88 | +    handleRemoveFromCart,  | 
 | 89 | +    increment,  | 
 | 90 | +    decrement,  | 
 | 91 | +  };  | 
 | 92 | +};  | 
0 commit comments