197 lines
6.8 KiB
TypeScript
197 lines
6.8 KiB
TypeScript
"use client";
|
||
|
||
import { useGetFoods } from "@/app/[name]/(Main)/hooks/useMenuData";
|
||
import { useGetProfile } from "@/app/[name]/(Profile)/profile/hooks/userProfileData";
|
||
import Button from "@/components/button/PrimaryButton";
|
||
import NotificationBellIcon from "@/components/icons/NotificationBellIcon";
|
||
import MenuItem from "@/components/listview/MenuItem";
|
||
import MenuItemRenderer from "@/components/listview/MenuItemRenderer";
|
||
import PagerModal from "@/components/pager/PagerModal";
|
||
import Prompt from "@/components/utils/Prompt";
|
||
import { ArrowLeft, Trash } from "iconsax-react";
|
||
import Image from "next/image";
|
||
import { useRouter } from "next/navigation";
|
||
import React from "react";
|
||
import { useTranslation } from "react-i18next";
|
||
import { useGetAbout } from "../about/hooks/useAboutData";
|
||
import CartSkeleton from "./components/CartSkeleton";
|
||
import CartSummary from "./components/CartSummary";
|
||
import { useCart } from "./hook/useCart";
|
||
import { useGetCartItems } from "./hooks/useCartData";
|
||
import {
|
||
cartItemsToFoods,
|
||
guestCartItemsToFoods,
|
||
hasCartEntries,
|
||
} from "./lib/cartUtils";
|
||
|
||
const CartPage = () => {
|
||
const { t } = useTranslation("parallels", { keyPrefix: "Cart" });
|
||
const router = useRouter();
|
||
const { isSuccess } = useGetProfile();
|
||
const { clearCart, items } = useCart();
|
||
const { data: cartData, isPending: cartPending } = useGetCartItems(isSuccess);
|
||
const { data: foodsResponse } = useGetFoods();
|
||
const { data: aboutData } = useGetAbout();
|
||
const [showClearConfirm, setShowClearConfirm] = React.useState(false);
|
||
const [showPagerModal, setShowPagerModal] = React.useState(false);
|
||
|
||
const isPremium = aboutData?.data?.plan === "premium";
|
||
|
||
const cartFoods = React.useMemo(() => {
|
||
const foods = foodsResponse?.data ?? [];
|
||
if (isSuccess) {
|
||
const apiItems = cartData?.data?.items ?? [];
|
||
return cartItemsToFoods(apiItems, foods);
|
||
}
|
||
return guestCartItemsToFoods(items, foods);
|
||
}, [isSuccess, cartData?.data?.items, items, foodsResponse?.data]);
|
||
|
||
const hasItems = React.useMemo(() => {
|
||
if (isSuccess) {
|
||
return (cartData?.data?.totalItems ?? 0) > 0 || hasCartEntries(items);
|
||
}
|
||
return hasCartEntries(items);
|
||
}, [isSuccess, cartData?.data?.totalItems, items]);
|
||
|
||
const guestAwaitingMenu =
|
||
!isSuccess && hasItems && cartFoods.length === 0 && !foodsResponse?.data;
|
||
|
||
const showInitialCartLoad = isSuccess && cartPending && !cartData && hasItems;
|
||
|
||
const isCartEmpty = !hasItems;
|
||
|
||
const handleClearCart = (e: React.MouseEvent) => {
|
||
e?.preventDefault();
|
||
e?.stopPropagation();
|
||
clearCart();
|
||
setShowClearConfirm(false);
|
||
};
|
||
|
||
const toggleClearConfirm = (e: React.MouseEvent) => {
|
||
e?.preventDefault();
|
||
e?.stopPropagation();
|
||
setShowClearConfirm(false);
|
||
};
|
||
|
||
return (
|
||
<div className="overflow-y-auto h-full noscrollbar flex flex-col bg-background">
|
||
<div className="grid grid-cols-3 items-center mt-6">
|
||
{isCartEmpty ? (
|
||
<span></span>
|
||
) : (
|
||
<Trash
|
||
className="cursor-pointer place-self-start"
|
||
size="24"
|
||
color="currentColor"
|
||
onClick={() => setShowClearConfirm(true)}
|
||
/>
|
||
)}
|
||
<h1 className="text-sm2 place-self-center font-medium">
|
||
{t("Heading")}
|
||
</h1>
|
||
<ArrowLeft
|
||
className="cursor-pointer place-self-end"
|
||
size="24"
|
||
color="currentColor"
|
||
onClick={() => router.back()}
|
||
/>
|
||
</div>
|
||
|
||
<div className="mt-8 flex-1 h-full">
|
||
{showInitialCartLoad || guestAwaitingMenu ? (
|
||
<CartSkeleton />
|
||
) : isCartEmpty ? (
|
||
<div className="flex flex-col items-center justify-center gap-4 h-full">
|
||
<Image
|
||
src="/assets/images/cart.png"
|
||
alt="cart"
|
||
width={120}
|
||
height={120}
|
||
className="object-contain"
|
||
/>
|
||
<div className="flex flex-col items-center gap-2 text-sm2 text-muted-foreground">
|
||
<p>
|
||
{t("EmptyStateTitle", {
|
||
defaultValue: "سبد خرید شما خالی است",
|
||
})}
|
||
</p>
|
||
<p className="text-xs">
|
||
{t("EmptyStateDescription", {
|
||
defaultValue: "برای افزودن غذا، به منوی رستوران برگردید.",
|
||
})}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="flex flex-col gap-4 pb-24">
|
||
{!isPremium && (
|
||
<div className="bg-container rounded-container p-4 border border-border shadow-sm">
|
||
<div className="flex items-start gap-3 mb-4">
|
||
<div className="shrink-0 mt-0.5">
|
||
<NotificationBellIcon
|
||
width={24}
|
||
height={24}
|
||
className="currentColor"
|
||
/>
|
||
</div>
|
||
<div className="flex-1">
|
||
<p className="text-sm font-medium text-foreground mb-1">
|
||
ثبت سفارش
|
||
</p>
|
||
<p className="text-xs text-muted-foreground leading-5">
|
||
برای ثبت سفارش، لطفاً گارسون را صدا کنید
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<Button
|
||
onClick={() => setShowPagerModal(true)}
|
||
className="w-full dark:bg-white! dark:text-black! flex items-center justify-center gap-2"
|
||
>
|
||
<NotificationBellIcon
|
||
width={18}
|
||
height={18}
|
||
className="text-white dark:text-black!"
|
||
/>
|
||
<span>صدا کردن گارسون</span>
|
||
</Button>
|
||
</div>
|
||
)}
|
||
{cartFoods.map((food) => (
|
||
<MenuItemRenderer key={food.id}>
|
||
<MenuItem food={food} />
|
||
</MenuItemRenderer>
|
||
))}
|
||
<CartSummary isPremium={isPremium} hasItems={hasItems} />
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div
|
||
className={
|
||
showClearConfirm
|
||
? "fixed inset-0 z-1001"
|
||
: "pointer-events-none fixed inset-0 z-1001"
|
||
}
|
||
>
|
||
<Prompt
|
||
title="پاک کردن سبد خرید"
|
||
description="آیا از پاک کردن تمامی آیتمهای سبد خرید اطمینان دارید؟"
|
||
textConfirm="بله"
|
||
textCancel="خیر"
|
||
onConfirm={handleClearCart}
|
||
onCancel={toggleClearConfirm}
|
||
visible={showClearConfirm}
|
||
onClick={toggleClearConfirm}
|
||
/>
|
||
</div>
|
||
|
||
<PagerModal
|
||
visible={showPagerModal}
|
||
onClose={() => setShowPagerModal(false)}
|
||
/>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default CartPage;
|