"use client"; import { useGetFoods } from "@/app/[name]/(Main)/hooks/useMenuData"; import { useGetProfile } from "@/app/[name]/(Profile)/profile/hooks/userProfileData"; import { hasAuthToken } from "@/lib/api/func"; import { useReceiptStore } from "@/zustand/receiptStore"; import { useEffect, useMemo, useState } from "react"; import { cartItemsToFoods, guestCartItemsToFoods, hasCartEntries, } from "../lib/cartUtils"; import { useBulkCart, useGetCartItems } from "./useCartData"; function useReceiptHydrated() { const [hydrated, setHydrated] = useState(() => useReceiptStore.persist.hasHydrated() ); useEffect(() => { const unsub = useReceiptStore.persist.onFinishHydration(() => setHydrated(true) ); setHydrated(useReceiptStore.persist.hasHydrated()); return unsub; }, []); return hydrated; } export function useCartPageState() { const { isSuccess, isPending: profilePending, isFetched: profileFetched, } = useGetProfile(); const localItems = useReceiptStore((state) => state.items); const clearLocalCart = useReceiptStore((state) => state.clear); const receiptHydrated = useReceiptHydrated(); const [offlineSyncState, setOfflineSyncState] = useState< "idle" | "syncing" | "done" >("idle"); const { data: cartData, isPending: cartPending, isFetching: cartFetching, isFetched: cartFetched, } = useGetCartItems(isSuccess); const { mutate: mutateBulkCart, isPending: bulkSyncPending } = useBulkCart(); const { data: foodsResponse, isPending: foodsPending } = useGetFoods(); const foods = foodsResponse?.data ?? []; const apiItems = cartData?.data?.items ?? []; const apiTotalItems = cartData?.data?.totalItems ?? 0; const apiHasItems = apiTotalItems > 0 || apiItems.some((item) => item.quantity > 0); const localHasItems = hasCartEntries(localItems); useEffect(() => { if ( !isSuccess || !cartFetched || apiHasItems || !localHasItems || offlineSyncState !== "idle" || bulkSyncPending ) { return; } const bulkItems = Object.entries(localItems) .filter(([, detail]) => detail?.quantity && detail.quantity > 0) .map(([foodId, detail]) => ({ foodId: String(foodId), quantity: detail.quantity, })); if (bulkItems.length === 0) { return; } setOfflineSyncState("syncing"); mutateBulkCart( { items: bulkItems }, { onSuccess: () => clearLocalCart(), onSettled: () => setOfflineSyncState("done"), } ); }, [ isSuccess, cartFetched, apiHasItems, localHasItems, localItems, bulkSyncPending, offlineSyncState, mutateBulkCart, clearLocalCart, ]); const cartFoods = useMemo(() => { if (isSuccess) { return cartItemsToFoods(apiItems, foods); } return guestCartItemsToFoods(localItems, foods); }, [isSuccess, apiItems, localItems, foods]); const isAuthResolving = hasAuthToken() && (!profileFetched || profilePending); const isCartResolving = isSuccess && (!cartFetched || cartPending); const isCartRefetchingEmpty = isSuccess && cartFetched && cartFetching && !apiHasItems; const needsOfflineSync = isSuccess && cartFetched && localHasItems && !apiHasItems; const isOfflineSyncing = needsOfflineSync && offlineSyncState !== "done"; const isGuestHydrating = !hasAuthToken() && !receiptHydrated; const guestAwaitingMenu = !isSuccess && localHasItems && cartFoods.length === 0 && (foodsPending || foods.length === 0); const isLoading = isAuthResolving || isCartResolving || isCartRefetchingEmpty || isOfflineSyncing || isGuestHydrating || guestAwaitingMenu; const hasItems = isSuccess ? apiHasItems : localHasItems; const isCartEmpty = !isLoading && !hasItems; return { isLoading, isCartEmpty, hasItems, cartFoods, }; }