import { useState, useCallback } from 'react' import useSWR, { mutate } from 'swr' async function getText(res) { try { return (await res.text()) || res.statusText } catch (error) { return res.statusText } } async function getError(res) { if (res.headers.get('Content-Type')?.includes('application/json')) { const data = await res.json() return data.errors[0] } return { message: await getText(res) } } async function fetcher(url) { const res = await fetch(url) if (res.status === 200) { return res.json() } throw await getError(res) } export function useCart() { return useSWR('/api/cart', fetcher) } export function useAddToCart() { const [{ addingToCart, error }, setStatus] = useState({ addingToCart: false, }) const addToCart = useCallback(async ({ product }) => { setStatus({ addingToCart: true }) const res = await fetch('/api/cart', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ product }), }) // Product added as expected if (res.status === 200) { setStatus({ addingToCart: false }) return mutate('/api/cart') } const error = await getError(res) console.error('Adding product to cart failed with:', res.status, error) setStatus({ addingToCart: false, error }) }, []) return { addToCart, addingToCart, error } } export function useUpdateCart() { const [{ updatingCart, error }, setStatus] = useState({ updatingCart: false, }) const updateCart = useCallback(async ({ product, item }) => { setStatus({ updatingCart: true }) const res = await fetch( `/api/cart?itemId=${item.id}`, product.quantity < 1 ? { method: 'DELETE' } : { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ product }), } ) // Product updated as expected if (res.status === 200) { setStatus({ updatingCart: false }) return mutate('/api/cart') } const error = await getError(res) console.error('Update to cart failed with:', res.status, error) setStatus({ updatingCart: false, error }) }, []) return { updateCart, updatingCart, error } } export function useRemoveFromCart() { const { updateCart, updatingCart, error } = useUpdateCart() const removeFromCart = async ({ item }) => { updateCart({ item, product: { quantity: 0 } }) } return { removeFromCart, removingFromCart: updatingCart, error } }