From 194533ec5f4dfcc9775de5027dc85c82ff35187f Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Wed, 3 Jun 2026 15:08:09 +0330 Subject: [PATCH] fast navigate + cache --- .../(Dialogs)/cart/components/CartSummary.tsx | 134 ------------------ src/app/[name]/(Dialogs)/cart/page.tsx | 17 --- .../[id]/components/CouponSection.tsx | 2 +- .../[id]/components/PaymentSection.tsx | 2 +- .../[id]/components/SummarySection.tsx | 6 +- .../(Dialogs)/order/checkout/[id]/page.tsx | 2 +- src/app/[name]/(Main)/[id]/page.tsx | 2 +- .../[name]/(Main)/about/hooks/useAboutData.ts | 2 + .../{(Dialogs) => (Main)}/cart/CartPage.tsx | 60 +++++--- .../cart/components/CartItemsList.tsx | 0 .../cart/components/CartSkeleton.tsx | 0 .../(Main)/cart/components/CartSummary.tsx | 115 +++++++++++++++ .../cart/hook/useCart.ts | 0 .../cart/hooks/useCartData.ts | 1 + src/app/[name]/(Main)/cart/lib/cartUtils.ts | 36 +++++ src/app/[name]/(Main)/cart/page.tsx | 5 + .../cart/service/CartService.ts | 0 .../{(Dialogs) => (Main)}/cart/store/Store.ts | 0 .../{(Dialogs) => (Main)}/cart/types/Types.ts | 0 src/app/[name]/(Main)/hooks/useMenuData.ts | 2 + src/app/[name]/lib/getRestaurant.ts | 11 +- src/components/CartChecker.tsx | 2 +- src/components/listview/MenuItem.tsx | 2 +- src/components/navigation/BottomNavBar.tsx | 2 +- src/components/navigation/BottomNavLink.tsx | 5 +- src/components/wrapper/ClientSideWrapper.tsx | 2 +- src/features/auth/components/StepOtp.tsx | 2 +- 27 files changed, 218 insertions(+), 194 deletions(-) delete mode 100644 src/app/[name]/(Dialogs)/cart/components/CartSummary.tsx delete mode 100644 src/app/[name]/(Dialogs)/cart/page.tsx rename src/app/[name]/{(Dialogs) => (Main)}/cart/CartPage.tsx (78%) rename src/app/[name]/{(Dialogs) => (Main)}/cart/components/CartItemsList.tsx (100%) rename src/app/[name]/{(Dialogs) => (Main)}/cart/components/CartSkeleton.tsx (100%) create mode 100644 src/app/[name]/(Main)/cart/components/CartSummary.tsx rename src/app/[name]/{(Dialogs) => (Main)}/cart/hook/useCart.ts (100%) rename src/app/[name]/{(Dialogs) => (Main)}/cart/hooks/useCartData.ts (99%) create mode 100644 src/app/[name]/(Main)/cart/lib/cartUtils.ts create mode 100644 src/app/[name]/(Main)/cart/page.tsx rename src/app/[name]/{(Dialogs) => (Main)}/cart/service/CartService.ts (100%) rename src/app/[name]/{(Dialogs) => (Main)}/cart/store/Store.ts (100%) rename src/app/[name]/{(Dialogs) => (Main)}/cart/types/Types.ts (100%) diff --git a/src/app/[name]/(Dialogs)/cart/components/CartSummary.tsx b/src/app/[name]/(Dialogs)/cart/components/CartSummary.tsx deleted file mode 100644 index 1121a27..0000000 --- a/src/app/[name]/(Dialogs)/cart/components/CartSummary.tsx +++ /dev/null @@ -1,134 +0,0 @@ -'use client'; - -import React from 'react'; -import Link from 'next/link'; -import { useParams, useRouter, usePathname } from 'next/navigation'; -import Button from '@/components/button/PrimaryButton'; -import { useGetFoods } from '@/app/[name]/(Main)/hooks/useMenuData'; -import type { Food } from '@/app/[name]/(Main)/types/Types'; -import { useCart } from '../hook/useCart'; -import { useTranslation } from 'react-i18next'; -import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; -import { useGetCartItems } from '../hooks/useCartData'; -import { useCartStore } from '../store/Store'; - -interface CartSummaryProps { - isPremium: boolean; -} - -const CartSummary = ({ isPremium }: CartSummaryProps) => { - const params = useParams(); - const router = useRouter(); - const pathname = usePathname(); - const name = params.name as string; - const { isSuccess } = useGetProfile(); - const { data: foodsResponse } = useGetFoods(); - const foods = React.useMemo(() => foodsResponse?.data ?? [], [foodsResponse?.data]); - const { items } = useCart(); - const { data: cartData } = useGetCartItems(isSuccess); - const { t } = useTranslation('parallels', { keyPrefix: 'Cart' }); - const { description, setDescription } = useCartStore(); - - const cartFoods = React.useMemo(() => { - if (!foods.length) return []; - return Object.entries(items) - .filter(([, detail]) => detail?.quantity && detail.quantity > 0) - .map(([id]) => - foods.find((foodItem) => String(foodItem.id) === String(id)) - ) - .filter((food): food is Food => Boolean(food)); - }, [foods, items]); - - const totalPrice = React.useMemo(() => { - // اگر داده از API آمده و total وجود دارد، از آن استفاده می‌کنیم - if (isSuccess && cartData?.data?.total !== undefined) { - return cartData.data.total; - } - - // در غیر این صورت، محاسبه محلی با در نظر گرفتن تخفیف - return cartFoods.reduce((sum, food) => { - const qty = items[String(food.id)]?.quantity ?? 0; - const basePrice = food.price ?? 0; - const discount = food.discount ?? 0; - const priceAfterDiscount = basePrice * (1 - discount / 100); - return sum + priceAfterDiscount * qty; - }, 0); - }, [cartFoods, items, isSuccess, cartData?.data?.total]); - - const isCartEmpty = cartFoods.length === 0; - - const formatPrice = React.useCallback( - (value: number) => value.toLocaleString('fa-IR'), - [] - ); - - return ( - <> - {!isCartEmpty && ( - <> - {isPremium && ( -
-
-

{t('InputDescription.Label')}

- - -
-
- )} - -
-
-
-
{t('PayableAmountLabel')}
- { - isPremium && -
{formatPrice(totalPrice)} تومان
- - } -
- - {isPremium && ( - { - if (!isSuccess) { - event.preventDefault(); - const redirectUrl = encodeURIComponent(pathname); - router.replace(`/${name}/auth?redirect=${redirectUrl}`); - return; - } - }} - > - - - )} - {!isPremium && ( -
{formatPrice(totalPrice)} تومان
- )} -
-
- - )} - - {/* {!isCartEmpty && ( -
- {t('CartControlsHint', { defaultValue: 'برای ویرایش تعداد، از دکمه‌های هر آیتم استفاده کنید.' })} -
- - -
-
- )} */} - - ); -}; - -export default CartSummary; - diff --git a/src/app/[name]/(Dialogs)/cart/page.tsx b/src/app/[name]/(Dialogs)/cart/page.tsx deleted file mode 100644 index 28f6af6..0000000 --- a/src/app/[name]/(Dialogs)/cart/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; - -import dynamic from 'next/dynamic'; - -const CartPage = dynamic(() => import('./CartPage'), { - ssr: false, - loading: () => ( -
- -

در حال دریافت سبد خرید...

-
- ), -}); - -export default function Page() { - return ; -} diff --git a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/CouponSection.tsx b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/CouponSection.tsx index d89ac9d..a46c235 100644 --- a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/CouponSection.tsx +++ b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/CouponSection.tsx @@ -9,7 +9,7 @@ import Button from '@/components/button/PrimaryButton'; import { extractErrorMessage } from '@/lib/func'; import { toast } from '@/components/Toast'; import { useEffect, useState } from 'react'; -import { useGetCartItems } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData'; +import { useGetCartItems } from '@/app/[name]/(Main)/cart/hooks/useCartData'; type CouponSectionProps = { couponType: string; diff --git a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx index f6c0789..ecd477b 100644 --- a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx +++ b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx @@ -7,7 +7,7 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { useGetPaymentMethod } from '../../hooks/useOrderData'; import { useCheckoutStore } from '../../store/Store'; import { useGetUserWallet } from '@/app/[name]/(Main)/transactions/hooks/useTransactionData'; -import { useGetCartItems } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData'; +import { useGetCartItems } from '@/app/[name]/(Main)/cart/hooks/useCartData'; import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; type PaymentSectionProps = { diff --git a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/SummarySection.tsx b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/SummarySection.tsx index cec63d0..aa15b22 100644 --- a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/SummarySection.tsx +++ b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/SummarySection.tsx @@ -9,12 +9,12 @@ import { toast } from '@/components/Toast'; import { useCreateOrder } from '../../hooks/useOrderData'; import { extractErrorMessage } from '@/lib/func'; import { useParams } from 'next/navigation'; -import { useGetCartItems, useSaveAllMethod } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData'; +import { useGetCartItems, useSaveAllMethod } from '@/app/[name]/(Main)/cart/hooks/useCartData'; import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; import { useCallback, useMemo } from 'react'; import { useGetShipmentMethod } from '../../hooks/useOrderData'; -import CartItemsList from '@/app/[name]/(Dialogs)/cart/components/CartItemsList'; -import { useCartStore } from '@/app/[name]/(Dialogs)/cart/store/Store'; +import CartItemsList from '@/app/[name]/(Main)/cart/components/CartItemsList'; +import { useCartStore } from '@/app/[name]/(Main)/cart/store/Store'; type SummarySectionProps = { cartModal: boolean; diff --git a/src/app/[name]/(Dialogs)/order/checkout/[id]/page.tsx b/src/app/[name]/(Dialogs)/order/checkout/[id]/page.tsx index d8f949d..3968b44 100644 --- a/src/app/[name]/(Dialogs)/order/checkout/[id]/page.tsx +++ b/src/app/[name]/(Dialogs)/order/checkout/[id]/page.tsx @@ -11,7 +11,7 @@ import { ShippingSection } from './components/ShippingSection'; import { SummarySection } from './components/SummarySection'; import { TableSection } from './components/TableSection'; import { useGetShipmentMethod } from '../hooks/useOrderData'; -import { useGetCartItems } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData'; +import { useGetCartItems } from '@/app/[name]/(Main)/cart/hooks/useCartData'; import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; import { useCheckoutStore } from '../store/Store'; diff --git a/src/app/[name]/(Main)/[id]/page.tsx b/src/app/[name]/(Main)/[id]/page.tsx index c44007b..85e6477 100644 --- a/src/app/[name]/(Main)/[id]/page.tsx +++ b/src/app/[name]/(Main)/[id]/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCart } from "@/app/[name]/(Dialogs)/cart/hook/useCart"; +import { useCart } from "@/app/[name]/(Main)/cart/hook/useCart"; import MinusIcon from "@/components/icons/MinusIcon"; import PlusIcon from "@/components/icons/PlusIcon"; import { toast } from "@/components/Toast"; diff --git a/src/app/[name]/(Main)/about/hooks/useAboutData.ts b/src/app/[name]/(Main)/about/hooks/useAboutData.ts index fc5edfe..dbc577d 100644 --- a/src/app/[name]/(Main)/about/hooks/useAboutData.ts +++ b/src/app/[name]/(Main)/about/hooks/useAboutData.ts @@ -9,6 +9,8 @@ export const useGetAbout = () => { queryFn: () => api.getAbout(name), enabled: !!name, retry: false, + staleTime: 5 * 60_000, + refetchOnMount: false, }); }; diff --git a/src/app/[name]/(Dialogs)/cart/CartPage.tsx b/src/app/[name]/(Main)/cart/CartPage.tsx similarity index 78% rename from src/app/[name]/(Dialogs)/cart/CartPage.tsx rename to src/app/[name]/(Main)/cart/CartPage.tsx index 1b20029..7c86f02 100644 --- a/src/app/[name]/(Dialogs)/cart/CartPage.tsx +++ b/src/app/[name]/(Main)/cart/CartPage.tsx @@ -11,35 +11,54 @@ import Prompt from '@/components/utils/Prompt'; import { useGetFoods } from '@/app/[name]/(Main)/hooks/useMenuData'; import MenuItem from '@/components/listview/MenuItem'; import MenuItemRenderer from '@/components/listview/MenuItemRenderer'; -import type { Food } from '@/app/[name]/(Main)/types/Types'; -import { useGetAbout } from '../../(Main)/about/hooks/useAboutData'; +import { useGetAbout } from '../about/hooks/useAboutData'; +import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; +import { useGetCartItems } from './hooks/useCartData'; import PagerModal from '@/components/pager/PagerModal'; import Button from '@/components/button/PrimaryButton'; import NotificationBellIcon from '@/components/icons/NotificationBellIcon'; +import CartSkeleton from './components/CartSkeleton'; +import { + cartItemToFood, + 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 { data: foodsResponse, isFetching } = useGetFoods(); - const { data: aboutData } = useGetAbout(); + const isPremium = aboutData?.data?.plan === 'premium'; - const foods = React.useMemo(() => foodsResponse?.data ?? [], [foodsResponse?.data]); - const isLoading = isFetching && !foods.length; const cartFoods = React.useMemo(() => { - if (!foods.length) return []; - return Object.entries(items) - .filter(([, detail]) => detail?.quantity && detail.quantity > 0) - .map(([id]) => - foods.find((foodItem) => String(foodItem.id) === String(id)) - ) - .filter((food): food is Food => Boolean(food)); - }, [foods, items]); + if (isSuccess) { + const apiItems = + cartData?.data?.items?.filter((item) => item.quantity > 0) ?? []; + return apiItems.map(cartItemToFood); + } + return guestCartItemsToFoods(items, foodsResponse?.data ?? []); + }, [isSuccess, cartData?.data?.items, items, foodsResponse?.data]); - const isCartEmpty = cartFoods.length === 0; + 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(); @@ -55,7 +74,7 @@ const CartPage = () => { }; return ( -
+
{isCartEmpty ? ( @@ -77,11 +96,8 @@ const CartPage = () => {
- {isLoading ? ( -
- -

در حال دریافت سبد خرید...

-
+ {showInitialCartLoad || guestAwaitingMenu ? ( + ) : isCartEmpty ? (
{ ))} - +
)}
diff --git a/src/app/[name]/(Dialogs)/cart/components/CartItemsList.tsx b/src/app/[name]/(Main)/cart/components/CartItemsList.tsx similarity index 100% rename from src/app/[name]/(Dialogs)/cart/components/CartItemsList.tsx rename to src/app/[name]/(Main)/cart/components/CartItemsList.tsx diff --git a/src/app/[name]/(Dialogs)/cart/components/CartSkeleton.tsx b/src/app/[name]/(Main)/cart/components/CartSkeleton.tsx similarity index 100% rename from src/app/[name]/(Dialogs)/cart/components/CartSkeleton.tsx rename to src/app/[name]/(Main)/cart/components/CartSkeleton.tsx diff --git a/src/app/[name]/(Main)/cart/components/CartSummary.tsx b/src/app/[name]/(Main)/cart/components/CartSummary.tsx new file mode 100644 index 0000000..c8ffa32 --- /dev/null +++ b/src/app/[name]/(Main)/cart/components/CartSummary.tsx @@ -0,0 +1,115 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { useParams, useRouter, usePathname } from 'next/navigation'; +import Button from '@/components/button/PrimaryButton'; +import { useGetFoods } from '@/app/[name]/(Main)/hooks/useMenuData'; +import { useCart } from '../hook/useCart'; +import { useTranslation } from 'react-i18next'; +import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; +import { useGetCartItems } from '../hooks/useCartData'; +import { useCartStore } from '../store/Store'; +import { guestCartItemsToFoods } from '../lib/cartUtils'; + +interface CartSummaryProps { + isPremium: boolean; + hasItems: boolean; +} + +const CartSummary = ({ isPremium, hasItems }: CartSummaryProps) => { + const params = useParams(); + const router = useRouter(); + const pathname = usePathname(); + const name = params.name as string; + const { isSuccess } = useGetProfile(); + const { data: foodsResponse } = useGetFoods(); + const { items } = useCart(); + const { data: cartData } = useGetCartItems(isSuccess); + const { t } = useTranslation('parallels', { keyPrefix: 'Cart' }); + const { description, setDescription } = useCartStore(); + + const totalPrice = React.useMemo(() => { + if (isSuccess && cartData?.data?.total !== undefined) { + return cartData.data.total; + } + + const foods = foodsResponse?.data ?? []; + const cartFoods = guestCartItemsToFoods(items, foods); + return cartFoods.reduce((sum, food) => { + const qty = items[String(food.id)]?.quantity ?? 0; + const basePrice = food.price ?? 0; + const discount = food.discount ?? 0; + const priceAfterDiscount = basePrice * (1 - discount / 100); + return sum + priceAfterDiscount * qty; + }, 0); + }, [isSuccess, cartData?.data?.total, foodsResponse?.data, items]); + + const formatPrice = React.useCallback( + (value: number) => value.toLocaleString('fa-IR'), + [] + ); + + if (!hasItems) { + return null; + } + + return ( + <> + {isPremium && ( +
+
+

{t('InputDescription.Label')}

+ + +
+
+ )} + +
+
+
+
{t('PayableAmountLabel')}
+ {isPremium && ( +
+ {formatPrice(totalPrice)} تومان +
+ )} +
+ + {isPremium && ( + { + if (!isSuccess) { + event.preventDefault(); + const redirectUrl = encodeURIComponent(pathname); + router.replace(`/${name}/auth?redirect=${redirectUrl}`); + return; + } + }} + > + + + )} + {!isPremium && ( +
+ {formatPrice(totalPrice)} تومان +
+ )} +
+
+ + ); +}; + +export default CartSummary; diff --git a/src/app/[name]/(Dialogs)/cart/hook/useCart.ts b/src/app/[name]/(Main)/cart/hook/useCart.ts similarity index 100% rename from src/app/[name]/(Dialogs)/cart/hook/useCart.ts rename to src/app/[name]/(Main)/cart/hook/useCart.ts diff --git a/src/app/[name]/(Dialogs)/cart/hooks/useCartData.ts b/src/app/[name]/(Main)/cart/hooks/useCartData.ts similarity index 99% rename from src/app/[name]/(Dialogs)/cart/hooks/useCartData.ts rename to src/app/[name]/(Main)/cart/hooks/useCartData.ts index 9216caa..35dc7ff 100644 --- a/src/app/[name]/(Dialogs)/cart/hooks/useCartData.ts +++ b/src/app/[name]/(Main)/cart/hooks/useCartData.ts @@ -184,6 +184,7 @@ export const useGetCartItems = (enabled = true) => { queryKey: ["cart-items"], queryFn: api.getCartItems, enabled, + staleTime: 60_000, refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, diff --git a/src/app/[name]/(Main)/cart/lib/cartUtils.ts b/src/app/[name]/(Main)/cart/lib/cartUtils.ts new file mode 100644 index 0000000..0ed5a98 --- /dev/null +++ b/src/app/[name]/(Main)/cart/lib/cartUtils.ts @@ -0,0 +1,36 @@ +import type { CartItem } from '../types/Types'; +import type { Food } from '@/app/[name]/(Main)/types/Types'; + +export function cartItemToFood(item: CartItem): Food { + return { + id: item.foodId, + category: '', + title: item.foodTitle, + desc: '', + content: [], + price: item.price, + prepareTime: 0, + isActive: true, + images: [], + inPlaceServe: true, + pickupServe: true, + discount: item.discount, + isSpecialOffer: false, + }; +} + +export function guestCartItemsToFoods( + items: Record, + foods: Food[] +): Food[] { + return Object.entries(items) + .filter(([, detail]) => detail?.quantity && detail.quantity > 0) + .map(([id]) => foods.find((food) => String(food.id) === String(id))) + .filter((food): food is Food => Boolean(food)); +} + +export function hasCartEntries( + items: Record +): boolean { + return Object.values(items).some((detail) => detail?.quantity && detail.quantity > 0); +} diff --git a/src/app/[name]/(Main)/cart/page.tsx b/src/app/[name]/(Main)/cart/page.tsx new file mode 100644 index 0000000..107b040 --- /dev/null +++ b/src/app/[name]/(Main)/cart/page.tsx @@ -0,0 +1,5 @@ +'use client'; + +import CartPage from './CartPage'; + +export default CartPage; diff --git a/src/app/[name]/(Dialogs)/cart/service/CartService.ts b/src/app/[name]/(Main)/cart/service/CartService.ts similarity index 100% rename from src/app/[name]/(Dialogs)/cart/service/CartService.ts rename to src/app/[name]/(Main)/cart/service/CartService.ts diff --git a/src/app/[name]/(Dialogs)/cart/store/Store.ts b/src/app/[name]/(Main)/cart/store/Store.ts similarity index 100% rename from src/app/[name]/(Dialogs)/cart/store/Store.ts rename to src/app/[name]/(Main)/cart/store/Store.ts diff --git a/src/app/[name]/(Dialogs)/cart/types/Types.ts b/src/app/[name]/(Main)/cart/types/Types.ts similarity index 100% rename from src/app/[name]/(Dialogs)/cart/types/Types.ts rename to src/app/[name]/(Main)/cart/types/Types.ts diff --git a/src/app/[name]/(Main)/hooks/useMenuData.ts b/src/app/[name]/(Main)/hooks/useMenuData.ts index 2010c78..727281f 100644 --- a/src/app/[name]/(Main)/hooks/useMenuData.ts +++ b/src/app/[name]/(Main)/hooks/useMenuData.ts @@ -8,6 +8,8 @@ export const useGetFoods = () => { queryKey: ["menu"], queryFn: () => api.getFoods(name), enabled: !!name, + staleTime: 5 * 60_000, + refetchOnMount: false, }); }; diff --git a/src/app/[name]/lib/getRestaurant.ts b/src/app/[name]/lib/getRestaurant.ts index 1386a77..c5691a2 100644 --- a/src/app/[name]/lib/getRestaurant.ts +++ b/src/app/[name]/lib/getRestaurant.ts @@ -1,20 +1,17 @@ +import { cache } from "react"; import { API_BASE_URL } from "@/config/const"; import { AboutResponse, Restaurant } from "../(Main)/about/types/Types"; import axios from "axios"; -export async function getRestaurant(slug: string): Promise { +async function fetchRestaurant(slug: string): Promise { try { const response = await axios(`${API_BASE_URL}/public/restaurants/${slug}`, { - // cache: "no-store", - headers: { "Content-Type": "application/json", "X-SLUG": slug, }, }); - console.log("response", response); - if (!response.data) { if (response.status === 404) { throw new Error("RESTAURANT_NOT_FOUND"); @@ -30,11 +27,11 @@ export async function getRestaurant(slug: string): Promise { return data.data; } catch (error) { - console.log("error", error); - if (error instanceof Error && error.message === "RESTAURANT_NOT_FOUND") { throw error; } throw new Error(`Failed to fetch restaurant data: ${error}`); } } + +export const getRestaurant = cache(fetchRestaurant); diff --git a/src/components/CartChecker.tsx b/src/components/CartChecker.tsx index 514229a..6f26783 100644 --- a/src/components/CartChecker.tsx +++ b/src/components/CartChecker.tsx @@ -1,6 +1,6 @@ "use client" -import { useCart } from '@/app/[name]/(Dialogs)/cart/hook/useCart' +import { useCart } from '@/app/[name]/(Main)/cart/hook/useCart' import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData' import { useParams } from 'next/navigation' import { useEffect, useRef, type FC } from 'react' diff --git a/src/components/listview/MenuItem.tsx b/src/components/listview/MenuItem.tsx index 0322c01..444bc50 100644 --- a/src/components/listview/MenuItem.tsx +++ b/src/components/listview/MenuItem.tsx @@ -1,7 +1,7 @@ /* eslint-disable @next/next/no-img-element */ "use client"; -import { useCart } from "@/app/[name]/(Dialogs)/cart/hook/useCart"; +import { useCart } from "@/app/[name]/(Main)/cart/hook/useCart"; import type { Food, FoodImage } from "@/app/[name]/(Main)/types/Types"; import MinusIcon from "@/components/icons/MinusIcon"; import PlusIcon from "@/components/icons/PlusIcon"; diff --git a/src/components/navigation/BottomNavBar.tsx b/src/components/navigation/BottomNavBar.tsx index 5123d04..0183765 100644 --- a/src/components/navigation/BottomNavBar.tsx +++ b/src/components/navigation/BottomNavBar.tsx @@ -10,7 +10,7 @@ import HeartIcon from '../icons/HeartIcon' import { useParams, usePathname, useRouter } from 'next/navigation' import HomeIcon from '../icons/HomeIcon' import { useTranslation } from 'react-i18next'; -import { useCart } from '@/app/[name]/(Dialogs)/cart/hook/useCart'; +import { useCart } from '@/app/[name]/(Main)/cart/hook/useCart'; import { Building } from 'iconsax-react'; import clsx from 'clsx'; import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; diff --git a/src/components/navigation/BottomNavLink.tsx b/src/components/navigation/BottomNavLink.tsx index 18e7cc2..706cc90 100644 --- a/src/components/navigation/BottomNavLink.tsx +++ b/src/components/navigation/BottomNavLink.tsx @@ -11,12 +11,13 @@ type Props = { value: string } & LinkProps & React.AnchorHTMLAttributes -function BottomNavLink({ icon, value, href, ...restProps }: Props) { +function BottomNavLink({ icon, value, href, prefetch, ...restProps }: Props) { const pathname = usePathname(); const isActive = pathname === href; + const shouldPrefetch = prefetch ?? true; return ( - diff --git a/src/features/auth/components/StepOtp.tsx b/src/features/auth/components/StepOtp.tsx index fd31edf..dd63863 100644 --- a/src/features/auth/components/StepOtp.tsx +++ b/src/features/auth/components/StepOtp.tsx @@ -9,7 +9,7 @@ import { toast } from '@/components/Toast' import Button from '@/components/button/PrimaryButton' import { extractErrorMessage } from '@/lib/func' import { useReceiptStore } from '@/zustand/receiptStore' -import { useBulkCart } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData' +import { useBulkCart } from '@/app/[name]/(Main)/cart/hooks/useCartData' import { setRefreshToken, setToken } from '@/lib/api/func' import { useSearchParams } from 'next/navigation'