show variant in carts
This commit is contained in:
@@ -8,20 +8,39 @@ import {
|
|||||||
useGetCartItems,
|
useGetCartItems,
|
||||||
useIncrementCart,
|
useIncrementCart,
|
||||||
} from "../hooks/useCartData";
|
} from "../hooks/useCartData";
|
||||||
|
import { toast } from "@/components/Toast";
|
||||||
|
import { extractErrorMessage } from "@/lib/func";
|
||||||
|
|
||||||
export const useCart = () => {
|
export const useCart = () => {
|
||||||
const { isSuccess } = useGetProfile();
|
const { isSuccess } = useGetProfile();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const currentSlug = (params.name as string) || null;
|
const currentSlug = (params.name as string) || null;
|
||||||
const { clear, increment, decrement, items, slug, setSlug } = useReceiptStore();
|
const {
|
||||||
const { mutate: mutateIncrementCart, isPending: isIncrementPending } = useIncrementCart();
|
clear,
|
||||||
const { mutate: mutateDecrementCart, isPending: isDecrementPending } = useDecrementCart();
|
increment,
|
||||||
|
decrement,
|
||||||
|
items,
|
||||||
|
slug,
|
||||||
|
setSlug,
|
||||||
|
} = useReceiptStore();
|
||||||
|
const {
|
||||||
|
mutate: mutateIncrementCart,
|
||||||
|
isPending: isIncrementPending,
|
||||||
|
} = useIncrementCart();
|
||||||
|
const {
|
||||||
|
mutate: mutateDecrementCart,
|
||||||
|
isPending: isDecrementPending,
|
||||||
|
} = useDecrementCart();
|
||||||
const { mutate: mutateClearCart } = useClearCart();
|
const { mutate: mutateClearCart } = useClearCart();
|
||||||
const { data: cartItems } = useGetCartItems(isSuccess);
|
const { data: cartItems } = useGetCartItems(isSuccess);
|
||||||
|
|
||||||
const addToCart = (id: string | number) => {
|
const addToCart = (id: string | number) => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
mutateIncrementCart(id);
|
mutateIncrementCart(id, {
|
||||||
|
onError: (error) => {
|
||||||
|
toast(extractErrorMessage(error), "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// تنظیم slug هنگام افزودن آیتم به سبد (فقط برای کاربران لاگین نشده)
|
// تنظیم slug هنگام افزودن آیتم به سبد (فقط برای کاربران لاگین نشده)
|
||||||
if (currentSlug && slug !== currentSlug) {
|
if (currentSlug && slug !== currentSlug) {
|
||||||
@@ -33,7 +52,11 @@ export const useCart = () => {
|
|||||||
|
|
||||||
const removeFromCart = (id: string | number) => {
|
const removeFromCart = (id: string | number) => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
mutateDecrementCart(id);
|
mutateDecrementCart(id, {
|
||||||
|
onError: (error) => {
|
||||||
|
toast(extractErrorMessage(error), "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
decrement(id);
|
decrement(id);
|
||||||
}
|
}
|
||||||
@@ -41,7 +64,11 @@ export const useCart = () => {
|
|||||||
|
|
||||||
const clearCart = useCallback(() => {
|
const clearCart = useCallback(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
mutateClearCart();
|
mutateClearCart(undefined, {
|
||||||
|
onError: (error) => {
|
||||||
|
toast(extractErrorMessage(error), "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
@@ -53,9 +80,13 @@ export const useCart = () => {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return cartItems.data.items.reduce((acc, item) => {
|
return cartItems.data.items.reduce((acc, item) => {
|
||||||
acc[item.variantId] = { quantity: item.quantity };
|
acc[item.variantId] = {
|
||||||
|
quantity: item.quantity,
|
||||||
|
...(item.variantValue != null && { variantValue: item.variantValue }),
|
||||||
|
...(item.image != null && { image: item.image }),
|
||||||
|
};
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<string | number, { quantity: number }>);
|
}, {} as Record<string | number, { quantity: number; variantValue?: string; image?: string }>);
|
||||||
} else {
|
} else {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import Prompt from '@/components/utils/Prompt';
|
|||||||
import { useGetProducts } from '@/app/[name]/(Main)/hooks/useMenuData';
|
import { useGetProducts } from '@/app/[name]/(Main)/hooks/useMenuData';
|
||||||
import MenuItem from '@/components/listview/MenuItem';
|
import MenuItem from '@/components/listview/MenuItem';
|
||||||
import MenuItemRenderer from '@/components/listview/MenuItemRenderer';
|
import MenuItemRenderer from '@/components/listview/MenuItemRenderer';
|
||||||
import type { Product } from '@/app/[name]/(Main)/types/Types';
|
|
||||||
|
|
||||||
const CartIndex = () => {
|
const CartIndex = () => {
|
||||||
const { t } = useTranslation('parallels', { keyPrefix: 'Cart' });
|
const { t } = useTranslation('parallels', { keyPrefix: 'Cart' });
|
||||||
@@ -26,13 +25,14 @@ const CartIndex = () => {
|
|||||||
if (!products.length) return [];
|
if (!products.length) return [];
|
||||||
return Object.entries(items)
|
return Object.entries(items)
|
||||||
.filter(([, detail]) => detail?.quantity && detail.quantity > 0)
|
.filter(([, detail]) => detail?.quantity && detail.quantity > 0)
|
||||||
.map(([variantId]) => {
|
.map(([variantId, detail]) => {
|
||||||
const product = products.find((p) =>
|
const product = products.find((p) =>
|
||||||
p.variants?.some((v) => v.id === variantId)
|
p.variants?.some((v) => v.id === variantId)
|
||||||
);
|
);
|
||||||
return product ? { product, variantId } : null;
|
const variantValue = (detail as { variantValue?: string } | undefined)?.variantValue;
|
||||||
|
return product ? { product, variantId, variantValue } : null;
|
||||||
})
|
})
|
||||||
.filter((x): x is { product: Product; variantId: string } => Boolean(x));
|
.filter((x): x is NonNullable<typeof x> => x != null);
|
||||||
}, [products, items]);
|
}, [products, items]);
|
||||||
|
|
||||||
const isCartEmpty = cartProducts.length === 0;
|
const isCartEmpty = cartProducts.length === 0;
|
||||||
@@ -98,9 +98,9 @@ const CartIndex = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col gap-4 pb-24">
|
<div className="flex flex-col gap-4 pb-24">
|
||||||
{cartProducts.map(({ product, variantId }) => (
|
{cartProducts.map(({ product, variantId, variantValue }) => (
|
||||||
<MenuItemRenderer key={variantId}>
|
<MenuItemRenderer key={variantId}>
|
||||||
<MenuItem product={product} variantId={variantId} />
|
<MenuItem product={product} variantId={variantId} variantValue={variantValue} />
|
||||||
</MenuItemRenderer>
|
</MenuItemRenderer>
|
||||||
))}
|
))}
|
||||||
<CartSummary isPremium />
|
<CartSummary isPremium />
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ export type BulkCartItem = {
|
|||||||
export interface CartItem {
|
export interface CartItem {
|
||||||
variantId: string;
|
variantId: string;
|
||||||
productTitle: string;
|
productTitle: string;
|
||||||
|
variantValue?: string;
|
||||||
|
image?: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
price: number;
|
price: number;
|
||||||
discount: number;
|
discount: number;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function CartQuantityControl({
|
|||||||
isMutating = false,
|
isMutating = false,
|
||||||
addDisabled = false,
|
addDisabled = false,
|
||||||
addLabel = 'افزودن',
|
addLabel = 'افزودن',
|
||||||
addingLabel = 'در حال افزودن...',
|
addingLabel = '',
|
||||||
fullWidth = false,
|
fullWidth = false,
|
||||||
}: CartQuantityControlProps) {
|
}: CartQuantityControlProps) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ interface MenuItemProps {
|
|||||||
product: Product;
|
product: Product;
|
||||||
/** در صفحه سبد هر خط با variantId مشخص میشود */
|
/** در صفحه سبد هر خط با variantId مشخص میشود */
|
||||||
variantId?: string | null;
|
variantId?: string | null;
|
||||||
|
/** مقدار تنوع (مثلاً «قرمز»، «تنوع سوم») — برای نمایش در سبد خرید */
|
||||||
|
variantValue?: string | null;
|
||||||
/** حالت نمایش: list = یک ستونه (پیشفرض)، grid = دو ستونه */
|
/** حالت نمایش: list = یک ستونه (پیشفرض)، grid = دو ستونه */
|
||||||
viewMode?: MenuItemViewMode;
|
viewMode?: MenuItemViewMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuItem = ({ product, variantId: variantIdProp, viewMode = 'list' }: MenuItemProps) => {
|
const MenuItem = ({ product, variantId: variantIdProp, variantValue: variantValueProp, viewMode = 'list' }: MenuItemProps) => {
|
||||||
const { items, addToCart, removeFromCart, isCartMutating } = useCart();
|
const { items, addToCart, removeFromCart, isCartMutating } = useCart();
|
||||||
const params = useParams<{ name: string }>();
|
const params = useParams<{ name: string }>();
|
||||||
const name = params?.name || "";
|
const name = params?.name || "";
|
||||||
@@ -61,6 +63,10 @@ const MenuItem = ({ product, variantId: variantIdProp, viewMode = 'list' }: Menu
|
|||||||
[product.name, product.title]
|
[product.name, product.title]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** فقط در سبد خرید تنوع نمایش داده شود */
|
||||||
|
const isInCart = variantIdProp != null;
|
||||||
|
const variantValueDisplay = isInCart ? (variantValueProp ?? selectedVariant?.value ?? null) : null;
|
||||||
|
|
||||||
const productContent = useMemo(() => {
|
const productContent = useMemo(() => {
|
||||||
const content = product.content;
|
const content = product.content;
|
||||||
if (!content) return '';
|
if (!content) return '';
|
||||||
@@ -126,10 +132,15 @@ const MenuItem = ({ product, variantId: variantIdProp, viewMode = 'list' }: Menu
|
|||||||
alt={productName}
|
alt={productName}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={productDetailUrl} className="cursor-pointer min-w-0 mt-4">
|
<Link href={productDetailUrl} className="cursor-pointer min-w-0 mt-4 flex items-center justify-between gap-2">
|
||||||
<div className="text-sm2 font-normal text-black dark:text-white wrap-break-word line-clamp-2">
|
<div className="text-sm2 font-normal text-black dark:text-white wrap-break-word line-clamp-2 min-w-0">
|
||||||
{productName}
|
{productName}
|
||||||
</div>
|
</div>
|
||||||
|
{variantValueDisplay && (
|
||||||
|
<span className="bg-primary text-primary-foreground text-[10px] px-1 py-0.5 rounded-md shrink-0">
|
||||||
|
{variantValueDisplay}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
<div className="flex flex-col gap-2 mt-1">
|
<div className="flex flex-col gap-2 mt-1">
|
||||||
<div className="flex flex-col gap-1 min-h-10 justify-center" dir="ltr">
|
<div className="flex flex-col gap-1 min-h-10 justify-center" dir="ltr">
|
||||||
@@ -184,9 +195,16 @@ const MenuItem = ({ product, variantId: variantIdProp, viewMode = 'list' }: Menu
|
|||||||
<div className="w-full inline-flex flex-col justify-between min-w-0">
|
<div className="w-full inline-flex flex-col justify-between min-w-0">
|
||||||
<Link href={productDetailUrl} className="cursor-pointer min-w-0">
|
<Link href={productDetailUrl} className="cursor-pointer min-w-0">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<div className="text-sm2 font-normal text-black dark:text-white wrap-break-word">
|
<div className="flex items-center justify-between gap-2 min-w-0">
|
||||||
|
<div className="text-sm2 font-normal text-black dark:text-white wrap-break-word min-w-0">
|
||||||
{productName}
|
{productName}
|
||||||
</div>
|
</div>
|
||||||
|
{variantValueDisplay && (
|
||||||
|
<span className="bg-primary text-primary-foreground text-[10px] px-1 py-0.5 rounded-md shrink-0">
|
||||||
|
{variantValueDisplay}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
{(productContent || productDescription) && (
|
{(productContent || productDescription) && (
|
||||||
<div className="text-[#7F7F7F] line-clamp-2 text-xs leading-5 font-normal mt-2 wrap-break-word overflow-hidden">
|
<div className="text-[#7F7F7F] line-clamp-2 text-xs leading-5 font-normal mt-2 wrap-break-word overflow-hidden">
|
||||||
{productContent || productDescription}
|
{productContent || productDescription}
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
// export const API_BASE_URL = "https://dmenuplus-api.dev.danakcorp.com";
|
// export const API_BASE_URL = "https://dmenuplus-api.dev.danakcorp.com";
|
||||||
export const API_BASE_URL = "https://dkala-api.danakcorp.com";
|
// export const API_BASE_URL = "https://dkala-api.danakcorp.com";
|
||||||
// export const API_BASE_URL = "http://10.191.241.88:4000";
|
export const API_BASE_URL = "http://10.191.241.88:4000";
|
||||||
export const TOKEN_NAME = "dkala-t";
|
export const TOKEN_NAME = "dkala-t";
|
||||||
export const REFRESH_TOKEN_NAME = "dkala-rt";
|
export const REFRESH_TOKEN_NAME = "dkala-rt";
|
||||||
|
|||||||
Reference in New Issue
Block a user