This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
"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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user