Skip to main content

oefenhub_beheerder_12_modules_V1_4.html

Korte beschrijving

Mockup van het modulebeheer voor beheerders binnen OefenHub. Deze pagina biedt overzicht en beheer van technische of inhoudelijke modules die in het platform beschikbaar zijn.

Gerelateerde documentatie

Bestand

Broncode

/mockups_html/beheerder/oefenhub_beheerder_12_modules_V1_4.html
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>OefenHub Beheer - Modules beheren</title>
<link href="./oefenhub_shared_logo.css" rel="stylesheet">
<style>
:root {
--blue-1:#8fd0ff; --blue-2:#5bb3ff; --blue-3:#1f82e9; --blue-4:#0d5db8;
--text:#114f95; --muted:#5f7ea5; --line:rgba(17,79,149,.12);
--orange-1:#ffbb4d; --orange-2:#ff9620; --orange-3:#f87400;
--green-1:#8adf67; --green-2:#57ba3c; --green-3:#2c9348;
--yellow-1:#ffd04e; --yellow-2:#f6aa07; --purple-1:#8d6cff; --purple-2:#6248d8;
--red-1:#ff8f8f; --red-2:#df4949;
--shadow:0 12px 28px rgba(35,100,177,.12); --shadow-soft:0 8px 18px rgba(35,100,177,.08);
}
* { box-sizing:border-box; }
html,body { margin:0; padding:0; }
body {
font-family:"Segoe UI", Tahoma, Geneva, Verdana, sans-serif; color:var(--text);
background:
radial-gradient(circle at 8% 14%, rgba(255,255,255,.68) 0 12%, transparent 13%),
radial-gradient(circle at 18% 10%, rgba(255,255,255,.45) 0 9%, transparent 10%),
radial-gradient(circle at 86% 17%, rgba(255,255,255,.58) 0 11%, transparent 12%),
linear-gradient(180deg, #7ec2f8 0%, #bfe2fd 15%, #edf7ff 34%, #f7fbff 100%);
min-height:100vh;
}
.wrap { width:min(1240px, calc(100% - 30px)); margin:0 auto; }
.header {
padding:10px 0 12px; background:linear-gradient(180deg, rgba(100,171,238,.92), rgba(120,192,248,.85));
border-bottom:1px solid rgba(255,255,255,.38); box-shadow:0 8px 20px rgba(28,100,177,.08);
position:relative; z-index:10;
}
.header-row { display:grid; grid-template-columns:minmax(220px,1fr) auto minmax(160px,1fr); align-items:center; gap:10px; }
.brand { display:flex; flex-direction:column; align-items:flex-start; min-width:250px; }
.brand img { display:block; height:46px; width:auto; }
.welcome-text { font-size:12px; color:rgba(17,79,149,.82); font-weight:700; margin-top:-10px; margin-left:53px; }
.nav-pills { display:flex; align-items:center; justify-content:center; gap:10px; white-space:nowrap; }
.nav-item { position:relative; }
.pill { border:0; border-radius:12px; padding:10px 16px; color:#fff; font-size:13px; font-weight:900; box-shadow:var(--shadow-soft); cursor:pointer; }
.pill.blue { background:linear-gradient(180deg, #2f88ea, #176acc); }
.pill.orange { background:linear-gradient(180deg, #ffbb4d, #ff7f12); }
.pill.green { background:linear-gradient(180deg, #8adf67, #58ba3d); }
.pill.has-chevron { display:inline-flex; align-items:center; gap:8px; }
.dropdown-menu {
position:absolute; top:calc(100% + 8px); left:0; width:304px; background:linear-gradient(180deg, rgba(255,255,255,.97), rgba(244,250,255,.98));
border-radius:20px; box-shadow:0 12px 24px rgba(35,100,177,.16); border:1px solid rgba(170,204,238,.55); padding:10px 12px;
z-index:40; opacity:0; visibility:hidden; transform:translateY(-4px); transition:opacity .18s ease, transform .18s ease, visibility .18s ease;
}
.dropdown-menu::before { content:""; position:absolute; top:-10px; left:36px; border-left:10px solid transparent; border-right:10px solid transparent; border-bottom:10px solid rgba(255,255,255,.97); }
.dropdown-menu.align-right { left:auto; right:0; width:294px; }
.dropdown-menu.align-right::before { left:auto; right:20px; }
.nav-item:hover .dropdown-menu, .nav-item:focus-within .dropdown-menu, .nav-item.open .dropdown-menu { opacity:1; visibility:visible; transform:translateY(0); }
.menu-list { display:flex; flex-direction:column; gap:0; }
.menu-link { display:grid; grid-template-columns:auto 1fr auto; align-items:center; gap:9px; padding:9px 11px; border-radius:13px; text-decoration:none; color:#18518f; font-size:15px; font-weight:900; box-shadow:inset 0 -1px 0 rgba(17,79,149,.10); }
.menu-link:last-child { box-shadow:none; }
.menu-link.no-arrow { grid-template-columns:auto 1fr; }
.menu-link:hover, .menu-link.is-active { background:linear-gradient(180deg, #edf5ff, #dcecff); }
.menu-icon { width:23px; height:23px; border-radius:7px; display:grid; place-items:center; color:#fff; font-size:14px; font-weight:900; box-shadow:inset 0 1px 1px rgba(255,255,255,.35), 0 4px 8px rgba(0,0,0,.10); }
.menu-icon.orange { background:linear-gradient(180deg, #ffbb4d, #ff7f12); }
.menu-icon.blue { background:linear-gradient(180deg, #49a4ff, #1f7fe2); }
.menu-icon.green { background:linear-gradient(180deg, #8add68, #4baa35); }
.menu-arrow { color:#18518f; font-size:20px; line-height:1; font-weight:700; }
.header-actions { display:flex; align-items:center; justify-content:flex-end; gap:10px; min-width:120px; }
.mail-btn, .profile-chip { border:0; box-shadow:var(--shadow-soft); cursor:pointer; }
.mail-btn { position:relative; width:40px; height:40px; border-radius:999px; background:linear-gradient(180deg, #ffffff, #eef6ff); color:var(--blue-4); font-size:17px; }
.badge { position:absolute; right:-2px; bottom:-2px; min-width:18px; height:18px; padding:0 5px; border-radius:999px; background:#e23838; color:#fff; font-size:11px; font-weight:800; display:flex; align-items:center; justify-content:center; border:2px solid #fff; }
.profile-nav { position:relative; }
.profile-chip { display:inline-flex; align-items:center; justify-content:center; width:40px; height:40px; border-radius:999px; background:linear-gradient(180deg, #ffffff, #edf6ff); padding:0; }
.avatar { width:28px; height:28px; border-radius:999px; display:grid; place-items:center; color:#fff; font-size:13px; font-weight:900; background:linear-gradient(180deg, #ffb247, #ff8120); }

main.page-shell { padding:22px 0 30px; }
.breadcrumb { display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-bottom:14px; color:#34679f; font-size:13px; font-weight:800; }
.breadcrumb strong { color:#0d5db8; }
.crumb-sep { opacity:.55; }
.hero-card, .panel-card, .side-card, .tabs-card, .table-card, .note-card, .detail-card { background:rgba(255,255,255,.92); border:1px solid rgba(17,79,149,.08); border-radius:26px; box-shadow:var(--shadow-soft); }
.hero-card { padding:20px 22px; margin-bottom:18px; }
.hero-title { margin:0 0 10px; font-size:22px; line-height:1.1; color:#0d5db8; }
.hero-text { margin:0; font-size:15px; line-height:1.65; max-width:940px; }
.subnav-note { margin-top:14px; padding-top:14px; border-top:1px solid rgba(17,79,149,.10); display:flex; gap:10px; flex-wrap:wrap; }
.subnav-pill { display:inline-flex; align-items:center; min-height:34px; padding:0 14px; border-radius:999px; background:#eef6ff; color:#1b5ca0; font-size:13px; font-weight:900; }
.subnav-pill.active { background:#174f90; color:#fff; }

.selection-grid { display:grid; grid-template-columns:minmax(0, 1.2fr) minmax(280px, .8fr); gap:18px; align-items:start; }
.panel-card { padding:18px 20px; min-width:0; overflow:hidden; }
.panel-head { display:flex; justify-content:space-between; gap:14px; align-items:flex-start; margin-bottom:14px; }
.panel-title { margin:0; font-size:19px; color:#0d5db8; }
.panel-copy { margin:6px 0 0; font-size:13px; line-height:1.5; color:#6280a3; }
.toolbar { display:flex; gap:10px; flex-wrap:wrap; align-items:center; }
.search-input, .mini-input, .mini-select, .text-input { width:100%; border:1px solid rgba(17,79,149,.14); background:rgba(255,255,255,.98); border-radius:16px; padding:13px 14px; font:inherit; color:#134f92; box-shadow:inset 0 1px 0 rgba(255,255,255,.8); }
.toolbar .search-wrap { flex:1 1 240px; min-width:220px; }
.toolbar .mini-select { width:auto; min-width:180px; }
.overview-list { display:grid; gap:10px; max-height:420px; overflow:auto; padding-right:6px; }
.overview-item { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:14px; align-items:center; padding:14px 15px; border:1px solid rgba(132,186,236,.35); background:linear-gradient(180deg, rgba(246,250,255,.96), rgba(235,244,255,.92)); border-radius:20px; min-width:0; }
.overview-main { min-width:0; }
.overview-head { display:flex; gap:12px; align-items:flex-start; min-width:0; }
.cat-icon { width:44px; height:44px; border-radius:14px; display:grid; place-items:center; color:#fff; font-weight:900; font-size:18px; flex:0 0 44px; }
.cat-copy { min-width:0; }
.cat-copy strong { display:block; font-size:15px; color:#0d5db8; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cat-copy span { display:block; margin-top:4px; font-size:13px; color:#5a7ea6; line-height:1.45; }
.meta-row { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.tag { display:inline-flex; align-items:center; min-height:26px; padding:0 10px; border-radius:999px; font-size:11px; font-weight:900; }
.tag.blue { background:#dceeff; color:#216ab9; } .tag.green { background:#e3f7ea; color:#23804a; } .tag.orange { background:#fff0d8; color:#c27209; } .tag.grey { background:#edf3f8; color:#6a84a2; }
.btn { border:0; border-radius:15px; min-height:44px; padding:0 16px; font:inherit; font-size:14px; font-weight:900; cursor:pointer; box-shadow:var(--shadow-soft); }
.btn-primary { background:linear-gradient(180deg, #ffbc4b, #ff9621); color:#fff; }
.btn-secondary { background:linear-gradient(180deg, #eef6ff, #dcecff); color:#0d5db8; }
.btn-danger { background:linear-gradient(180deg,#ef6b6b,#cf3e3e); color:#fff; }
.btn-ghost { background:#fff; color:#0d5db8; border:1px solid rgba(17,79,149,.14); box-shadow:none; }
.readonly-grid { display:grid; gap:0px; }
.readonly-row { display:grid; grid-template-columns:1fr auto; gap:10px; align-items:start; padding:10px 0; border-top:1px solid rgba(17,79,149,.08); }
.readonly-row:first-child { border-top:0; padding-top:0; }
.readonly-row span { color:#6381a4; font-size:13px; }
.readonly-row strong { color:#184f90; font-size:14px; text-align:right; }
.quick-history { margin-top:14px; padding-top:14px; border-top:1px solid rgba(17,79,149,.10); max-height:320px; overflow:auto; padding-right:6px; }
.quick-history h3 { margin:0 0 10px; font-size:15px; color:#0d5db8; }
.history-mini-item { padding:10px 12px; border-radius:16px; background:#f7fbff; border:1px solid rgba(17,79,149,.08); margin-bottom:8px; }
.history-mini-item:last-child { margin-bottom:0; }
.history-mini-item strong { display:block; font-size:13px; color:#184f90; }
.history-mini-item span { display:block; margin-top:4px; font-size:12px; color:#6381a4; line-height:1.45; }
.manage-stage { display:none; margin-top:18px; }
.manage-stage.open { display:block; }
.manage-head { display:flex; justify-content:space-between; align-items:center; gap:16px; margin-bottom:14px; }
.top-summary { display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:12px; margin-top:14px; }
.summary-box { border:1px solid #d5e5f7; background:#f8fbff; border-radius:24px; padding:8px 15px; }
.summary-box strong { display:block; color:#1a4f8f; font-size:19px; margin-bottom:8px; }
.summary-box span { color:#5f80a8; font-size:12px; line-height:1.55; display:block; }
.top-summary-two { grid-template-columns:repeat(2, minmax(0,1fr)); }
.meta-card-list { display:grid; grid-template-columns:1fr; gap:12px; margin-top:12px; }
.meta-card {
border:1px solid #d5e5f7; background:#f8fbff; border-radius:24px; padding:8px 15px;
display:grid; gap:4px; align-items:start;
}
.meta-card strong { color:#5374a0; font-size:13px; display:block; }
.meta-card span { color:#1a4f8f; font-size:14px; line-height:1.45; display:block; }
.tabs-card { padding:16px 18px 20px; }
.tab-row { display:flex; align-items:flex-end; gap:6px; flex-wrap:wrap; margin:0px; }
.tab-btn {
border:1px solid rgba(140,197,242,1); border-bottom:0; border-radius:18px 18px 0 0;
background:linear-gradient(180deg, rgba(255,255,255,.94), rgba(245,250,255,.96));
color:#235b99; font-weight:900; font-size:13px; padding:0 20px; min-height:25px;
display:inline-flex; align-items:center; justify-content:center; cursor:pointer; box-shadow:0 -3px 12px rgba(35,100,177,.05);
}
.tab-btn.active { background:linear-gradient(180deg,#4ea5ff,#1f79dc); color:#fff; border-color:#2f88ea; }
.tab-pane {
display:none; background:linear-gradient(180deg, rgba(255,255,255,.94), rgba(245,250,255,.96));
border:1px solid rgb(140 197 242); border-radius:0 24px 24px 24px; padding:18px; box-shadow:var(--shadow-soft); min-height:560px;
}
.tab-pane.active { display:block; }
.tab-layout { display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:18px; align-items:start; }
.intro-box, .form-card, .history-card, .target-card { padding:18px 20px; border-radius:24px; background:#fff; border:1px solid rgba(17,79,149,.08); box-shadow:var(--shadow-soft); }
.target-card { height:520px; display:flex; flex-direction:column; }
.intro-box h3, .form-card h3, .history-card h3, .target-card h3 { margin:0 0 10px; font-size:18px; color:#0d5db8; }
.intro-box p, .form-card p, .history-card p, .target-card p { margin:0; font-size:14px; line-height:1.6; color:#5f7ea5; }
.info-list { display:grid; gap:10px; margin-top:14px; }
.info-item { padding:12px 14px; border-radius:16px; background:#f7fbff; border:1px solid rgba(17,79,149,.08); }
.info-item strong { display:block; color:#184f90; font-size:14px; margin-bottom:4px; }
.info-item span { color:#6381a4; font-size:13px; line-height:1.5; }
.form-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; }
.field, .field-full { display:grid; gap:8px; }
.field-full { grid-column:1 / -1; }
label { font-size:13px; font-weight:900; color:#235790; }
.picker-grid { display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:10px; }
.picker-item { border:1px solid rgba(17,79,149,.12); border-radius:16px; padding:12px 10px; text-align:center; background:#fff; font-size:13px; font-weight:800; color:#20538d; }
.picker-item .swatch { width:30px; height:30px; border-radius:10px; margin:0 auto 8px; }
.inline-note { margin-top:10px; padding:12px 14px; border-radius:16px; background:#fef5e8; border:1px solid rgba(248,116,0,.16); color:#7b5c22; font-size:13px; line-height:1.5; }
.readonly-display { min-height:50px; border:1px solid rgba(17,79,149,.12); border-radius:16px; padding:12px 14px; background:#f5f9ff; display:flex; align-items:center; }
.status-stats { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:12px; margin-top:16px; }
.status-stat { padding:10px 14px; border-radius:18px; border:1px solid rgba(246,170,7,.28); background:linear-gradient(180deg, #fff8df, #ffeeb7); }
.status-stat.good { border-color:rgba(87,186,60,.24); background:linear-gradient(180deg, #eefae9, #dff4d7); }
.status-stat strong { display:block; color:#8a6400; font-size:18px; margin-bottom:4px; }
.status-stat.good strong { color:#246a39; }
.status-stat span { color:#7a6230; font-size:12px; line-height:1.45; display:block; }
.status-stat.good span { color:#3f7b52; }
.actions-row { display:flex; justify-content:space-between; flex-wrap:wrap; margin-top:15px; padding-top:15px; border-top:1px solid rgba(17,79,149,.10); }
.target-layout { display:grid; grid-template-columns:minmax(0, 1fr) 320px; gap:18px; align-items:stretch; }
.compact { min-height:520px; }
.mini-note { margin-top:12px; color:#5f7ea5; font-size:13px; line-height:1.55; }
.hidden { display:none !important; }
.target-list-card { height:520px; display:flex; flex-direction:column; }
.target-list { display:block; max-height:none; overflow:auto; padding-right:6px; flex:1 1 auto; }
.target-detail-card { height:520px; display:flex; flex-direction:column; }
.target-item { margin-bottom:10px; }
.target-copy { display:grid; gap:6px; }
.target-copy .target-tags { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
.target-tags { display:inline-flex; flex-wrap:wrap; gap:8px; align-items:center; }
.mini-tag { display:inline-flex; align-items:center; min-height:24px; padding:0 10px; border-radius:999px; background:#eef5fd; color:#1b5ca0; font-size:11px; font-weight:800; }
.target-item:last-child { margin-bottom:0; }
.target-item { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:12px; align-items:center; padding:12px 14px; border-radius:18px; background:#f8fbff; border:1px solid #dbe8f7; }
.target-item.active { border-color:#5e93d9; box-shadow:0 0 0 3px rgba(88,139,212,.12); background:linear-gradient(180deg,#ffffff 0%,#f3f8fe 100%); }
.target-copy strong { display:block; color:#1c4f8b; font-size:15px; }
.target-copy > span { display:block; color:#607fa6; font-size:13px; margin-top:4px; }
.warning-box { margin-top:14px; padding:14px 16px; border-radius:16px; background:rgba(255,187,77,.18); border:1px solid rgba(246,170,7,.22); color:#6c561a; font-size:13px; line-height:1.55; }
.history-card { height: 520px; display:flex; flex-direction:column; }
.target-card .readonly-grid { margin-top:8px; }
.history-scroll { margin-top:16px; overflow:auto; flex:1 1 auto; }
.history-table { width:100%; border-collapse:separate; border-spacing:0 10px; }
.history-table th { text-align:left; font-size:12px; text-transform:uppercase; letter-spacing:.04em; color:#6a84a2; padding:0 12px 2px; position:sticky; top:0; background:linear-gradient(180deg, rgba(255,255,255,.98), rgba(245,250,255,.98)); z-index:2; }
.history-table td { background:#f8fbff; border-top:1px solid #dce9f8; border-bottom:1px solid #dce9f8; padding:12px; font-size:13px; color:#184f90; vertical-align:top; }
.history-table td:first-child { border-left:1px solid #dce9f8; border-radius:14px 0 0 14px; }
.history-table td:last-child { border-right:1px solid #dce9f8; border-radius:0 14px 14px 0; }
.muted { color:#6a84a2; }
.site-footer { margin-top:24px; padding:24px 0 22px; background:linear-gradient(180deg, rgba(255,255,255,.82), rgba(235,246,255,.92)); border-top:1px solid rgba(170,204,238,.62); border-radius:26px 26px 0 0; box-shadow:0 -10px 24px rgba(35,100,177,.06); }
.footer-grid { width:min(1240px, calc(100% - 30px)); margin:0 auto; display:grid; grid-template-columns:1.3fr 1fr 1fr; gap:22px; }
.footer-col h4 { margin:0 0 8px; font-size:16px; color:#0f4d91; }
.footer-col p { margin:0; color:#5e7ea6; font-size:14px; line-height:1.55; }
.footer-links { display:flex; flex-direction:column; gap:7px; }
.footer-links a { color:#2364a7; text-decoration:none; font-weight:700; font-size:14px; }
.footer-bottom { width:min(1240px, calc(100% - 30px)); margin:18px auto 0; padding-top:14px; border-top:1px solid rgba(170,204,238,.56); color:#6b86aa; font-size:13px; font-weight:700; }
.modal-overlay { position:fixed; inset:0; background:rgba(18,50,88,.34); backdrop-filter:blur(3px); display:none; align-items:center; justify-content:center; padding:24px; z-index:120; }
.modal-overlay.open { display:flex; }
.modal-card { width:min(580px, 100%); background:#fff; border-radius:24px; padding:22px; box-shadow:0 22px 44px rgba(13,56,110,.22); border:1px solid rgba(17,79,149,.1); }
.modal-head { display:flex; justify-content:space-between; gap:16px; align-items:flex-start; margin-bottom:12px; }
.modal-head h3 { margin:0; font-size:20px; color:#0d5db8; }
.modal-close { border:0; background:#eef6ff; color:#0d5db8; width:38px; height:38px; border-radius:999px; cursor:pointer; font-size:20px; font-weight:700; }
.modal-actions { display:flex; justify-content:flex-end; gap:10px; margin-top:16px; }

.subtab-shell { margin-top:4px; }
.subtab-row { display:flex; align-items:flex-end; gap:6px; flex-wrap:wrap; margin:0; }
.subtab-btn {
border:1px solid rgba(140,197,242,1); border-bottom:0; border-radius:16px 16px 0 0;
background:linear-gradient(180deg, rgba(255,255,255,.92), rgba(231,242,255,.92));
color:#235b99; font-weight:900; font-size:13px; padding:0 18px; min-height:25px;
display:inline-flex; align-items:center; justify-content:center; cursor:pointer;
box-shadow:0 -3px 12px rgba(35,100,177,.05);
}
.subtab-btn.active { background:linear-gradient(180deg,#4ea5ff,#1f79dc); color:#fff; border-color:#2f88ea; }
.subtab-pane { display:none; background:rgb(183 222 253); border:1px solid rgb(140 197 242); border-radius:0 22px 22px 22px; padding:18px; box-shadow:var(--shadow-soft); min-height:560px; }
.subtab-pane.active { display:block; }
.warning-box.error { background:rgba(255,143,143,.16); border-color:rgba(223,73,73,.25); color:#a33f3f; }
.btn[disabled] { background:linear-gradient(180deg,#eef2f6,#dde5ee); color:#8ea0b3; cursor:not-allowed; box-shadow:none; }
.target-card.compact, .form-card.compact { height:520px; display:flex; flex-direction:column; }
.scroll-stack { overflow:auto; flex:1 1 auto; padding-right:6px; }
.mini-note { margin-top:10px; font-size:12px; color:#6381a4; line-height:1.45; }

@media (max-width:1100px) {
.header-row { grid-template-columns:1fr; gap:14px; } .brand { justify-self:center; align-items:center; min-width:0; } .welcome-text { margin-left:0; margin-top:-6px; } .header-actions { justify-content:center; } .nav-pills { overflow-x:auto; justify-content:flex-start; padding-bottom:2px; width:100%; }
.selection-grid, .tab-layout, .target-layout { grid-template-columns:1fr; } .footer-grid { grid-template-columns:1fr; gap:24px; } .top-summary { grid-template-columns:repeat(2, minmax(0,1fr)); } .top-summary-two { grid-template-columns:repeat(2, minmax(0,1fr)); }
}
@media (max-width:760px) {
.wrap { width:min(100%, calc(100% - 18px)); } .page-content { padding:18px; } .form-grid, .picker-grid, .top-summary, .top-summary-two { grid-template-columns:1fr; } .overview-item, .target-item { grid-template-columns:1fr; } .readonly-row { grid-template-columns:1fr; } .readonly-row strong { text-align:left; }
.site-footer { padding:20px 18px 16px; } .footer-bottom { justify-content:flex-start; }
}
</style>
</head>
<body>
<header class="header">
<div class="wrap">
<div class="header-row">
<div class="brand">
<div class="brand-logo" aria-label="OefenHub logo" role="img"></div>
<div class="welcome-text">Welkom terug, Noor</div>
</div>

<nav class="nav-pills" aria-label="Hoofdmenu">
<div class="nav-item"><button class="pill orange">Site instellingen</button></div>
<div class="nav-item" id="contentNav">
<button class="pill blue has-chevron" id="contentMenuBtn" aria-expanded="false" aria-haspopup="true">Content <span></span></button>
<div class="dropdown-menu" id="contentMenu">
<div class="menu-list">
<a class="menu-link no-arrow" href="#"><span class="menu-icon blue">C</span><span>Categorieën beheren</span></a>
<a class="menu-link no-arrow is-active" href="#"><span class="menu-icon orange">M</span><span>Modules beheren</span></a>
<a class="menu-link no-arrow" href="#"><span class="menu-icon green">D</span><span>Docent ondersteuning</span></a>
</div>
</div>
</div>
<div class="nav-item"><button class="pill green">Accounts</button></div>
</nav>

<div class="header-actions">
<button class="mail-btn" aria-label="Meldingen"><span class="badge">2</span></button>
<div class="profile-nav nav-item">
<button class="profile-chip" aria-haspopup="true" aria-expanded="false"><span class="avatar">N</span></button>
<div class="dropdown-menu align-right">
<div class="menu-list">
<a class="menu-link" href="#"><span class="menu-icon blue">P</span><span>Profiel</span><span class="menu-arrow"></span></a>
<a class="menu-link" href="#"><span class="menu-icon orange">V</span><span>Voorkeuren</span><span class="menu-arrow"></span></a>
<a class="menu-link" href="#"><span class="menu-icon green">T</span><span>Toegankelijkheid</span><span class="menu-arrow"></span></a>
<a class="menu-link" href="#"><span class="menu-icon blue">M</span><span>Meldingen (2)</span><span class="menu-arrow"></span></a>
<a class="menu-link" href="#"><span class="menu-icon orange">U</span><span>Uitloggen</span><span class="menu-arrow"></span></a>
</div>
</div>
</div>
</div>
</div>
</div>
</header>

<main class="page-shell">
<div class="wrap">
<div class="breadcrumb"><span>Home</span><span class="crumb-sep"></span><span>Content</span><span class="crumb-sep"></span><strong>Modules beheren</strong></div>

<section class="hero-card">
<h1 class="hero-title">Modules beheren</h1>
<p class="hero-text">Deze beheerpagina is gericht op centrale technische modules. Je selecteert eerst een module, bekijkt de belangrijkste readonly gegevens en opent daarna het beheer om beschikbaarheid, migratie of historie te bekijken. Concrete oefenconfiguraties van docenten beheer je hier niet; deze pagina gaat alleen over het beschikbaar stellen en technisch beheren van modules.</p>
</section>

<section class="selection-grid" id="selectionStage">
<div class="panel-card">
<div class="panel-head">
<div>
<h2 class="panel-title">Overzicht</h2>
<p class="panel-copy">Zoek een technische module en selecteer deze om een compact overzicht te bekijken.</p>
</div>
<button class="btn btn-secondary">Nieuwe module</button>
</div>
<div class="toolbar" style="margin-bottom:14px;">
<div class="search-wrap"><input class="search-input" type="text" value="basis" aria-label="Zoek module"/></div>
</div>
<div class="overview-list">
<article class="overview-item">
<div class="overview-main">
<div class="overview-head">
<div class="cat-copy"><strong>Basisrekenen</strong><span>Code: OefenHub.Modules.Math.BasicArithmetic · Versie 2.3.1</span></div>
</div>
<div class="meta-row"><span class="tag blue">Actief</span><span class="tag green">Zichtbaar voor testdocenten</span><span class="tag green">12 actieve docenten</span><span class="tag orange">46 oefenkoppelingen</span></div>
</div>
<button class="btn btn-primary open-manage">Selecteer</button>
</article>
<article class="overview-item">
<div class="overview-main">
<div class="overview-head">
<div class="cat-copy"><strong>Breuken trainer</strong><span>Code: OefenHub.Modules.Math.Fractions · Versie 2.0.0</span></div>
</div>
<div class="meta-row"><span class="tag blue">Actief</span><span class="tag grey">Niet zichtbaar voor testdocenten</span><span class="tag green">8 actieve docenten</span><span class="tag orange">21 oefenkoppelingen</span></div>
</div>
<button class="btn btn-ghost">Selecteer</button>
</article>
<article class="overview-item">
<div class="overview-main">
<div class="overview-head">
<div class="cat-copy"><strong>Rekensprint compact</strong><span>Code: OefenHub.Modules.Math.SpeedDrill · Versie 1.9.1</span></div>
</div>
<div class="meta-row"><span class="tag grey">Inactief</span><span class="tag grey">Niet zichtbaar voor testdocenten</span><span class="tag green">0 actieve docenten</span><span class="tag orange">0 oefenkoppelingen</span></div>
</div>
<button class="btn btn-ghost">Selecteer</button>
</article>
<article class="overview-item">
<div class="overview-main">
<div class="overview-head">
<div class="cat-copy"><strong>Tafels generator</strong><span>Code: OefenHub.Modules.Math.Tables · Versie 1.4.2</span></div>
</div>
<div class="meta-row"><span class="tag blue">Actief</span><span class="tag green">Zichtbaar voor testdocenten</span><span class="tag green">5 actieve docenten</span><span class="tag orange">13 oefenkoppelingen</span></div>
</div>
<button class="btn btn-ghost">Selecteer</button>
</article>
</div>
</div>

<aside class="panel-card">
<div class="panel-head" style="margin-bottom:10px;">
<div>
<h2 class="panel-title">Geselecteerde module</h2>
<p class="panel-copy">Compact readonly overzicht. Voor inhoudelijk beheer open je daarna de beheerweergave.</p>
</div>
</div>
<div class="readonly-grid">
<div class="readonly-row"><span>Weergave naam</span><strong>Basisrekenen</strong></div>
<div class="readonly-row"><span>Versie</span><strong>2.3.1</strong></div>
<div class="readonly-row"><span>Status</span><strong>Actief</strong></div>
<div class="readonly-row"><span>Zichtbaar voor testdocenten</span><strong>Ja</strong></div>
<div class="readonly-row"><span>Actieve docenten</span><strong>12</strong></div>
<div class="readonly-row"><span>Actieve oefenkoppelingen</span><strong>46</strong></div>
<div class="readonly-row"><span>Aangemaakt door</span><strong>Naomi Beheerder · 14-01-2026</strong></div>
<div class="readonly-row"><span>Laatst gewijzigd</span><strong>Tom Beheerder · 03-04-2026</strong></div>
</div>
<div class="quick-history">
<h3>Recente wijzigingen (laatste 60 dagen)</h3>
<div class="history-mini-item"><strong>Versie bijgewerkt</strong><span>03-04-2026 · door Tom Beheerder</span></div>
<div class="history-mini-item"><strong>Testzichtbaarheid aangepast</strong><span>17-03-2026 · door Naomi Beheerder</span></div>
</div>
<div class="actions-row" style="border-top:0; padding-top:16px; margin-top:6px; justify-content:center;">
<button class="btn btn-primary open-manage">Open beheer</button>
</div>
</aside>
</section>

<section class="manage-stage" id="manageStage">
<div class="tabs-card">
<div class="manage-head">
<h2 class="panel-title" style="margin:0;font-size:20px;color:#0f4d91;">Modulebeheer - Basisrekenen V2.3.1</h2>
<button class="btn btn-danger manage-return" id="closeManage">Terug naar overzicht</button>
</div>

<div class="tab-row">
<button class="tab-btn active" data-tab="intro">Intro / uitleg</button>
<button class="tab-btn" data-tab="module">Module</button>
<button class="tab-btn" data-tab="migreren-docent">Migreren - docent</button>
<button class="tab-btn" data-tab="migreren-alles">Migreren - alles</button>
<button class="tab-btn" data-tab="geschiedenis">Geschiedenis</button>
</div>

<div class="tab-pane active" id="tab-intro">
<div class="tab-layout">
<div class="intro-box">
<h3>Wat kun je hier doen?</h3>
<p>Gebruik deze tabs om de geselecteerde technische module te beheren. In <strong>Module</strong> bekijk je de module-identiteit, beschikbaarheid en testzichtbaarheid. In <strong>Migreren - docent</strong> zet je alleen oefeningen van één geselecteerde docent over. In <strong>Migreren - alles</strong> voer je een globale migratie uit voor alle gekoppelde oefeningen. In <strong>Geschiedenis</strong> zie je alle acties op moduleniveau.</p>
<div class="info-list">
<div class="info-item"><strong>Status van de hele module</strong><span>Het uitschakelen van een module is een technische ingreep. Doe dit pas wanneer er geen actieve koppelingen meer bestaan.</span></div>
<div class="info-item"><strong>Testzichtbaarheid staat hier los van</strong><span>De instelling ‘zichtbaar voor testdocenten’ kan los worden aangepast zonder de hele module uit te schakelen.</span></div>
<div class="info-item"><strong>Gescheiden migraties</strong><span>Docentgerichte migraties en globale migraties zijn bewust gescheiden om impact en risico duidelijk te houden.</span></div>
</div>
</div>
<aside class="side-card" style="padding:18px 20px;">
<h2 class="panel-title" style="font-size:18px;">Gebruik & impact</h2>
<div class="top-summary top-summary-two">
<div class="summary-box"><strong>12</strong><span>Actieve docenten</span></div>
<div class="summary-box"><strong>46</strong><span>Actieve oefenkoppelingen</span></div>
</div>
<div class="meta-card-list">
<div class="meta-card"><strong>Actieve docentniveaus</strong><span>18 niveaus gebruiken deze module via actieve oefenkoppelingen</span></div>
<div class="meta-card"><strong>Afgeronde runs (90 dagen)</strong><span>284 afgeronde runs en 7 nog openstaande runs verwijzen naar deze module</span></div>
</div>
</aside>
</div>
</div>

<div class="tab-pane" id="tab-module">
<div class="tab-layout">
<div class="form-card">
<h3>Modulegegevens</h3>
<p>Hier beheer je de centrale technische module-identiteit en beschikbaarheid voor docenten. Dit scherm gaat niet over docentgebonden oefenconfiguraties.</p>
<div class="form-grid" style="margin-top:16px;">
<div class="field"><label>Weergave naam</label><input class="text-input" type="text" value="Basisrekenen"/></div>
<div class="field"><label>Versie</label><input class="text-input" type="text" value="2.3.1"/></div>
<div class="field-full"><label>Code reference</label><input class="text-input" type="text" value="OefenHub.Modules.Math.BasicArithmetic"/></div>
<div class="field"><label>Huidige status</label><div class="target-tags"><span class="tag blue">Actief</span></div></div>
<div class="field"><label>Zichtbaar voor testdocenten</label><div class="target-tags"><span class="tag green">Ja</span></div></div>
</div>
<div class="actions-row">
<button class="btn btn-secondary" id="toggleTestVisibility">Maak onzichtbaar voor testdocenten</button>
<button class="btn btn-primary" id="openSaveModal">Opslaan</button>
</div>
<div class="inline-note">De zichtbaarheid voor testdocenten staat los van het uitschakelen van de hele module. Het aanpassen van deze testinstelling mag dus ook wanneer er nog actieve koppelingen bestaan.</div>
<div class="actions-row" style="justify-content:center;">
<button class="btn btn-danger" id="openStatusModal">Module uitschakelen</button>
</div>
</div>
<aside class="side-card" style="padding:18px 20px;">
<h2 class="panel-title" style="font-size:18px;">Gebruik &amp; impact</h2>
<div class="status-stats">
<div class="status-stat"><strong>12</strong><span>Actieve docenten gebruiken deze module</span></div>
<div class="status-stat"><strong>46</strong><span>Actieve oefenkoppelingen aanwezig</span></div>
<div class="status-stat"><strong>18</strong><span>Actieve docentniveaus gebruiken via gekoppelde oefeningen deze module</span></div>
<div class="status-stat"><strong>7</strong><span>Niet-afgeronde runs verwijzen momenteel nog naar deze module</span></div>
</div>
<div class="inline-note">De knop om deze module uit te schakelen wordt pas functioneel toegestaan wanneer actieve docentkoppelingen en actieve oefenkoppelingen beide op <strong>0</strong> staan. De instelling <strong>zichtbaar voor testdocenten</strong> mag daar los van worden aangepast.</div>
</aside>
</div>
</div>

<div class="tab-pane" id="tab-migreren-docent">
<div class="subtab-shell">
<div class="subtab-row">
<button class="subtab-btn active" data-subtab="step1-module">Stap 1 - Module</button>
<button class="subtab-btn" data-subtab="step2-docent">Stap 2 - Docent</button>
</div>

<div class="subtab-pane active" id="subtab-step1-module">
<div class="target-layout">
<div class="form-card compact" style="display:flex; flex-direction:column;">
<h3>Selecteer eerst een doelmodule</h3>
<p>Zoek en selecteer een actieve doelmodule. Deze keuze wordt daarna meegenomen naar stap 2, waar je alleen nog zoekt binnen docenten die de huidige bronmodule daadwerkelijk gebruiken.</p>
<div style="margin:16px 0 14px;"><input class="search-input" type="text" placeholder="Zoek actieve doelmodule" aria-label="Zoek doelmodule voor docentmigratie"/></div>
<div class="scroll-stack" style="flex:1 1 auto; min-height:0;">
<div class="target-list">
<div class="target-item active">
<div class="target-copy"><strong>Basisrekenen next</strong><div class="target-tags"><span class="tag blue">Versie 3.0.0</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Basisrekenen compact</strong><div class="target-tags"><span class="tag blue">Versie 2.9.4</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Rekenmix modern</strong><div class="target-tags"><span class="tag blue">Versie 1.1.0</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Getallenlijn trainer</strong><div class="target-tags"><span class="tag blue">Versie 1.8.2</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
</div>
</div>
</div>
<aside class="target-card compact" style="display:flex; flex-direction:column;">
<h3>Geselecteerde doelmodule</h3>
<div class="readonly-grid" style="margin-top:8px;">
<div class="readonly-row"><span>Bronmodule</span><strong>Basisrekenen V2.3.1</strong></div>
<div class="readonly-row"><span>Doelmodule</span><strong id="teacherTargetPreview">Nog niet bevestigd</strong></div>
<div class="readonly-row"><span>Actieve docenten</span><strong>12</strong></div>
<div class="readonly-row"><span>Actieve oefenkoppelingen</span><strong>46</strong></div>
</div>
<div class="warning-box">Kies hier eerst de doelmodule die je in stap 2 wilt gebruiken voor een docentgerichte migratie.</div>
<div class="actions-row" style="justify-content:center; margin-top:auto;">
<button class="btn btn-primary" id="selectTargetForTeacher">Selecteer deze module<br/>en ga naar stap 2</button>
</div>
</aside>
</div>
</div>

<div class="subtab-pane" id="subtab-step2-docent">
<div class="target-layout">
<div class="form-card compact" style="display:flex; flex-direction:column;">
<h3>Zoek docent binnen relevante docenten</h3>
<p>Zoek alleen binnen docenten die minimaal één concrete oefening hebben die op de huidige bronmodule draait. Daardoor blijft de lijst beperkt tot docenten waarvoor deze migratie zinvol is.</p>
<div style="margin:16px 0 14px;"><input class="search-input" type="text" value="Marieke Jansen" aria-label="Zoek docent voor modulemigratie"/></div>
<div class="scroll-stack" style="flex:1 1 auto; min-height:0;">
<div class="target-list">
<div class="target-item active">
<div class="target-copy"><strong>Marieke Jansen</strong><div class="target-tags"><span class="tag green">3 docentniveaus</span><span class="tag orange">14 oefenkoppelingen</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Rachid de Boer</strong><div class="target-tags"><span class="tag green">2 docentniveaus</span><span class="tag orange">6 oefenkoppelingen</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Sanne van Dijk</strong><div class="target-tags"><span class="tag green">4 docentniveaus</span><span class="tag orange">11 oefenkoppelingen</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
</div>
</div>
</div>
<aside class="target-card compact">
<h3>Geselecteerde docent</h3>
<div class="warning-box error" id="teacherStepWarning">Selecteer eerst in stap 1 een doelmodule voordat je een docentmigratie kunt uitvoeren.</div>
<div class="readonly-grid" style="margin-top:8px;">
<div class="readonly-row"><span>Bronmodule</span><strong>Basisrekenen V2.3.1</strong></div>
<div class="readonly-row"><span>Doelmodule</span><strong id="teacherTargetName">Nog niet geselecteerd</strong></div>
<div class="readonly-row"><span>Docent</span><strong>Marieke Jansen</strong></div>
<div class="readonly-row"><span>Te migreren koppelingen</span><strong>14 oefeningen</strong></div>
</div>
<div class="warning-box hidden" id="teacherImpactWarning">Historische runs blijven historisch herleidbaar. Alleen actieve oefenkoppelingen van de geselecteerde docent worden overgezet naar de gekozen doelmodule.</div>
<div class="actions-row" style="justify-content:center;">
<button class="btn btn-primary" id="openMigrateTeacherModal" disabled>Migreer voor docent</button>
</div>
</aside>
</div>
</div>
</div>
</div>

<div class="tab-pane" id="tab-migreren-alles">
<div class="target-layout">
<div class="form-card target-list-card">
<h3>Migreren - alles</h3>
<p>Zoek en selecteer een actieve doelmodule. Deze migratie zet alle actieve oefenkoppelingen van de huidige bronmodule over.</p>
<div style="margin:16px 0 14px;"><input class="search-input" type="text" placeholder="Zoek actieve doelmodule" aria-label="Zoek doelmodule"/></div>
<div class="target-list">
<div class="target-item active">
<div class="target-copy"><strong>Basisrekenen next</strong><div class="target-tags"><span class="tag blue">Versie 3.0.0</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Basisrekenen compact</strong><div class="target-tags"><span class="tag blue">Versie 2.9.4</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Rekenmix modern</strong><div class="target-tags"><span class="tag blue">Versie 1.1.0</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
<div class="target-item">
<div class="target-copy"><strong>Getallenlijn trainer</strong><div class="target-tags"><span class="tag blue">Versie 1.8.2</span><span class="tag green">Actief</span></div></div>
<button class="btn btn-ghost">Selecteer</button>
</div>
</div>
</div>
<aside class="target-card">
<h3>Geselecteerde globale migratie</h3>
<div class="readonly-grid" style="margin-top:8px;">
<div class="readonly-row"><span>Bronmodule</span><strong>Basisrekenen V2.3.1</strong></div>
<div class="readonly-row"><span>Doelmodule</span><strong>Basisrekenen next V3.0.0</strong></div>
<div class="readonly-row"><span>Docenten geraakt</span><strong>12</strong></div>
<div class="readonly-row"><span>Te migreren koppelingen</span><strong>46 oefeningen</strong></div>
</div>
<div class="warning-box">Deze actie migreert alle actieve oefenkoppelingen van de bronmodule naar de gekozen doelmodule. Historische runs en resultaten blijven historisch herleidbaar.</div>
<div class="actions-row" style="justify-content:center;">
<button class="btn btn-primary" id="openMigrateAllModal">Migreer alles</button>
</div>
</aside>
</div>
</div>

<div class="tab-pane" id="tab-geschiedenis">
<div class="history-card">
<h3>Geschiedenis van deze module</h3>
<p>Alle acties worden op moduleniveau gelogd. Migraties verschijnen dus als gewone geschiedenisregels binnen deze module, naast activatie, testzichtbaarheid en versiebeheer.</p>
<div class="history-scroll">
<table class="history-table">
<thead>
<tr><th>Datum</th><th>Actie</th><th>Details</th><th>Door</th><th>Reden</th></tr>
</thead>
<tbody>
<tr><td>03-04-2026 14:22</td><td>Versie bijgewerkt</td><td>Van 2.3.0 naar 2.3.1</td><td>Tom Beheerder</td><td>Bugfix release na supportmelding</td></tr>
<tr><td>17-03-2026 09:11</td><td>Testzichtbaarheid gewijzigd</td><td>Module zichtbaar gemaakt voor testdocenten</td><td>Naomi Beheerder</td><td>Voorbereiding acceptatietest</td></tr>
<tr><td>10-02-2026 16:42</td><td>Globale migratie uitgevoerd</td><td>46 actieve oefenkoppelingen overgezet van Basisrekenen v2.2 naar Basisrekenen v2.3</td><td>Kim Beheerder</td><td>Verouderde moduleversie uitfaseren</td></tr>
<tr><td>14-01-2026 11:08</td><td>Aangemaakt</td><td>Technische module aangemaakt en beschikbaar gesteld voor docenten</td><td>Naomi Beheerder</td><td>Initiële module-inrichting</td></tr>
<tr><td>11-01-2026 09:17</td><td>Docentmigratie uitgevoerd</td><td>14 oefenkoppelingen van docent Marieke Jansen overgezet naar Breuken trainer 2.0</td><td>Tom Beheerder</td><td>Gerichte migratie na supportverzoek</td></tr>
<tr><td>08-01-2026 13:05</td><td>Statuswijziging geblokkeerd</td><td>Module kon niet inactief worden gezet omdat nog 46 actieve oefenkoppelingen bestaan</td><td>Kim Beheerder</td><td>Controle op actieve koppelingen</td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</div>

</main>

<footer class="site-footer">
<div class="footer-grid">
<div class="footer-col"><h4>OefenHub Beheer</h4><p>Beheer technische modules en migraties vanuit één overzichtelijke omgeving.</p></div>
<div class="footer-col"><h4>Snelle toegang</h4><div class="footer-links"><a href="#">Content</a><a href="#">Site instellingen</a><a href="#">Accounts</a></div></div>
<div class="footer-col"><h4>Ondersteuning</h4><div class="footer-links"><a href="#">Privacybeleid</a><a href="#">Contact</a><a href="#">Uitloggen</a></div></div>
</div>
<div class="footer-bottom">© 2026 OefenHub</div>
</footer>

<div class="modal-overlay" id="saveModal">
<div class="modal-card">
<div class="modal-head"><h3>Wijzigingen opslaan</h3><button class="modal-close" data-close="saveModal">×</button></div>
<p>Weet je zeker dat je de wijzigingen voor <strong>Basisrekenen V2.3.1</strong> wilt doorvoeren? Geef hieronder de reden van wijziging op.</p>
<label>Reden van wijziging</label>
<textarea class="text-input" style="min-height:120px; margin-top:8px;">Versie- en zichtbaarheidinformatie van de module bijgewerkt.</textarea>
<div class="modal-actions"><button class="btn btn-secondary" data-close="saveModal">Annuleren</button><button class="btn btn-primary" data-close="saveModal">Bevestig opslaan</button></div>
</div>
</div>

<div class="modal-overlay" id="migrateModal">
<div class="modal-card">
<div class="modal-head"><h3>Module migreren</h3><button class="modal-close" data-close="migrateModal">×</button></div>
<p>Weet je zeker dat je <strong>Basisrekenen V2.3.1</strong> wilt migreren? Geef hieronder de reden op zodat deze actie volledig auditbaar blijft.</p>
<label>Reden van migratie</label>
<textarea class="text-input" style="min-height:120px; margin-top:8px;">Verouderde moduleversie gecontroleerd uitfaseren en bestaande koppelingen overzetten.</textarea>
<div class="modal-actions"><button class="btn btn-secondary" data-close="migrateModal">Annuleren</button><button class="btn btn-primary" data-close="migrateModal">Bevestig migratie</button></div>
</div>
</div>

<div class="modal-overlay" id="statusModal">
<div class="modal-card">
<div class="modal-head"><h3>Module uitschakelen niet beschikbaar</h3><button class="modal-close" data-close="statusModal">×</button></div>
<p>Deze module heeft nog actieve oefenkoppelingen. Migreer of ontkoppel eerst alle actieve oefeningen voordat je de module naar <strong>inactief</strong> kunt wijzigen.</p>
<div class="modal-actions"><button class="btn btn-primary" data-close="statusModal">Sluiten</button></div>
</div>
</div>

<script>
const contentNav = document.getElementById('contentNav');
const contentBtn = document.getElementById('contentMenuBtn');
contentBtn.addEventListener('click', (e) => { e.stopPropagation(); contentNav.classList.toggle('open'); contentBtn.setAttribute('aria-expanded', contentNav.classList.contains('open')); });
document.addEventListener('click', (e) => { if (!contentNav.contains(e.target)) { contentNav.classList.remove('open'); contentBtn.setAttribute('aria-expanded', 'false'); } });

const selectionStage = document.getElementById('selectionStage');
const manageStage = document.getElementById('manageStage');
document.querySelectorAll('.open-manage').forEach(btn => btn.addEventListener('click', () => { selectionStage.style.display='none'; manageStage.classList.add('open'); }));
document.getElementById('closeManage').addEventListener('click', () => { manageStage.classList.remove('open'); selectionStage.style.display='grid'; window.scrollTo({top:0, behavior:'smooth'}); });

const tabButtons = document.querySelectorAll('.tab-btn');
const tabPanes = document.querySelectorAll('.tab-pane');
tabButtons.forEach(btn => btn.addEventListener('click', () => {
tabButtons.forEach(b => b.classList.remove('active'));
tabPanes.forEach(p => p.classList.remove('active'));
btn.classList.add('active');
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
}));

const subtabButtons = document.querySelectorAll('.subtab-btn');
const subtabPanes = document.querySelectorAll('.subtab-pane');
subtabButtons.forEach(btn => btn.addEventListener('click', () => {
subtabButtons.forEach(b => b.classList.remove('active'));
subtabPanes.forEach(p => p.classList.remove('active'));
btn.classList.add('active');
document.getElementById('subtab-' + btn.dataset.subtab).classList.add('active');
if (btn.dataset.subtab === 'step2-docent' && !teacherTargetSelected) {
teacherStepWarning.classList.remove('hidden');
teacherImpactWarning.classList.add('hidden');
migrateTeacherBtn.disabled = true;
}
}));

let teacherTargetSelected = false;
const teacherTargetName = document.getElementById('teacherTargetName');
const teacherTargetPreview = document.getElementById('teacherTargetPreview');
const teacherStepWarning = document.getElementById('teacherStepWarning');
const teacherImpactWarning = document.getElementById('teacherImpactWarning');
const migrateTeacherBtn = document.getElementById('openMigrateTeacherModal');

document.getElementById('selectTargetForTeacher').addEventListener('click', () => {
teacherTargetSelected = true;
teacherTargetName.textContent = 'Basisrekenen next V3.0.0';
teacherTargetPreview.textContent = 'Basisrekenen next V3.0.0';
teacherStepWarning.classList.add('hidden');
teacherImpactWarning.classList.remove('hidden');
migrateTeacherBtn.disabled = false;
document.querySelectorAll('.subtab-btn').forEach(b => b.classList.remove('active'));
document.querySelector('[data-subtab="step2-docent"]').classList.add('active');
document.querySelectorAll('.subtab-pane').forEach(p => p.classList.remove('active'));
document.getElementById('subtab-step2-docent').classList.add('active');
});

const openModal = id => document.getElementById(id).classList.add('open');
const closeModal = id => document.getElementById(id).classList.remove('open');
document.getElementById('openSaveModal').addEventListener('click', () => openModal('saveModal'));
document.getElementById('toggleTestVisibility').addEventListener('click', () => openModal('saveModal'));
document.getElementById('openMigrateTeacherModal').addEventListener('click', () => { if (!migrateTeacherBtn.disabled) openModal('migrateModal'); });
document.getElementById('openMigrateAllModal').addEventListener('click', () => openModal('migrateModal'));
document.getElementById('openStatusModal').addEventListener('click', () => openModal('statusModal'));
document.querySelectorAll('[data-close]').forEach(btn => btn.addEventListener('click', () => closeModal(btn.dataset.close)));
document.querySelectorAll('.modal-overlay').forEach(overlay => overlay.addEventListener('click', e => { if (e.target === overlay) overlay.classList.remove('open'); }));
</script>
</body>
</html>