payble fix with discount

This commit is contained in:
hamid zarghami
2025-12-18 10:38:16 +03:30
parent 1c39e9c6b3
commit 510d1718f4
3 changed files with 71 additions and 23 deletions
@@ -9,6 +9,7 @@ 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';
interface CartSummaryProps {
description?: string;
@@ -24,6 +25,7 @@ const CartSummary = ({ description = '', onDescriptionChange }: CartSummaryProps
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 cartFoods = React.useMemo(() => {
@@ -37,11 +39,20 @@ const CartSummary = ({ description = '', onDescriptionChange }: CartSummaryProps
}, [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;
return sum + (food.price ?? 0) * qty;
const basePrice = food.price ?? 0;
const discount = food.discount ?? 0;
const priceAfterDiscount = basePrice * (1 - discount / 100);
return sum + priceAfterDiscount * qty;
}, 0);
}, [cartFoods, items]);
}, [cartFoods, items, isSuccess, cartData?.data?.total]);
const isCartEmpty = cartFoods.length === 0;
+23 -18
View File
@@ -12,7 +12,7 @@ export interface Category {
deletedAt: string | null;
title: string;
isActive: boolean;
restId: string;
restaurant: string;
avatarUrl: string | null;
}
@@ -22,23 +22,33 @@ export type FoodImage = string | { url: string; alt?: string | null };
export interface Food {
id: string;
createdAt?: string;
updatedAt?: string;
deletedAt?: string | null;
restaurant?: string;
category?: Category;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
restaurant: string;
category: Category;
inventory: string;
title: string;
desc: string;
content: string[];
price: number;
order: number | null;
prepareTime: number | null;
weekDays: number[];
mealTypes: unknown[];
isActive: boolean;
images: string[];
inPlaceServe: boolean;
pickupServe: boolean;
score: number;
discount: number;
isSpecialOffer: boolean;
// فیلدهای قدیمی برای سازگاری با سایر بخش‌های کد
name?: string;
title?: string;
foodName?: string;
description?: string;
desc?: string | null;
content?: string[] | string | null;
price: number;
image?: string | null;
images?: FoodImage[] | null;
points?: number | null;
order?: number | null;
prepareTime?: number | null;
sat?: boolean;
sun?: boolean;
mon?: boolean;
@@ -47,12 +57,7 @@ export interface Food {
dinner?: boolean;
stock?: number;
stockDefault?: number;
isActive?: boolean;
inPlaceServe?: boolean;
pickupServe?: boolean;
rate?: number;
discount?: number;
isSpecialOffer?: boolean;
[key: string]: unknown;
}
+35 -3
View File
@@ -64,11 +64,30 @@ const MenuItem = ({ food }: MenuItemProps) => {
return desc.replace(/,/g, '،');
}, [food.description, food.desc]);
const finalPrice = useMemo(() => {
const basePrice = food.price || 0;
const discount = food.discount || 0;
if (discount > 0) {
return Math.max(0, basePrice - discount);
}
return basePrice;
}, [food.price, food.discount]);
const formattedPrice = useMemo(
() => (finalPrice ? finalPrice.toLocaleString('fa-IR') : '0'),
[finalPrice]
);
const formattedOriginalPrice = useMemo(
() => (food.price ? food.price.toLocaleString('fa-IR') : '0'),
[food.price]
);
const hasDiscount = useMemo(
() => (food.discount || 0) > 0,
[food.discount]
);
const handleAddToCart = () => {
addToCart(food.id);
};
@@ -104,9 +123,22 @@ const MenuItem = ({ food }: MenuItemProps) => {
</div>
</Link>
<div className="inline-flex mt-2 gap-2 justify-between w-full items-center">
<span className="w-full text-sm mt-1" dir="ltr">
{formattedPrice} T
</span>
<div className="w-full flex flex-col gap-1" dir="ltr">
{hasDiscount ? (
<>
<span className="text-xs text-disabled-text line-through">
{formattedOriginalPrice} T
</span>
<span className="text-sm font-medium text-primary dark:text-foreground">
{formattedPrice} T
</span>
</>
) : (
<span className="text-sm mt-1">
{formattedPrice} T
</span>
)}
</div>
<motion.div
whileTap={{ scale: 1.05 }}
className="bg-background active:drop-shadow-xs max-w-[115px] rounded-md w-full h-8 inline-flex p-1 justify-between items-center gap-2 relative overflow-hidden"