Feat: milestones under well visit, standalone schedule tabs, remove admin models
- Move Milestones from standalone tab to well visit subtab (wv-panel-milestones) with 'Copy to Note' button that fills Developmental Assessment card in Visit Note - Sidebar Milestones button now navigates to Well Visit → Milestones subtab - Move Full Vaccine Schedule → standalone sidebar tab (vaxschedule-tab) - Move Catch-Up Schedule → standalone sidebar tab (catchup-tab) - Add Developmental Assessment textarea (wv-milestones-text) to Visit Note panel - Remove AI Models management from admin panel (was failing to load) - switchSubtab scoped to wellvisit-tab so standalone schedule panels unaffected - Expose window.wvSwitchSubtab for cross-module subtab switching
This commit is contained in:
parent
bfa832713d
commit
90c7bc35af
5 changed files with 136 additions and 197 deletions
|
|
@ -174,7 +174,7 @@
|
|||
<span>SOAP Note</span>
|
||||
</button>
|
||||
<span class="sidebar-section-label">Pediatric</span>
|
||||
<button class="tab-btn" data-tab="milestones">
|
||||
<button class="tab-btn" data-tab="wellvisit" data-subtab="milestones">
|
||||
<i class="fas fa-baby"></i>
|
||||
<span>Milestones</span>
|
||||
</button>
|
||||
|
|
@ -182,6 +182,14 @@
|
|||
<i class="fas fa-calendar-check"></i>
|
||||
<span>Well Visit</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="vaxschedule">
|
||||
<i class="fas fa-table"></i>
|
||||
<span>Vaccine Schedule</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="catchup">
|
||||
<i class="fas fa-rotate"></i>
|
||||
<span>Catch-Up Schedule</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="sickvisit">
|
||||
<i class="fas fa-thermometer-half"></i>
|
||||
<span>Sick Visit</span>
|
||||
|
|
@ -708,87 +716,25 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ===== TAB: MILESTONES ===== -->
|
||||
<section id="milestones-tab" class="tab-content">
|
||||
<!-- ===== TAB: VACCINE SCHEDULE ===== -->
|
||||
<section id="vaxschedule-tab" class="tab-content">
|
||||
<div class="module-header">
|
||||
<h2><i class="fas fa-baby"></i> Developmental Milestones</h2>
|
||||
<p>AAP & Nelson — Click to assess. Blank = not assessed (omitted).</p>
|
||||
<h2><i class="fas fa-table"></i> Full Vaccine Schedule</h2>
|
||||
<p>AAP/ACIP 2025 — Complete immunization schedule for 0–18 years</p>
|
||||
</div>
|
||||
|
||||
<div class="demographics-bar">
|
||||
<div class="demo-field"><label>Patient Age</label><input type="text" id="ms-age" placeholder="e.g., 9 months"></div>
|
||||
<div class="demo-field"><label>Gender</label><select id="ms-gender"><option value="">Select</option><option>Male</option><option>Female</option></select></div>
|
||||
<div class="demo-field">
|
||||
<label>Age Group</label>
|
||||
<select id="ms-age-group">
|
||||
<option value="">-- Select --</option>
|
||||
<option value="2 months">2 Months</option>
|
||||
<option value="4 months">4 Months</option>
|
||||
<option value="6 months">6 Months</option>
|
||||
<option value="9 months">9 Months</option>
|
||||
<option value="12 months">12 Months</option>
|
||||
<option value="15 months">15 Months</option>
|
||||
<option value="18 months">18 Months</option>
|
||||
<option value="24 months">2 Years</option>
|
||||
<option value="30 months">2.5 Years</option>
|
||||
<option value="36 months">3 Years</option>
|
||||
<option value="48 months">4 Years</option>
|
||||
<option value="60 months">5 Years</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="demo-field">
|
||||
<label>Output Format</label>
|
||||
<select id="ms-format">
|
||||
<option value="narrative">Narrative (paragraphs)</option>
|
||||
<option value="list">Structured List</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="demo-field demo-field-model">
|
||||
<label><i class="fas fa-robot"></i> Model</label>
|
||||
<select class="tab-model-select"></select>
|
||||
</div>
|
||||
<div id="wv-panel-schedule">
|
||||
<p class="wv-loading">Loading schedule...</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="legend">
|
||||
<div class="legend-item"><span class="legend-icon legend-yes">✓</span> Achieved</div>
|
||||
<div class="legend-item"><span class="legend-icon legend-no">✗</span> Not Achieved</div>
|
||||
<div class="legend-item"><span class="legend-icon legend-blank">—</span> Not Assessed (omitted)</div>
|
||||
<!-- ===== TAB: CATCH-UP SCHEDULE ===== -->
|
||||
<section id="catchup-tab" class="tab-content">
|
||||
<div class="module-header">
|
||||
<h2><i class="fas fa-rotate"></i> Catch-Up Schedule</h2>
|
||||
<p>ACIP catch-up immunization schedule for persons aged 4 months–18 years</p>
|
||||
</div>
|
||||
|
||||
<div id="milestone-checklist"></div>
|
||||
|
||||
<div class="milestone-actions" id="milestone-actions" style="display:none">
|
||||
<button id="ms-all-yes" class="btn-sm btn-success"><i class="fas fa-check-double"></i> All Yes</button>
|
||||
<button id="ms-all-clear" class="btn-sm btn-ghost"><i class="fas fa-eraser"></i> Clear All</button>
|
||||
<button id="ms-generate-btn" class="btn-generate btn-generate-teal"><i class="fas fa-wand-magic-sparkles"></i> Generate Narrative</button>
|
||||
</div>
|
||||
|
||||
<div id="ms-output" class="card output-card hidden">
|
||||
<div class="card-header output-header">
|
||||
<h3><i class="fas fa-file-medical"></i> Developmental Assessment</h3>
|
||||
<div class="output-actions">
|
||||
<span id="ms-model-tag" class="model-tag"></span>
|
||||
<button class="btn-sm btn-primary" onclick="copyText('ms-narrative-text')"><i class="fas fa-copy"></i> Copy</button>
|
||||
<button class="btn-sm btn-ghost" onclick="speakText('ms-narrative-text')"><i class="fas fa-volume-high"></i> Read</button>
|
||||
<button class="btn-sm btn-ghost" onclick="exportToNextcloud('ms-narrative-text','milestones')"><i class="fas fa-cloud-arrow-up"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ms-summary-bar" class="summary-bar hidden"></div>
|
||||
<div id="ms-narrative-text" class="output-text" contenteditable="true"></div>
|
||||
<div class="summary-section">
|
||||
<div class="summary-section-header">
|
||||
<button id="ms-quick-summary-btn" class="btn-generate-summary"><i class="fas fa-compress"></i> 3-Sentence Summary</button>
|
||||
</div>
|
||||
<div id="ms-quick-summary" class="hidden">
|
||||
<div class="card-header summary-output-header">
|
||||
<h3><i class="fas fa-clipboard-list"></i> Quick Summary</h3>
|
||||
<div class="output-actions">
|
||||
<button class="btn-sm btn-primary" onclick="copyText('ms-summary-text')"><i class="fas fa-copy"></i> Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ms-summary-text" class="summary-output-text" contenteditable="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wv-panel-catchup">
|
||||
<p class="wv-loading">Loading catch-up schedule...</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -977,19 +923,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── CMS: Models Management ─────────────────────────────────── -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-microchip"></i> AI Models</h3>
|
||||
<button id="btn-add-custom-model" class="btn-sm btn-ghost"><i class="fas fa-plus"></i> Add Custom</button>
|
||||
</div>
|
||||
<div style="padding:16px;display:flex;flex-direction:column;gap:10px;">
|
||||
<div id="cms-models-list" style="display:flex;flex-direction:column;gap:6px;">
|
||||
<p style="color:var(--g400);font-size:13px;">Loading models...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── CMS: Saved Encounters (Admin View) ─────────────────────── -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
|
|
@ -1036,11 +969,8 @@
|
|||
<button class="wv-subtab-btn active" data-subtab="byvisit">
|
||||
<i class="fas fa-child"></i> By Visit Age
|
||||
</button>
|
||||
<button class="wv-subtab-btn" data-subtab="schedule">
|
||||
<i class="fas fa-table"></i> Full Vaccine Schedule
|
||||
</button>
|
||||
<button class="wv-subtab-btn" data-subtab="catchup">
|
||||
<i class="fas fa-rotate"></i> Catch-Up Schedule
|
||||
<button class="wv-subtab-btn" data-subtab="milestones">
|
||||
<i class="fas fa-baby"></i> Milestones
|
||||
</button>
|
||||
<button class="wv-subtab-btn" data-subtab="shadess" style="display:none;">
|
||||
<i class="fas fa-brain"></i> SSHADESS (12+)
|
||||
|
|
@ -1061,14 +991,86 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Full Vaccine Schedule sub-panel -->
|
||||
<div id="wv-panel-schedule" class="wv-subpanel hidden">
|
||||
<p class="wv-loading">Loading schedule...</p>
|
||||
</div>
|
||||
<!-- Milestones sub-panel -->
|
||||
<div id="wv-panel-milestones" class="wv-subpanel hidden">
|
||||
|
||||
<div class="demographics-bar">
|
||||
<div class="demo-field"><label>Patient Age</label><input type="text" id="ms-age" placeholder="e.g., 9 months"></div>
|
||||
<div class="demo-field"><label>Gender</label><select id="ms-gender"><option value="">Select</option><option>Male</option><option>Female</option></select></div>
|
||||
<div class="demo-field">
|
||||
<label>Age Group</label>
|
||||
<select id="ms-age-group">
|
||||
<option value="">-- Select --</option>
|
||||
<option value="2 months">2 Months</option>
|
||||
<option value="4 months">4 Months</option>
|
||||
<option value="6 months">6 Months</option>
|
||||
<option value="9 months">9 Months</option>
|
||||
<option value="12 months">12 Months</option>
|
||||
<option value="15 months">15 Months</option>
|
||||
<option value="18 months">18 Months</option>
|
||||
<option value="24 months">2 Years</option>
|
||||
<option value="30 months">2.5 Years</option>
|
||||
<option value="36 months">3 Years</option>
|
||||
<option value="48 months">4 Years</option>
|
||||
<option value="60 months">5 Years</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="demo-field">
|
||||
<label>Output Format</label>
|
||||
<select id="ms-format">
|
||||
<option value="narrative">Narrative (paragraphs)</option>
|
||||
<option value="list">Structured List</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="demo-field demo-field-model">
|
||||
<label><i class="fas fa-robot"></i> Model</label>
|
||||
<select class="tab-model-select"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legend">
|
||||
<div class="legend-item"><span class="legend-icon legend-yes">✓</span> Achieved</div>
|
||||
<div class="legend-item"><span class="legend-icon legend-no">✗</span> Not Achieved</div>
|
||||
<div class="legend-item"><span class="legend-icon legend-blank">—</span> Not Assessed (omitted)</div>
|
||||
</div>
|
||||
|
||||
<div id="milestone-checklist"></div>
|
||||
|
||||
<div class="milestone-actions" id="milestone-actions" style="display:none">
|
||||
<button id="ms-all-yes" class="btn-sm btn-success"><i class="fas fa-check-double"></i> All Yes</button>
|
||||
<button id="ms-all-clear" class="btn-sm btn-ghost"><i class="fas fa-eraser"></i> Clear All</button>
|
||||
<button id="ms-generate-btn" class="btn-generate btn-generate-teal"><i class="fas fa-wand-magic-sparkles"></i> Generate Narrative</button>
|
||||
</div>
|
||||
|
||||
<div id="ms-output" class="card output-card hidden">
|
||||
<div class="card-header output-header">
|
||||
<h3><i class="fas fa-file-medical"></i> Developmental Assessment</h3>
|
||||
<div class="output-actions">
|
||||
<span id="ms-model-tag" class="model-tag"></span>
|
||||
<button class="btn-sm btn-primary" onclick="copyText('ms-narrative-text')"><i class="fas fa-copy"></i> Copy</button>
|
||||
<button class="btn-sm btn-success" id="btn-ms-copy-to-note"><i class="fas fa-clipboard-check"></i> Copy to Note</button>
|
||||
<button class="btn-sm btn-ghost" onclick="speakText('ms-narrative-text')"><i class="fas fa-volume-high"></i> Read</button>
|
||||
<button class="btn-sm btn-ghost" onclick="exportToNextcloud('ms-narrative-text','milestones')"><i class="fas fa-cloud-arrow-up"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ms-summary-bar" class="summary-bar hidden"></div>
|
||||
<div id="ms-narrative-text" class="output-text" contenteditable="true"></div>
|
||||
<div class="summary-section">
|
||||
<div class="summary-section-header">
|
||||
<button id="ms-quick-summary-btn" class="btn-generate-summary"><i class="fas fa-compress"></i> 3-Sentence Summary</button>
|
||||
</div>
|
||||
<div id="ms-quick-summary" class="hidden">
|
||||
<div class="card-header summary-output-header">
|
||||
<h3><i class="fas fa-clipboard-list"></i> Quick Summary</h3>
|
||||
<div class="output-actions">
|
||||
<button class="btn-sm btn-primary" onclick="copyText('ms-summary-text')"><i class="fas fa-copy"></i> Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ms-summary-text" class="summary-output-text" contenteditable="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Catch-Up Schedule sub-panel -->
|
||||
<div id="wv-panel-catchup" class="wv-subpanel hidden">
|
||||
<p class="wv-loading">Loading catch-up schedule...</p>
|
||||
</div>
|
||||
|
||||
<!-- SSHADESS sub-panel (age 12+) -->
|
||||
|
|
@ -1199,6 +1201,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Milestones carry-over -->
|
||||
<div class="card" style="margin-bottom:10px;" id="wv-milestones-card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-baby"></i> Developmental Assessment</h3>
|
||||
<span style="font-size:12px;color:var(--g500);">From Milestones tab</span>
|
||||
</div>
|
||||
<div style="padding:8px 16px;">
|
||||
<textarea id="wv-milestones-text" rows="3" style="width:100%;font-size:12px;padding:8px;border:1px solid var(--g300);border-radius:6px;resize:vertical;box-sizing:border-box;" placeholder="Developmental assessment auto-fills when you click 'Copy to Note' on Milestones tab..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ROS Card -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
|
||||
|
|
|
|||
|
|
@ -257,7 +257,6 @@
|
|||
if (e.target.closest('#btn-reset-prompt')) resetPrompt();
|
||||
if (e.target.closest('#btn-save-smtp')) saveSmtp();
|
||||
if (e.target.closest('#btn-clear-smtp')) clearSmtp();
|
||||
if (e.target.closest('#btn-add-custom-model')) addCustomModel();
|
||||
if (e.target.closest('#btn-save-auto-delete')) saveAutoDelete();
|
||||
if (e.target.closest('#btn-reset-all-defaults')) resetAllDefaults();
|
||||
});
|
||||
|
|
@ -307,7 +306,6 @@
|
|||
|
||||
loadPromptList();
|
||||
loadSmtp();
|
||||
loadModels();
|
||||
}
|
||||
|
||||
// ---- ANNOUNCEMENT ----
|
||||
|
|
@ -512,98 +510,6 @@
|
|||
.catch(function() { showToast('Request failed', 'error'); });
|
||||
}
|
||||
|
||||
// ---- MODELS ----
|
||||
|
||||
function loadModels() {
|
||||
var container = document.getElementById('cms-models-list');
|
||||
fetch('/api/admin/config/models', { headers: getAuthHeaders() })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
if (!data.success) {
|
||||
if (container) container.innerHTML = '<p style="color:var(--red);font-size:13px;">Failed to load models: ' + (data.error || 'Unknown error') + '</p>';
|
||||
return;
|
||||
}
|
||||
renderModelsList(data.models || [], data.custom || []);
|
||||
})
|
||||
.catch(function(e) {
|
||||
console.error('[Admin] Models load failed:', e);
|
||||
if (container) container.innerHTML = '<p style="color:var(--red);font-size:13px;"><i class="fas fa-circle-xmark"></i> Failed to load models. <button id="btn-retry-models" style="color:var(--blue);background:none;border:none;cursor:pointer;text-decoration:underline;font-size:13px;">Retry</button></p>';
|
||||
var retryBtn = document.getElementById('btn-retry-models');
|
||||
if (retryBtn) retryBtn.addEventListener('click', loadModels);
|
||||
});
|
||||
}
|
||||
|
||||
function renderModelsList(models, custom) {
|
||||
var container = document.getElementById('cms-models-list');
|
||||
if (!container) return;
|
||||
|
||||
var rows = models.map(function(m) {
|
||||
return '<div class="model-row">' +
|
||||
'<div class="model-row-name">' + esc(m.name) +
|
||||
' <span class="model-row-tag">' + esc(m.tag || '') + '</span>' +
|
||||
'</div>' +
|
||||
'<span class="model-row-cost">' + esc(m.cost || '') + '</span>' +
|
||||
'<label style="display:flex;align-items:center;gap:4px;font-size:12px;">' +
|
||||
'<input type="checkbox" class="model-toggle" data-id="' + esc(m.id) + '" ' + (m.enabled !== false ? 'checked' : '') + '> Enabled' +
|
||||
'</label>' +
|
||||
'</div>';
|
||||
});
|
||||
|
||||
if (custom.length > 0) {
|
||||
rows.push('<div style="font-size:11px;font-weight:700;color:var(--g500);text-transform:uppercase;letter-spacing:0.5px;margin-top:8px;padding-top:8px;border-top:1px solid var(--g200);">Custom Models</div>');
|
||||
custom.forEach(function(m) {
|
||||
rows.push('<div class="model-row">' +
|
||||
'<div class="model-row-name">' + esc(m.name) + ' <span class="model-row-tag" style="background:var(--blue-light);color:var(--blue);">CUSTOM</span></div>' +
|
||||
'<span class="model-row-cost" style="font-family:monospace;font-size:11px;">' + esc(m.id) + '</span>' +
|
||||
'<button class="btn-sm btn-ghost model-delete-custom" data-id="' + esc(m.id) + '" style="color:var(--red);font-size:11px;"><i class="fas fa-trash"></i></button>' +
|
||||
'</div>');
|
||||
});
|
||||
}
|
||||
|
||||
container.innerHTML = rows.join('');
|
||||
|
||||
container.querySelectorAll('.model-toggle').forEach(function(cb) {
|
||||
cb.addEventListener('change', function() {
|
||||
fetch('/api/admin/config/models/toggle', {
|
||||
method: 'PUT', headers: getAuthHeaders(),
|
||||
body: JSON.stringify({ modelId: cb.dataset.id, enabled: cb.checked })
|
||||
})
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(d) { if (!d.success) showToast(d.error || 'Failed', 'error'); })
|
||||
.catch(function() { showToast('Request failed', 'error'); });
|
||||
});
|
||||
});
|
||||
|
||||
container.querySelectorAll('.model-delete-custom').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
if (!confirm('Remove custom model "' + btn.dataset.id + '"?')) return;
|
||||
fetch('/api/admin/config/models/custom/' + encodeURIComponent(btn.dataset.id), { method: 'DELETE', headers: getAuthHeaders() })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(d) { if (d.success) { showToast('Removed', 'info'); loadModels(); } })
|
||||
.catch(function() {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function addCustomModel() {
|
||||
var id = prompt('OpenRouter Model ID (e.g. google/gemini-2.5-pro):');
|
||||
if (!id || !id.trim()) return;
|
||||
var name = prompt('Display name:', id.split('/').pop());
|
||||
if (!name) return;
|
||||
var cost = prompt('Cost estimate (e.g. ~$0.01):', '~$0.01');
|
||||
|
||||
fetch('/api/admin/config/models/custom', {
|
||||
method: 'POST', headers: getAuthHeaders(),
|
||||
body: JSON.stringify({ id: id.trim(), name: name.trim(), cost: cost || '?' })
|
||||
})
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
if (data.success) { showToast('Custom model added', 'success'); loadModels(); }
|
||||
else showToast(data.error || 'Failed', 'error');
|
||||
})
|
||||
.catch(function() { showToast('Request failed', 'error'); });
|
||||
}
|
||||
|
||||
// ---- AUTO-DELETE / RESET ----
|
||||
|
||||
function saveAutoDelete() {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
document.querySelectorAll('.tab-btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
activateTab(btn.getAttribute('data-tab'));
|
||||
var subtab = btn.getAttribute('data-subtab');
|
||||
if (subtab && typeof window.wvSwitchSubtab === 'function') {
|
||||
setTimeout(function() { window.wvSwitchSubtab(subtab); }, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -320,6 +320,16 @@
|
|||
window.loadSavedEncountersList = loadSavedEncountersList;
|
||||
|
||||
document.addEventListener('click', function(e) {
|
||||
// Copy milestones narrative to visit note
|
||||
if (e.target.closest('#btn-ms-copy-to-note')) {
|
||||
var msText = document.getElementById('ms-narrative-text');
|
||||
var wvMsEl = document.getElementById('wv-milestones-text');
|
||||
if (msText && wvMsEl) {
|
||||
var content = (msText.innerText || msText.textContent || '').trim();
|
||||
if (content) { wvMsEl.value = content; showToast('Milestones copied to Visit Note', 'success'); }
|
||||
else showToast('Generate a milestone assessment first', 'info');
|
||||
}
|
||||
}
|
||||
// Settings button — refresh saved encounters list
|
||||
if (e.target.closest('#btn-settings')) {
|
||||
loadSavedEncountersList();
|
||||
|
|
|
|||
|
|
@ -191,16 +191,22 @@
|
|||
switchSubtab('byvisit');
|
||||
}
|
||||
}
|
||||
// Milestones subtab is always shown (not age-gated)
|
||||
var milestonesBtn = document.querySelector('.wv-subtab-btn[data-subtab="milestones"]');
|
||||
if (milestonesBtn) {
|
||||
milestonesBtn.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
function switchSubtab(name) {
|
||||
document.querySelectorAll('.wv-subtab-btn').forEach(function (b) {
|
||||
b.classList.toggle('active', b.dataset.subtab === name);
|
||||
});
|
||||
document.querySelectorAll('.wv-subpanel').forEach(function (p) {
|
||||
(document.getElementById('wellvisit-tab') || document).querySelectorAll('.wv-subpanel').forEach(function (p) {
|
||||
p.classList.toggle('hidden', p.id !== 'wv-panel-' + name);
|
||||
});
|
||||
}
|
||||
window.wvSwitchSubtab = switchSubtab;
|
||||
|
||||
// ─── BY VISIT panel ───────────────────────────────────────────────────────
|
||||
function renderVisitPanel(visitId) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue