{"id":65,"date":"2025-12-05T16:06:59","date_gmt":"2025-12-05T21:06:59","guid":{"rendered":"https:\/\/shop.thegrandmehfil.com\/?page_id=65"},"modified":"2025-12-05T16:06:59","modified_gmt":"2025-12-05T21:06:59","slug":"65-2","status":"publish","type":"page","link":"https:\/\/shop.thegrandmehfil.com\/?page_id=65","title":{"rendered":""},"content":{"rendered":"  <div class=\"mfa-wrap\">\r\n    <div class=\"mfa-card\">\r\n      <div class=\"mfa-title\">Grocery Cost Analysis<\/div>\r\n      <div class=\"mfa-sub\">\r\n        Based on recent Rozel invoice prices (per unit). Use this page to spot items whose cost is jumping up or down.\r\n      <\/div>\r\n\r\n      <div class=\"mfa-search\">\r\n        <input id=\"mfa-search\" type=\"search\" placeholder=\"Search item (e.g. CARROT 50 LB)\">\r\n      <\/div>\r\n\r\n      <div id=\"mfa-status\" class=\"mfa-status\"><\/div>\r\n\r\n      <div style=\"overflow-x:auto\">\r\n        <table class=\"mfa-table\">\r\n          <thead>\r\n            <tr>\r\n              <th>Item<\/th>\r\n              <th>Last<\/th>\r\n              <th>Avg (last 6)<\/th>\r\n              <th>Min<\/th>\r\n              <th>Max<\/th>\r\n              <th>Last 3<\/th>\r\n              <th>Last vs Avg<\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"mfa-tbody\"><\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n  <script>(function(){\r\n    const STYLE=document.createElement('style');\r\n    STYLE.textContent=`\r\n  :root{\r\n    --bg:#0f172a;--card:#0b1220;--ink:#e2e8f0;\r\n    --muted:#94a3b8;--line:#1f2937;\r\n  }\r\n  .mfa-wrap{\r\n    max-width:1100px;margin:0 auto;padding:14px;\r\n    font-family:system-ui,Segoe UI,Roboto,Arial,sans-serif;\r\n    color:var(--ink);\r\n  }\r\n  .mfa-card{\r\n    background:var(--card);\r\n    border:1px solid var(--line);\r\n    border-radius:16px;\r\n    padding:16px;\r\n    margin-top:12px;\r\n  }\r\n  .mfa-title{\r\n    font-size:20px;font-weight:700;margin-bottom:4px;\r\n  }\r\n  .mfa-sub{\r\n    font-size:13px;color:var(--muted);margin-bottom:12px;\r\n  }\r\n  .mfa-status{\r\n    font-size:13px;color:var(--muted);margin:8px 0;\r\n  }\r\n  .mfa-search{margin:8px 0 12px}\r\n  .mfa-search input{\r\n    width:100%;max-width:320px;\r\n    padding:8px 10px;\r\n    border-radius:10px;\r\n    border:1px solid var(--line);\r\n    background:#020617;\r\n    color:var(--ink);\r\n    font-size:14px;\r\n  }\r\n  .mfa-table{\r\n    width:100%;\r\n    border-collapse:collapse;\r\n    font-size:13px;\r\n  }\r\n  .mfa-table th,.mfa-table td{\r\n    padding:6px 8px;\r\n    border-bottom:1px solid var(--line);\r\n    text-align:left;\r\n  }\r\n  .mfa-table th{\r\n    font-size:11px;\r\n    text-transform:uppercase;\r\n    letter-spacing:.04em;\r\n    color:var(--muted);\r\n  }\r\n  .mfa-badge-up{\r\n    color:#f97316;\r\n    font-weight:600;\r\n  }\r\n  .mfa-badge-down{\r\n    color:#22c55e;\r\n    font-weight:600;\r\n  }\r\n  `;\r\n    document.head.appendChild(STYLE);\r\n\r\n    const ajax='https:\/\/shop.thegrandmehfil.com\/wp-admin\/admin-ajax.php';\r\n    const base='https:\/\/script.google.com\/macros\/s\/AKfycby0cp7WxBTKZ3WPaTdFLP1Xpq27QuGLtP1dRQN6faKviS_XAWOk4x-bWSE1uy12-b0fpA\/exec';\r\n    const key='';\r\n\r\n    const qs=o=>new URLSearchParams(o).toString();\r\n    async function proxyGet(){\r\n      const r=await fetch(ajax,{\r\n        method:'POST',\r\n        headers:{'Content-Type':'application\/x-www-form-urlencoded'},\r\n        body:qs({action:'mehfil_get'})\r\n      });\r\n      if(!r.ok) throw new Error('HTTP '+r.status);\r\n      return await r.json();\r\n    }\r\n    async function directGet(){\r\n      const p={action:'getData',t:Date.now()};\r\n      if(key) p.key=key;\r\n      const r=await fetch(base+'?'+qs(p));\r\n      if(!r.ok) throw new Error('HTTP '+r.status);\r\n      return await r.json();\r\n    }\r\n    const apiGet=async()=>{ try{return await proxyGet();}catch(e){return await directGet();} };\r\n\r\n    const statusEl=document.getElementById('mfa-status');\r\n    const searchEl=document.getElementById('mfa-search');\r\n    const tbody=document.getElementById('mfa-tbody');\r\n    let ALL=[];\r\n\r\n    function fmtMoney(v){\r\n      if(v===null||v===undefined||v==='') return '';\r\n      const n=Number(v); if(!isFinite(n)) return '';\r\n      return n.toFixed(2);\r\n    }\r\n    function fmtPct(v){\r\n      if(!isFinite(v)) return '';\r\n      return v.toFixed(1)+'%';\r\n    }\r\n\r\n    function renderRows(rows){\r\n      tbody.innerHTML='';\r\n      if(!rows.length){\r\n        const tr=document.createElement('tr');\r\n        const td=document.createElement('td');\r\n        td.colSpan=7;\r\n        td.textContent='No items with price history yet.';\r\n        td.style.color='#64748b';\r\n        tr.appendChild(td);\r\n        tbody.appendChild(tr);\r\n        return;\r\n      }\r\n      rows.forEach(r=>{\r\n        const tr=document.createElement('tr');\r\n        function cell(txt,cls){\r\n          const td=document.createElement('td');\r\n          if(cls) td.className=cls;\r\n          td.textContent=txt;\r\n          return td;\r\n        }\r\n        tr.appendChild(cell(r.item));\r\n        tr.appendChild(cell(fmtMoney(r.last)));\r\n        tr.appendChild(cell(fmtMoney(r.avg)));\r\n        tr.appendChild(cell(fmtMoney(r.min)));\r\n        tr.appendChild(cell(fmtMoney(r.max)));\r\n        tr.appendChild(cell(r.last3Str||''));\r\n\r\n        let diffTxt='', diffCls='';\r\n        if(isFinite(r.diffPct) && Math.abs(r.diffPct)>=0.5){\r\n          diffTxt=fmtPct(r.diffPct);\r\n          diffCls=r.diffPct>=0?'mfa-badge-up':'mfa-badge-down';\r\n        }\r\n        tr.appendChild(cell(diffTxt,diffCls));\r\n        tbody.appendChild(tr);\r\n      });\r\n    }\r\n\r\n    function applyFilter(){\r\n      const q=(searchEl.value||'').trim().toLowerCase();\r\n      if(!q){\r\n        renderRows(ALL);\r\n        statusEl.textContent='Items with history: '+ALL.length;\r\n        return;\r\n      }\r\n      const filtered=ALL.filter(r=>r.item.toLowerCase().includes(q));\r\n      renderRows(filtered);\r\n      statusEl.textContent='Filtered: '+filtered.length+' of '+ALL.length;\r\n    }\r\n    if(searchEl) searchEl.addEventListener('input',applyFilter);\r\n\r\n    (async()=>{\r\n      try{\r\n        statusEl.textContent='Loading price history\u2026';\r\n        const data=await apiGet();\r\n\r\n        \/\/ \ud83d\udd25 NEW: read from data.priceHistory.items instead of data.depts[\u2026].items[\u2026].cost\r\n        const ph = data.priceHistory || {};\r\n        const items = ph.items || {};\r\n\r\n        let rows = Object.entries(items).map(([name, s])=>{\r\n          const last = Number(s.last);\r\n          const avg  = Number(s.avg);\r\n          const min  = Number(s.min);\r\n          const max  = Number(s.max);\r\n          let diffPct = null;\r\n          if(isFinite(avg) && avg!==0){\r\n            diffPct=((last-avg)\/avg)*100;\r\n          }\r\n          return {\r\n            item:name,\r\n            last:last,\r\n            avg:avg,\r\n            min:min,\r\n            max:max,\r\n            last3Str:s.last3Str || '',\r\n            n:s.n || 0,\r\n            diffPct:diffPct\r\n          };\r\n        });\r\n\r\n        \/\/ Sort by biggest movers first\r\n        rows.sort((a,b)=>{\r\n          const ad=Math.abs(a.diffPct||0);\r\n          const bd=Math.abs(b.diffPct||0);\r\n          return bd-ad;\r\n        });\r\n\r\n        ALL=rows;\r\n        applyFilter();\r\n\r\n        const count = ph.count || rows.length || 0;\r\n        if(!count){\r\n          statusEl.textContent='No PRICE_HISTORY yet \u2013 once some Rozel invoices are processed you\\'ll see cost trends here.';\r\n        }else{\r\n          statusEl.textContent='Items with history: '+count;\r\n        }\r\n      }catch(e){\r\n        console.error(e);\r\n        statusEl.textContent='Failed to load analysis: '+e.message;\r\n      }\r\n    })();\r\n  })();<\/script>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_kadence_starter_templates_imported_post":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"class_list":["post-65","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=\/wp\/v2\/pages\/65","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=65"}],"version-history":[{"count":1,"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=\/wp\/v2\/pages\/65\/revisions"}],"predecessor-version":[{"id":66,"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=\/wp\/v2\/pages\/65\/revisions\/66"}],"wp:attachment":[{"href":"https:\/\/shop.thegrandmehfil.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=65"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}