1import { loadOrderConfirmation } from './order-confirmation.js'; 2import { setCartItems, buildCartKeyFromItem } from './cart.js'; 3import { getMenu, getConfig } from './config.js'; 4import { getIngredients } from './ingredients.js'; 5import { sanitizeCartItems } from './order-validation.js'; 6 7const REPEAT_KEY = 'planeta_repeat_order'; 8 9export function saveRepeatOrderSnapshot(orderData) { 10 if (!orderData?.items?.length) return; 11 try { 12 const snapshot = { 13 savedAt: Date.now(), 14 items: orderData.items.map(item => ({ 15 id: item.id, 16 name: item.name, 17 size: item.size || null, 18 price: item.price, 19 image: item.image || '', 20 extras: Array.isArray(item.extras) ? item.extras : [], 21 quantity: Math.max(1, Number(item.quantity) || 1) 22 })) 23 }; 24 localStorage.setItem(REPEAT_KEY, JSON.stringify(snapshot)); 25 } catch {} 26} 27 28export function loadRepeatOrderSnapshot() { 29 try { 30 const raw = localStorage.getItem(REPEAT_KEY); 31 if (!raw) return null; 32 const data = JSON.parse(raw); 33 if (!Array.isArray(data?.items) || !data.items.length) return null; 34 return data; 35 } catch { 36 return null; 37 } 38} 39 40export function hasRepeatableOrder() { 41 if (loadRepeatOrderSnapshot()?.items?.length) return true; 42 const confirmation = loadOrderConfirmation(); 43 return Array.isArray(confirmation?.orderData?.items) && confirmation.orderData.items.length > 0; 44} 45 46export function repeatLastOrder({ openCart = true } = {}) { 47 const snapshot = loadRepeatOrderSnapshot(); 48 const confirmation = loadOrderConfirmation(); 49 const sourceItems = snapshot?.items?.length 50 ? snapshot.items 51 : (confirmation?.orderData?.items || []); 52 53 if (!sourceItems.length) { 54 return { ok: false, error: 'Brak poprzedniego zamówienia do powtórzenia.' }; 55 } 56 57 const mapped = sourceItems.map(item => ({ 58 id: item.id, 59 name: item.name, 60 size: item.size || null, 61 price: Number(item.price) || 0, 62 image: item.image || '', 63 extras: Array.isArray(item.extras) ? item.extras : [], 64 quantity: Math.max(1, Math.min(99, Number(item.quantity) || 1)), 65 cartKey: buildCartKeyFromItem(item) 66 })); 67 68 const sanitized = sanitizeCartItems(mapped, getMenu(), getIngredients(), { 69 promotions: getConfig()?.promotions || {} 70 }).map(item => ({ 71 ...item, 72 cartKey: buildCartKeyFromItem(item), 73 image: item.image || mapped.find(m => m.id === item.id)?.image || '' 74 })); 75 76 if (!sanitized.length) { 77 return { ok: false, error: 'Pozycje z poprzedniego zamówienia nie sÄ już dostÄpne w menu.' }; 78 } 79 80 setCartItems(sanitized); 81 82 if (openCart) { 83 document.getElementById('cart-btn')?.click(); 84 } 85 86 return { ok: true, count: sanitized.length }; 87} 88 89export function bindRepeatOrderButtons(root = document) { 90 root.querySelectorAll('[data-repeat-order]').forEach(btn => { 91 btn.addEventListener('click', (e) => { 92 e.preventDefault(); 93 const result = repeatLastOrder({ openCart: true }); 94 if (!result.ok) { 95 window.alert(result.error || 'Nie udaÅo siÄ powtórzyÄ zamówienia.'); 96 } else if (btn.dataset.repeatRedirect) { 97 window.location.href = btn.dataset.repeatRedirect; 98 } 99 }); 100 }); 101}
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.