fix problem update price in cart

This commit is contained in:
hamid zarghami
2025-12-25 10:46:04 +03:30
parent 91b5a61fbd
commit 0f2f0d5c29
3 changed files with 109 additions and 81 deletions
@@ -1,13 +1,14 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import * as api from "../service/CartService";
import type { CartResponse, CartItem } from "../types/Types";
import type { FoodsResponse } from "@/app/[name]/(Main)/types/Types";
export const useBulkCart = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: api.bulkCart,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["cart-items"] });
queryClient.refetchQueries({ queryKey: ["cart-items"] });
},
});
};
@@ -18,56 +19,74 @@ export const useIncrementCart = () => {
mutationFn: api.increment,
onMutate: async (id: string | number) => {
await queryClient.cancelQueries({ queryKey: ["cart-items"] });
await queryClient.cancelQueries({ queryKey: ["menu"] });
const previousCart = queryClient.getQueryData<CartResponse>([
"cart-items",
]);
const foodsData = queryClient.getQueryData<FoodsResponse>(["menu"]);
if (previousCart?.data) {
if (previousCart?.data && foodsData?.data) {
const existingItem = previousCart.data.items.find(
(item) => item.foodId === String(id)
);
let updatedItems: CartItem[];
let newTotalItems: number;
if (existingItem) {
// به‌روزرسانی خوش‌بینانه برای آیتم موجود
const updatedItems = previousCart.data.items.map((item) => {
updatedItems = previousCart.data.items.map((item) => {
if (item.foodId === String(id)) {
return {
...item,
quantity: item.quantity + 1,
totalPrice: item.price * (item.quantity + 1) * (1 - item.discount / 100),
};
}
return item;
});
queryClient.setQueryData<CartResponse>(["cart-items"], {
...previousCart,
data: {
...previousCart.data,
items: updatedItems,
totalItems: previousCart.data.totalItems + 1,
},
});
newTotalItems = previousCart.data.totalItems + 1;
} else {
// افزودن خوش‌بینانه برای آیتم جدید
const newItem: CartItem = {
foodId: String(id),
foodTitle: "", // این بعداً از سرور پر می‌شود
quantity: 1,
price: 0,
discount: 0,
totalPrice: 0,
};
queryClient.setQueryData<CartResponse>(["cart-items"], {
...previousCart,
data: {
...previousCart.data,
items: [...previousCart.data.items, newItem],
totalItems: previousCart.data.totalItems + 1,
},
});
const food = foodsData.data.find((f) => String(f.id) === String(id));
if (food) {
const newItem: CartItem = {
foodId: String(id),
foodTitle: food.title || food.name || "",
quantity: 1,
price: food.price,
discount: food.discount || 0,
totalPrice: food.price * (1 - (food.discount || 0) / 100),
};
updatedItems = [...previousCart.data.items, newItem];
newTotalItems = previousCart.data.totalItems + 1;
} else {
return { previousCart };
}
}
// محاسبه subTotal جدید
const newSubTotal = updatedItems.reduce(
(sum, item) => sum + item.totalPrice,
0
);
// محاسبه total جدید (با حفظ deliveryFee، tax و discount)
const newTotal =
newSubTotal +
(previousCart.data.deliveryFee || 0) -
(previousCart.data.totalDiscount || 0) +
(previousCart.data.tax || 0);
queryClient.setQueryData<CartResponse>(["cart-items"], {
...previousCart,
data: {
...previousCart.data,
items: updatedItems,
totalItems: newTotalItems,
subTotal: newSubTotal,
total: newTotal,
},
});
}
return { previousCart };
@@ -77,6 +96,9 @@ export const useIncrementCart = () => {
queryClient.setQueryData(["cart-items"], context.previousCart);
}
},
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["cart-items"] });
},
});
};
@@ -102,18 +124,34 @@ export const useDecrementCart = () => {
return {
...item,
quantity: newQuantity,
totalPrice: item.price * newQuantity * (1 - item.discount / 100),
};
}
return item;
})
.filter((item: CartItem | null): item is CartItem => item !== null);
// محاسبه subTotal جدید
const newSubTotal = updatedItems.reduce(
(sum, item) => sum + item.totalPrice,
0
);
// محاسبه total جدید
const newTotal =
newSubTotal +
(previousCart.data.deliveryFee || 0) -
(previousCart.data.totalDiscount || 0) +
(previousCart.data.tax || 0);
queryClient.setQueryData<CartResponse>(["cart-items"], {
...previousCart,
data: {
...previousCart.data,
items: updatedItems,
totalItems: Math.max(0, previousCart.data.totalItems - 1),
subTotal: newSubTotal,
total: newTotal,
},
});
}
@@ -125,6 +163,9 @@ export const useDecrementCart = () => {
queryClient.setQueryData(["cart-items"], context.previousCart);
}
},
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["cart-items"] });
},
});
};
@@ -132,32 +173,8 @@ export const useClearCart = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: api.clear,
onMutate: async () => {
await queryClient.cancelQueries({ queryKey: ["cart-items"] });
const previousCart = queryClient.getQueryData<CartResponse>([
"cart-items",
]);
if (previousCart?.data) {
queryClient.setQueryData<CartResponse>(["cart-items"], {
...previousCart,
data: {
...previousCart.data,
items: [],
totalItems: 0,
subTotal: 0,
total: 0,
},
});
}
return { previousCart };
},
onError: (_err, _variables, context) => {
if (context?.previousCart) {
queryClient.setQueryData(["cart-items"], context.previousCart);
}
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["cart-items"] });
},
});
};
@@ -29,28 +29,28 @@ const getDeliveryMethodTitle = (method: string) => {
}
};
const getStatusPercentage = (status: string) => {
switch (status) {
case 'new':
case 'pendingPayment':
return 0;
case 'paid':
case 'confirmed':
return 20;
case 'preparing':
return 40;
case 'ready':
return 60;
case 'shipped':
case 'delivering':
return 80;
case 'completed':
case 'delivered':
return 100;
default:
return 0;
}
};
// const getStatusPercentage = (status: string) => {
// switch (status) {
// case 'new':
// case 'pendingPayment':
// return 0;
// case 'paid':
// case 'confirmed':
// return 20;
// case 'preparing':
// return 40;
// case 'ready':
// return 60;
// case 'shipped':
// case 'delivering':
// return 80;
// case 'completed':
// case 'delivered':
// return 100;
// default:
// return 0;
// }
// };
const getStatusText = (status: string): string => {
const statusKey = status as keyof typeof ordersTranslations.status;
@@ -1,8 +1,9 @@
'use client';
import { useSearchParams } from 'next/navigation';
import { useSearchParams, useRouter } from 'next/navigation';
import React, { useState, useEffect } from 'react';
import dynamic from 'next/dynamic';
import { ArrowLeft } from 'iconsax-react';
import useToggle from '@/hooks/helpers/useToggle';
import { useAuthStore } from '@/zustand/authStore';
import { MarkerData, NominatimReverseGeocodingResponse } from '../types/Types';
@@ -20,6 +21,7 @@ const CustomMap = dynamic(
function OrderTrackingPage() {
const router = useRouter();
const params = useSearchParams();
const id = params.get('id');
const editMode = !!id;
@@ -186,8 +188,17 @@ function OrderTrackingPage() {
/>
</div>
<div className="absolute top-4 right-4 z-1000">
<button
onClick={() => router.back()}
className="p-2 rounded-full bg-container/90 backdrop-blur-sm shadow-sm"
>
<ArrowLeft size={24} className="stroke-foreground" />
</button>
</div>
{hasServiceArea && (
<div className="absolute top-4 left-4 right-4 z-1000 max-w-sm">
<div className="absolute top-4 left-4 z-1000 max-w-sm">
<div className="bg-blue-50/90 border border-blue-200 rounded-lg p-3 shadow-sm">
<p className="text-xs text-blue-800">
محدوده سرویسدهی روی نقشه با رنگ آبی مشخص شده است