teach/public/js/role-preview.js
Ramon b81f5ac5dd
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 56s
feat: voeg rolvoorbeeld voor systeemmanager toe (v0.4.39-beta)
2026-07-20 14:08:37 +02:00

108 lines
4 KiB
JavaScript

/* teach - veilige rolvoorbeeldweergave voor systeemmanagers.
Alleen de clientinterface en zichtbare menu's veranderen. De sessiecookie,
currentUser en serverautorisatie blijven altijd van de systeemmanager. */
"use strict";
(function(){
const roleRow=document.getElementById("superViewRole");
const roleSeg=document.getElementById("segViewRole");
const banner=document.getElementById("rolePreviewBanner");
const bannerLabel=document.getElementById("rolePreviewLabel");
const resetButton=banner.querySelector("button");
const ROLE_KEYS={
super:"vwRoleSystem",admin:"vwRoleAdmin",teacher:"vwRoleTeacher",
parent:"vwRoleParent",pupil:"vwRolePupil"
};
let renderSequence=0;
const isSystemManager=()=>!!currentUser&&currentUser.role==="super";
const roleLabel=role=>T(ROLE_KEYS[role]||ROLE_KEYS.super);
function storedRole(){
try{
const value=localStorage.getItem("teach.superViewRole");
return VIEW_ROLES.includes(value)?value:"super";
}catch(e){return"super";}
}
function storeRole(role){
try{localStorage.setItem("teach.superViewRole",role);}catch(e){}
}
function previewNotice(text){
const note=document.createElement("aside");
note.className="role-preview-note";
const strong=document.createElement("strong");
strong.textContent=T("vwPreview")+": ";
note.append(strong,document.createTextNode(text));
return note;
}
function clearPreviewSurface(){
renderSequence++;
document.body.classList.remove("role-preview-active","role-preview-parent","role-preview-pupil");
banner.hidden=true;
if(isSystemManager()){
stopPupilView();
stopParentView();
}
}
function syncControls(){
const enabled=isSystemManager();
roleRow.hidden=!enabled;
const role=enabled?activeRole():"super";
roleSeg.querySelectorAll("button").forEach(button=>{
const selected=button.dataset.role===role;
button.classList.toggle("active",selected);
button.setAttribute("aria-pressed",String(selected));
});
banner.hidden=!enabled||role==="super";
bannerLabel.textContent=enabled&&role!=="super"?roleLabel(role):"";
}
async function renderPreviewSurface(){
const sequence=++renderSequence;
if(!isSystemManager()){clearPreviewSurface();syncControls();return;}
const role=activeRole();
document.body.classList.remove("role-preview-active","role-preview-parent","role-preview-pupil");
stopPupilView();
stopParentView();
if(role==="parent"){
document.body.classList.add("role-preview-active","role-preview-parent","parent-mode");
renderParentView([]);
const inner=parentView.querySelector(".parent-inner");
if(inner)inner.prepend(previewNotice(T("vwParentPreview")));
parentView.querySelectorAll("button,input,select,textarea").forEach(control=>{control.disabled=true;});
}else if(role==="pupil"){
document.body.classList.add("role-preview-active","role-preview-pupil","pupil-mode");
const snapshot=serializeBoard();
await renderPupilWidgets(snapshot.widgets||[],"kijken",true);
if(sequence!==renderSequence)return;
pupilView.prepend(previewNotice(T("vwPupilPreview")));
}
syncControls();
}
function chooseRole(role){
if(!isSystemManager()||!VIEW_ROLES.includes(role))return;
setActiveViewRole(role);
storeRole(role);
updateUserUI();
document.dispatchEvent(new CustomEvent("userchange"));
}
roleSeg.querySelectorAll("button").forEach(button=>{
button.addEventListener("click",()=>chooseRole(button.dataset.role));
});
resetButton.addEventListener("click",()=>chooseRole("super"));
document.addEventListener("userchange",()=>{
if(isSystemManager()){
const saved=storedRole();
if(activeRole()!==saved)setActiveViewRole(saved);
}else{
setActiveViewRole("super");
}
syncControls();
renderPreviewSurface();
});
document.addEventListener("langchange",()=>{
syncControls();
if(isSystemManager()&&["parent","pupil"].includes(activeRole()))renderPreviewSurface();
});
syncControls();
})();