نسخ من RaghadAlkhous/RestaurantDash
Initial commit - restaurant dashboard
هذا الالتزام موجود في:
140
src/services/cartHelpers.js
Normal file
140
src/services/cartHelpers.js
Normal file
@@ -0,0 +1,140 @@
|
||||
|
||||
import authService from './authService';
|
||||
|
||||
// === مفاتيح التخزين ===
|
||||
const CART_KEY = 'activeCartId';
|
||||
|
||||
// === LocalStorage Helpers ===
|
||||
export const setActiveCartId = (id) => {
|
||||
try { localStorage.setItem(CART_KEY, String(id)); } catch {}
|
||||
};
|
||||
export const getActiveCartId = () => {
|
||||
try { return localStorage.getItem(CART_KEY); } catch { return null; }
|
||||
};
|
||||
export const clearActiveCartId = () => {
|
||||
try { localStorage.removeItem(CART_KEY); } catch {}
|
||||
};
|
||||
|
||||
// === تحويل عناصر الكارت لصيغة JSON:API ===
|
||||
export const buildCartPayload = (items, totalPrice) => ({
|
||||
data: {
|
||||
type: "cart",
|
||||
attributes: {
|
||||
totalPrice: typeof totalPrice === 'number' ? Number(totalPrice) : undefined,
|
||||
},
|
||||
relationships: {
|
||||
cartItems: items.map(it => ({
|
||||
attributes: { quantity: Number(it.quantity) },
|
||||
relationships: {
|
||||
product: { data: { id: it.productId } }
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// === استخراج الـ productId من أي شكل محتمل ===
|
||||
export const extractProductId = (product) => (
|
||||
product?.relationships?.supplier_product?.id ||
|
||||
product?.relationships?.product?.data?.id ||
|
||||
product?.supplier_product_id ||
|
||||
product?.product_id ||
|
||||
product?.id
|
||||
);
|
||||
|
||||
// === استخراج عناصر الكارت من استجابة الباك ===
|
||||
export const getItemsFromCart = (cartData) => {
|
||||
const rel = cartData?.relationships || {};
|
||||
const list = rel.cartItems || rel.cart_items || [];
|
||||
return list.map(item => ({
|
||||
id: item.id,
|
||||
productId: item.relationships?.supplier_product?.id ||
|
||||
item.relationships?.product?.data?.id,
|
||||
quantity: Number(item?.attributes?.quantity || 0),
|
||||
})).filter(x => x.productId);
|
||||
};
|
||||
|
||||
// === إضافة/تحديث عنصر في قائمة الكارت ===
|
||||
export const upsertItem = (items, productId, quantity) => {
|
||||
const idx = items.findIndex(x => String(x.productId) === String(productId));
|
||||
if (idx >= 0) {
|
||||
const merged = [...items];
|
||||
merged[idx] = { ...merged[idx], quantity: Number(merged[idx].quantity) + Number(quantity) };
|
||||
return merged;
|
||||
}
|
||||
return [...items, { productId, quantity: Number(quantity) }];
|
||||
};
|
||||
|
||||
// === حساب إجمالي مؤقت إن توفر priceMap ===
|
||||
export const estimateTotal = (items, priceMap) => {
|
||||
if (!priceMap) return undefined;
|
||||
return items.reduce((sum, it) => sum + (Number(priceMap[it.productId]) || 0) * Number(it.quantity), 0);
|
||||
};
|
||||
|
||||
// === التأكد من وجود كارت فعّالة وإنشاؤها إذا لم توجد ===
|
||||
export const ensureActiveCart = async () => {
|
||||
const existing = getActiveCartId();
|
||||
if (existing) return existing;
|
||||
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) return null;
|
||||
|
||||
const payload = {
|
||||
data: {
|
||||
type: "cart",
|
||||
attributes: { totalPrice: 0 },
|
||||
relationships: { cartItems: [] }
|
||||
}
|
||||
};
|
||||
|
||||
const res = await authService.createCart(payload);
|
||||
if (res?.success && res?.data?.id) {
|
||||
setActiveCartId(res.data.id);
|
||||
return res.data.id;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// === إضافة منتج للكارت الفعّالة ===
|
||||
export const addItemToActiveCart = async ({ product, quantity = 1, priceMap = null }) => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) return { success: false, message: 'No token found' };
|
||||
|
||||
const cartId = await ensureActiveCart();
|
||||
if (!cartId) return { success: false, message: 'Failed to create or get cart' };
|
||||
|
||||
const current = await authService.getCartById(cartId);
|
||||
if (!current?.success || !current?.data) return { success: false, message: 'Failed to fetch active cart' };
|
||||
|
||||
const existingItems = getItemsFromCart(current.data);
|
||||
const productId = extractProductId(product);
|
||||
if (!productId) return { success: false, message: 'Invalid product id' };
|
||||
|
||||
const mergedItems = upsertItem(existingItems, productId, quantity);
|
||||
const totalPrice = estimateTotal(mergedItems, priceMap);
|
||||
const updatePayload = buildCartPayload(mergedItems, totalPrice);
|
||||
|
||||
const updated = await authService.updateCart(cartId, updatePayload);
|
||||
if (updated?.success && updated?.data?.id) {
|
||||
setActiveCartId(updated.data.id);
|
||||
return { success: true, data: updated.data, cartId: updated.data.id };
|
||||
}
|
||||
|
||||
return { success: false, message: updated?.message || 'Failed to update cart', errors: updated?.errors || null };
|
||||
};
|
||||
|
||||
// === تصدير الأدوات كموديل واحد ===
|
||||
const cartHelpers = {
|
||||
setActiveCartId,
|
||||
getActiveCartId,
|
||||
clearActiveCartId,
|
||||
ensureActiveCart,
|
||||
addItemToActiveCart,
|
||||
buildCartPayload,
|
||||
extractProductId,
|
||||
getItemsFromCart,
|
||||
upsertItem,
|
||||
estimateTotal,
|
||||
};
|
||||
|
||||
export default cartHelpers;
|
||||
المرجع في مشكلة جديدة
حظر مستخدم