1/** Gratis z sklepiku lojalnoÅciowego â kolejka do koszyka + budowa pozycji. */ 2 3export const LOYALTY_FREE_PENDING_KEY = 'planeta_loyalty_free_pending'; 4 5export function pickDefaultMenuSize(menuItem) { 6 const sizes = Array.isArray(menuItem?.sizes) ? menuItem.sizes : []; 7 if (!sizes.length) return null; 8 const base = sizes.find((s) => Number(s.priceModifier) === 0); 9 return String((base || sizes[0])?.name || '').trim() || null; 10} 11 12export function catalogUnitPrice(menuItem, size = null) { 13 const base = Math.max(0, Number(menuItem?.price) || 0); 14 if (!size) return Math.round(base * 100) / 100; 15 const mod = (menuItem?.sizes || []).find((s) => s.name === size)?.priceModifier; 16 return Math.round((base + (Number(mod) || 0)) * 100) / 100; 17} 18 19export function buildLoyaltyFreeCartKey(itemId, size = null) { 20 return `${itemId}::${size || 'default'}::loyaltyFree`; 21} 22 23export function buildLoyaltyFreeCartItem(menuItem, { couponCode, size = null } = {}) { 24 if (!menuItem?.id) return null; 25 const chosenSize = size || pickDefaultMenuSize(menuItem); 26 const catalogPrice = catalogUnitPrice(menuItem, chosenSize); 27 return { 28 cartKey: buildLoyaltyFreeCartKey(menuItem.id, chosenSize), 29 id: menuItem.id, 30 name: menuItem.name || menuItem.id, 31 size: chosenSize, 32 price: 0, 33 catalogPrice, 34 image: menuItem.image || '', 35 extras: [], 36 quantity: 1, 37 loyaltyFree: true, 38 loyaltyCouponCode: String(couponCode || '').trim().toUpperCase() || null 39 }; 40} 41 42export function queueLoyaltyFreeItem({ itemId, couponCode, title = '', size = null } = {}) { 43 const payload = { 44 itemId: String(itemId || '').trim(), 45 couponCode: String(couponCode || '').trim().toUpperCase(), 46 title: String(title || '').trim(), 47 size: String(size || '').trim() || null, 48 queuedAt: Date.now() 49 }; 50 if (!payload.itemId || !payload.couponCode) return false; 51 try { 52 localStorage.setItem(LOYALTY_FREE_PENDING_KEY, JSON.stringify(payload)); 53 localStorage.setItem('promoCode', payload.couponCode); 54 return true; 55 } catch { 56 return false; 57 } 58} 59 60export function peekLoyaltyFreePending() { 61 try { 62 const raw = localStorage.getItem(LOYALTY_FREE_PENDING_KEY); 63 if (!raw) return null; 64 const data = JSON.parse(raw); 65 if (!data?.itemId || !data?.couponCode) return null; 66 return data; 67 } catch { 68 return null; 69 } 70} 71 72export function clearLoyaltyFreePending() { 73 try { 74 localStorage.removeItem(LOYALTY_FREE_PENDING_KEY); 75 } catch {} 76} 77 78export function cartCatalogSubtotal(items = []) { 79 return Math.round( 80 (items || []).reduce((sum, item) => { 81 const unit = item?.loyaltyFree 82 ? (Number(item.catalogPrice) || 0) 83 : (Number(item.price) || 0); 84 return sum + unit * Math.max(1, Number(item.quantity) || 1); 85 }, 0) * 100 86 ) / 100; 87}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.