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 }; }