(()=>{ if(typeof api!=='function') return; const esc=v=>String(v??'').replace(/[&<>\"]/g,c=>({'&':'&','<':'<','>':'>','\"':'"'}[c])); const money=p=>'₹'+(Number(p||0)/100).toLocaleString('en-IN',{minimumFractionDigits:2,maximumFractionDigits:2}); const fmt=v=>v?new Date(v).toLocaleString('en-IN'):'—'; const msg=(id,t,e=false)=>{const x=document.getElementById(id);if(x){x.textContent=t;x.className='status'+(e?' error':'')}}; const table=(heads,rows)=>`
${heads.map(x=>``).join('')}${rows||''}
${x}
No records found.
`; function page(id,title,body){const p=document.getElementById(id);if(!p)return null;p.innerHTML=`

${title}

Live production data. All writes are server-authorized and audited.

Loading…
${body}
`;return p} page('promos','🎟️ Promotions & rewards',`

Coupons

Referrals

Gift cards

Wallet & loyalty

`); async function loadPromos(){try{msg('promosStatus','Loading promotions…');const [c,r,g,w]=await Promise.all([api('/v1/admin/growth/coupons?limit=500'),api('/v1/admin/growth/referrals?limit=500'),api('/v1/admin/growth/gift-cards?limit=500'),api('/v1/admin/growth/rewards?limit=500')]);document.getElementById('couponBody').innerHTML=table(['Code','Discount','Window','Active','Actions'],(c.coupons||[]).map(x=>`${esc(x.code)}${x.discount_type==='percent'?esc(x.discount_value)+'%':money(x.discount_value)}${fmt(x.starts_at)} → ${fmt(x.ends_at)}${x.is_active?'ACTIVE':'OFF'}`).join(''));document.getElementById('referralBody').innerHTML=table(['Code','Status','Created'],(r.referrals||[]).map(x=>`${esc(x.code)}${esc(x.status)}${fmt(x.created_at)}`).join(''));document.getElementById('giftBody').innerHTML=table(['Balance','Expiry','Active'],(g.gift_cards||[]).map(x=>`${money(x.balance_paise)}${fmt(x.expires_at)}${x.is_active?'ACTIVE':'OFF'}`).join(''));document.getElementById('rewardBody').innerHTML=table(['Customer','Wallet','Points'],(w.wallets||[]).map(x=>{const l=(w.loyalty||[]).find(y=>y.customer_id===x.customer_id);return `${esc(x.customer_id)}${money(x.balance_paise)}${Number(l?.points||0)}`}).join(''));document.querySelectorAll('.coupon-toggle').forEach(b=>b.onclick=async()=>{b.disabled=true;try{await api('/v1/admin/growth/coupons/'+encodeURIComponent(b.dataset.id),{method:'PATCH',body:JSON.stringify({is_active:b.dataset.next==='true'})});await loadPromos()}catch(e){alert(e.message||'Coupon update failed')}finally{b.disabled=false}});msg('promosStatus','Promotion, referral, gift-card and reward data loaded.')}catch(e){msg('promosStatus',e.message||'Unable to load promotion data',true)}} document.getElementById('couponAdd')?.addEventListener('click',async()=>{const code=prompt('Coupon code (A-Z, 0-9, _ or -)');if(!code)return;const type=prompt('Discount type: percent or fixed','percent');const value=Number(prompt(type==='percent'?'Percent discount':'Fixed discount in paise','10'));if(!Number.isInteger(value)||value<=0)return alert('Invalid discount value');try{await api('/v1/admin/growth/coupons',{method:'POST',body:JSON.stringify({code,discount_type:type,discount_value:value})});await loadPromos()}catch(e){alert(e.message||'Coupon creation failed')}}); document.getElementById('giftAdd')?.addEventListener('click',async()=>{const code=prompt('Gift card code (store securely; only its hash is retained)');if(!code)return;const value=Number(prompt('Value in paise','1000'));if(!Number.isInteger(value)||value<100)return alert('Invalid value');try{await api('/v1/admin/growth/gift-cards',{method:'POST',body:JSON.stringify({code,value_paise:value})});alert('Gift card issued. Store the code securely; it cannot be recovered from Admin.');await loadPromos()}catch(e){alert(e.message||'Gift card creation failed')}}); document.getElementById('promosRefresh')?.addEventListener('click',loadPromos); page('staff','🛡️ Staff & roles',`
`); async function loadStaff(){try{msg('staffStatus','Loading staff…');const d=await api('/v1/admin/staff');const q=(document.getElementById('staffLiveSearch')?.value||'').toLowerCase();const rows=(d.staff||[]).filter(x=>`${x.email} ${x.role}`.toLowerCase().includes(q));document.getElementById('staffLiveBody').innerHTML=table(['Email','Role','Active','Updated','Actions'],rows.map(x=>`${esc(x.email||x.user_id)}${esc(x.role||'customer')}${x.is_active?'ACTIVE':'DISABLED'}${fmt(x.updated_at)}${x.role!=='super_admin'?` `:'Protected'}`).join(''));document.querySelectorAll('.staff-active').forEach(b=>b.onclick=async()=>{try{await api('/v1/admin/staff/'+encodeURIComponent(b.dataset.id)+'/active',{method:'POST',body:JSON.stringify({is_active:b.dataset.next==='true'})});await loadStaff()}catch(e){alert(e.message||'Staff status update failed')}});document.querySelectorAll('.staff-role').forEach(b=>b.onclick=async()=>{const role=prompt('Role: admin_manager, store_manager, billing_staff, order_staff, inventory_staff, content_manager, support_staff, review_moderator, report_viewer');if(!role)return;try{await api('/v1/admin/staff/'+encodeURIComponent(b.dataset.id)+'/role',{method:'POST',body:JSON.stringify({role})});await loadStaff()}catch(e){alert(e.message||'Role update failed')}});msg('staffStatus',`${rows.length} staff records loaded.`)}catch(e){msg('staffStatus',e.message||'Unable to load staff',true)}} document.getElementById('staffLiveRefresh')?.addEventListener('click',loadStaff);document.getElementById('staffLiveSearch')?.addEventListener('input',loadStaff); page('settings','⚙️ Operational settings',`
`); async function loadSettings(){try{msg('settingsStatus','Loading settings…');const d=await api('/v1/admin/settings');const rows=d.settings||[];document.getElementById('settingsLiveBody').innerHTML=table(['Key','Value','Updated'],rows.map(x=>`${esc(x.key)}${esc(JSON.stringify(x.value))}${fmt(x.updated_at)}`).join(''))+`

Update protected setting

`;document.getElementById('settingSave').onclick=async()=>{try{const key=document.getElementById('settingKey').value.trim();const raw=document.getElementById('settingValue').value;const value=JSON.parse(raw);await api('/v1/admin/settings',{method:'PATCH',body:JSON.stringify({key,value})});await loadSettings()}catch(e){alert(e.message||'Setting update failed')}};msg('settingsStatus',`${rows.length} settings loaded.`)}catch(e){msg('settingsStatus',e.message||'Unable to load settings',true)}} document.getElementById('settingsRefresh')?.addEventListener('click',loadSettings); window.__DTGrowth={loadPromos,loadStaff,loadSettings}; document.querySelectorAll('.nav button[data-page]').forEach(b=>{const old=b.onclick;b.onclick=()=>{if(old)old.call(b);if(b.dataset.page==='promos')loadPromos();if(b.dataset.page==='staff')loadStaff();if(b.dataset.page==='settings')loadSettings()}}); setTimeout(()=>{loadPromos();loadStaff();loadSettings()},700); })();