ASSETDESK RECORD
${title}
Changes are saved immediately and recorded in the audit log.
`;
document.body.append(back);const form=back.querySelector('form');const close=()=>back.remove();back.querySelector('.crud-close').onclick=close;back.querySelector('.crud-cancel').onclick=close;back.addEventListener('click',e=>{if(e.target===back)close()});
form.onsubmit=async e=>{e.preventDefault();const button=form.querySelector('button[type=submit]');button.disabled=true;const d=Object.fromEntries(new FormData(form));d.id=r.id;d.active=active(r)?'1':'0';if(entity==='user'&&d.role!=='office')d.office_id='';try{await api(`${entity}_update`,d);location.reload()}catch(err){form.querySelector('.crud-error').textContent=err.message;button.disabled=false}};
}
async function toggle(entity,r){const next=!active(r);const label=next?'activate':'deactivate';if(!confirm(`Are you sure you want to ${label} this record?`))return;try{await api('set_active',{entity,id:r.id,active:next?'1':'0'});location.reload()}catch(e){alert(e.message)}}
async function removeRecord(entity,r){if(!confirm('Delete this record permanently? Linked records will block deletion.'))return;try{await api('delete_record',{entity,id:r.id});location.reload()}catch(e){alert(e.message)}}
function controls(entity,r){const bar=document.createElement('div');bar.className='crud-action-bar';const state=document.createElement('span');state.className=`crud-state ${active(r)?'is-active':'is-inactive'}`;state.textContent=active(r)?'Active':'Inactive';bar.append(state);const editPermission={office:'office_edit',vendor:'vendor_edit',asset:'asset_edit',stock:'stock_edit',user:'user_edit'}[entity];if(canPermission(editPermission)){const edit=document.createElement('button');edit.className='crud-button edit';edit.textContent='Edit';edit.onclick=e=>{e.stopPropagation();openEditor(entity,r)};bar.append(edit)}if(canPermission('record_status')&&entity!=='user'||ctx.user?.role==='admin'){const change=document.createElement('button');change.className='crud-button toggle';change.textContent=active(r)?'Deactivate':'Activate';change.onclick=e=>{e.stopPropagation();toggle(entity,r)};bar.append(change)}if(canPermission('record_delete')&&(entity!=='user'||ctx.user?.role==='admin')){const del=document.createElement('button');del.className='crud-button delete';del.textContent='Delete';del.onclick=e=>{e.stopPropagation();removeRecord(entity,r)};bar.append(del)}return bar}
function enhanceCards(selector,entity,rows){document.querySelectorAll(selector).forEach(card=>{if(card.dataset.crudEnhanced)return;const heading=card.querySelector('h2')?.textContent.trim();const r=rows.find(x=>x.name===heading);if(!r)return;card.dataset.crudEnhanced='1';card.append(controls(entity,r))})}
function enhance(){if(!ctx.user||!ctx.data)return;const p=page();if(p==='Offices')enhanceCards('.office-grid .office-card','office',ctx.data.offices||[]);if(p==='Inventory')enhanceCards('.office-grid .office-card','stock',ctx.data.stock||[]);if(p==='Vendors')document.querySelectorAll('.table-wrap tbody tr').forEach(row=>{if(row.dataset.crudEnhanced)return;const name=row.cells[0]?.textContent.trim();const r=(ctx.data.vendors||[]).find(x=>x.name===name);if(!r)return;row.dataset.crudEnhanced='1';const cell=document.createElement('td');cell.append(controls('vendor',r));row.append(cell)});if(p==='Assets')document.querySelectorAll('.table-wrap tbody tr').forEach(row=>{if(row.dataset.crudEnhanced)return;const tag=row.querySelector('.asset-cell small')?.textContent.split('·')[0].trim();const r=(ctx.data.assets||[]).find(x=>x.tag===tag);if(!r)return;row.dataset.crudEnhanced='1';const cell=document.createElement('td');cell.append(controls('asset',r));row.append(cell)});if(p==='Users & access'&&ctx.user.role==='admin')document.querySelectorAll('.table-wrap tbody tr').forEach(row=>{if(row.dataset.crudEnhanced)return;const email=row.cells[1]?.textContent.trim();const r=(ctx.data.users||[]).find(x=>x.email===email);if(!r)return;row.dataset.crudEnhanced='1';row.lastElementChild?.append(controls('user',r))})}
const observer=new MutationObserver(()=>requestAnimationFrame(enhance));observer.observe(document.body,{childList:true,subtree:true});
setInterval(async()=>{if(!ctx.user||!ctx.loaded){if(await load())enhance()}},1500);load().then(enhance);