Apne business ki identity, users, roles aur form access yahan manage karein.
ADMIN ONLY
Business profile
Yeh naam dashboard, sidebar aur browser title par show hoga.
User accounts & permissions
Har user ke liye role, visible pages aur create/edit/delete rights define karein.
USER
ROLE
OFFICE
STATUS
ACCESS
ACTIONS
Role guide
Role defaults apply jab user ke liye custom permissions select na ki jayein.
AdministratorComplete business, user, record aur settings access.Store operatorPurchases, vendors, assets, inventory aur movements.Office viewerAssigned office ke records read-only mode mein.
`;}
function officeName(id){return (settingsCtx.data?.offices||[]).find(o=>Number(o.id)===Number(id))?.name||'All offices';}
function renderUsers(panel){const body=panel.querySelector('[data-users-body]');const users=settingsCtx.data?.users||[];body.innerHTML=users.length?users.map(u=>{const p=normalizedPermissions(u);return `
${settingsEsc(u.name)}${settingsEsc(u.email)}
${settingsEsc(u.role)}
${settingsEsc(officeName(u.office_id))}
${settingsActive(u)?'Active':'Inactive'}
${p.pages.length} pages · ${p.actions.length} rights
`}).join(''):'
No users found. Create the first user above.
';}
function setBusinessForm(panel){const s=settingsCtx.data?.settings||{};const form=panel.querySelector('.business-form');for(const key of ['business_name','business_phone','business_email','business_address']){const input=form.elements[key];if(input)input.value=s[key]||'';}const preview=panel.querySelector('[data-logo-preview]');if(s.logo){preview.innerHTML=``}else preview.innerHTML='No logo selected';}
function openUserEditor(user){const editing=!!user;const initialRole=user?.role||'store';const perms=normalizedPermissions(user||{role:initialRole});const offices=(settingsCtx.data?.offices||[]).filter(settingsActive);const root=document.createElement('div');root.className='settings-user-backdrop';root.innerHTML=`
USER ACCESS CONTROL
${editing?'Edit user':'Create user'}
Role pages ko visible rakhta hai aur rights se forms/actions control hote hain.
`;document.body.append(root);const modal=root.firstElementChild;const form=modal.querySelector('form');const close=()=>root.remove();modal.querySelector('.settings-modal-close').onclick=close;modal.querySelector('.settings-modal-cancel').onclick=close;root.addEventListener('click',e=>{if(e.target===root)close()});const role=form.elements.role;const office=form.elements.office_id;const syncOffice=()=>{const isOffice=role.value==='office';modal.querySelector('[data-office-field]').hidden=!isOffice;office.required=isOffice;if(!isOffice)office.value='';};const setChecks=(name,values)=>modal.querySelectorAll(`input[name="${name}"]`).forEach(input=>input.checked=values.includes(input.value));const applyDefaults=()=>{const d=roleDefaults[role.value]||roleDefaults.store;setChecks('pages',d.pages);setChecks('actions',d.actions);};form.elements.name.value=user?.name||'';form.elements.email.value=user?.email||'';role.value=initialRole;if(editing){form.elements.active.value=settingsActive(user)?'1':'0';office.value=user.office_id||'';}role.onchange=syncOffice;modal.querySelector('[data-apply-role-defaults]').onclick=applyDefaults;syncOffice();form.onsubmit=async e=>{e.preventDefault();const button=form.querySelector('button[type="submit"]');const message=modal.querySelector('[data-user-message]');button.disabled=true;message.textContent='';const payload={name:form.elements.name.value,email:form.elements.email.value,role:role.value,office_id:office.value,permissions:JSON.stringify({pages:[...modal.querySelectorAll('input[name="pages"]:checked')].map(x=>x.value),actions:[...modal.querySelectorAll('input[name="actions"]:checked')].map(x=>x.value)})};if(editing){payload.id=user.id;payload.active=form.elements.active.value;}else payload.password=form.elements.password.value;try{await settingsApi(editing?'user_update':'user',payload);close();await refreshSettings();}catch(err){message.textContent=err.message;button.disabled=false;}};}
async function resetUser(user){const password=window.prompt('New password (minimum 12 characters)');if(password===null)return;if(password.length<12){window.alert('Password minimum 12 characters ka hona chahiye.');return;}try{await settingsApi('reset',{id:user.id,password});await refreshSettings();window.alert('Password reset ho gaya.');}catch(e){window.alert(e.message);}}
async function userAction(panel,e){const button=e.target.closest('[data-user-action]');if(!button)return;const user=(settingsCtx.data?.users||[]).find(u=>String(u.id)===button.dataset.id);if(!user)return;try{const action=button.dataset.userAction;if(action==='edit'){openUserEditor(user);return}if(action==='reset'){await resetUser(user);return}if(action==='toggle'){const next=!settingsActive(user);if(!window.confirm(`${next?'Activate':'Deactivate'} this user?`))return;await settingsApi('set_active',{entity:'user',id:user.id,active:next?'1':'0'});}if(action==='delete'){if(!window.confirm('Delete this user permanently? Linked history will block deletion.'))return;await settingsApi('delete_record',{entity:'user',id:user.id});}await refreshSettings();}catch(err){window.alert(err.message);}}
async function readLogo(file){if(!file)return settingsCtx.data?.settings?.logo||'';if(file.size>800000)throw Error('Logo file 800 KB se choti honi chahiye.');return new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=()=>resolve(reader.result);reader.onerror=()=>reject(Error('Logo read nahi ho saka.'));reader.readAsDataURL(file);});}
function wireBusiness(panel){const form=panel.querySelector('.business-form');form.onsubmit=async e=>{e.preventDefault();const button=form.querySelector('button[type="submit"]');const message=panel.querySelector('[data-business-message]');button.disabled=true;message.textContent='';try{const file=form.elements.logo_file.files[0];const payload={business_name:form.elements.business_name.value,business_phone:form.elements.business_phone.value,business_email:form.elements.business_email.value,business_address:form.elements.business_address.value,logo:await readLogo(file)};await settingsApi('settings_update',payload);await refreshSettings();message.textContent='Business profile save ho gaya.';}catch(err){message.textContent=err.message}finally{button.disabled=false;}};}
async function refreshSettings(){if(!(await settingsLoad()))return;const old=document.querySelector('[data-settings-panel]');if(old){const fresh=document.createElement('div');fresh.innerHTML=settingsPanelMarkup();const panel=fresh.firstElementChild;old.replaceWith(panel);renderUsers(panel);setBusinessForm(panel);wireBusiness(panel);}}
function enhanceSettings(){if(!settingsCtx.user||settingsCtx.user.role!=='admin'||settingsPage()!=='Settings')return;let panel=document.querySelector('[data-settings-panel]');if(!panel){const old=document.querySelector('section.settings');if(!old)return;const holder=document.createElement('div');holder.innerHTML=settingsPanelMarkup();panel=holder.firstElementChild;old.replaceWith(panel);renderUsers(panel);setBusinessForm(panel);wireBusiness(panel);}if(panel&&!panel.dataset.settingsEvents){panel.dataset.settingsEvents='1';panel.querySelector('[data-add-user]').onclick=()=>openUserEditor(null);panel.addEventListener('click',e=>userAction(panel,e));}}
const settingsObserver=new MutationObserver(()=>requestAnimationFrame(enhanceSettings));settingsObserver.observe(document.body,{childList:true,subtree:true});
setInterval(async()=>{if(!settingsCtx.user){if(await settingsLoad())enhanceSettings();}else{applyBusinessBranding(settingsCtx.data?.settings);enhanceSettings();}},1500);
settingsLoad().then(enhanceSettings).catch(()=>{});