⚠ Emergency? Call 911. Online services are not monitored 24/7.Non-emergency line: (555) 010-4400
Connecting to the Officer Portal…
`);w.document.close()} /* ---------- events ---------- */ main.addEventListener("click",async e=>{ const t=e.target.closest("[data-act]");if(!t||t.tagName==="SELECT")return;const act=t.dataset.act; if(act==="go"){go(t.dataset.v);return} if(act==="new"){go(t.dataset.v);openEditor(t.dataset.v,null);return} if(act==="newHere"){openEditor(view,null);return} if(act==="refresh"){t.disabled=true;await loadAll();renderSide();renderOverview();toast("Dashboard refreshed.");return} if(act==="seed"){t.disabled=true;t.textContent="Loading…";try{for(const r of DEFAULT_RANKS)await api("Rank",{method:"POST",body:{name:r[0],abbreviation:r[1],level:r[2]}});await load("Rank");renderEntity("Rank");renderSide();toast("Default ranks loaded. Edit them any time.")}catch(err){toast("Couldn't load ranks: "+err.message);t.disabled=false;t.textContent="Load default ranks"}return} const tr=t.closest("tr[data-id]");if(!tr)return;const n=view,id=+tr.dataset.id,r=(DATA[n]||[]).find(x=>x.id===id);if(!r)return; if(act==="view"){const nx=tr.nextElementSibling;if(nx&&nx.classList.contains("detail")){nx.remove();t.textContent="View";return}const d=document.createElement("tr");d.className="detail";d.innerHTML=`${detailHTML(n,r)}`;tr.after(d);t.textContent="Hide"} else if(act==="edit")openEditor(n,r); else if(act==="print")printRec(n,r); else if(act==="hire"){const map={"Patrol Officer":"Patrol","Dispatcher":"Dispatch","Detective":"Investigations","K-9 Handler":"K-9","SWAT / Tactical":"SWAT","Traffic Division":"Traffic","Reserve Officer":"Patrol"};const rn=ranks().map(x=>x.name);const want=r.position==="Dispatcher"?"Dispatcher":"Probationary Officer";go("Officer");openEditor("Officer",null,{name:r.name,rank:rn.includes(want)?want:rn[rn.length-1],division:map[r.position]||"Patrol",status:"Active",join_date:TODAY()});if(r.status!=="Accepted")api("Application/"+r.id,{method:"PATCH",body:{status:"Accepted"}}).then(()=>{r.status="Accepted";renderSide()}).catch(()=>{})} else if(act==="del"){if(!confirm("Delete this record permanently? This can't be undone."))return;try{await api(n+"/"+id,{method:"DELETE"});DATA[n]=DATA[n].filter(x=>x.id!==id);renderRows(n);renderSide();toast("Record deleted.")}catch(err){toast("Delete failed: "+err.message)}} }); main.addEventListener("change",async e=>{const s=e.target.closest('select[data-act="field"]');if(!s)return;const n=view,tr=s.closest("tr[data-id]");if(!tr)return;const id=+tr.dataset.id,f=s.dataset.field,r=(DATA[n]||[]).find(x=>x.id===id);if(!r)return;const old=r[f];s.disabled=true; try{await api(n+"/"+id,{method:"PATCH",body:{[f]:s.value}});r[f]=s.value;renderSide();toast(ENT[n].single+" updated: "+s.value);if(f===ENT[n].statusField)s.className="pill st-sel "+pillCls(n,s.value);if(n==="Officer"&&f==="rank")renderRows(n)} catch(err){s.value=old||"";toast("Update failed: "+err.message)}finally{s.disabled=false}}); main.addEventListener("input",e=>{if(e.target.id==="q"||e.target.id==="sf")renderRows(view)}); /* ---------- boot ---------- */ (async()=>{ const denied=await loadAll();document.getElementById("loading").hidden=true; if(denied){document.getElementById("locked").hidden=false;return} document.getElementById("portal").hidden=false; view=ENT[location.hash.slice(1)]?location.hash.slice(1):"overview";renderSide();go(view); setInterval(async()=>{if(document.hidden)return;await loadAll();renderSide();if(view==="overview")renderOverview()},60000); })(); })();