Fix loading race condition, improve quiz UX, editor toolbar, settings page
- Fix: component loader now fires tabChanged AFTER HTML is in DOM (fixes CMS/settings stuck at loading) - CMS: separate "New Article", "New Quiz", "New Pearl" buttons - CMS: editor toolbar with formatting buttons (bold, italic, headings, lists, links, tables, quotes, code, hr) - CMS: quiz questions have numbered headers (Q1, Q2...), larger inputs, clear "check correct answer" labels - CMS: validation prevents saving questions without correct answer marked - Quiz UX: large card-style question boxes with gradient number badges, bigger option buttons with hover effects and selection feedback, checkmark/cross icons on results - Settings: improved card spacing, input styling, section headers with bottom borders for visual hierarchy - Settings: updated compliance section (removed HIPAA references, added BAA/institution guidelines language)
This commit is contained in:
parent
82a0911d24
commit
ffacdcbedb
5 changed files with 155 additions and 60 deletions
|
|
@ -45,7 +45,11 @@
|
|||
<!-- Content list view -->
|
||||
<div id="cms-list-view">
|
||||
<div class="cms-toolbar">
|
||||
<button id="btn-lh-new-content" class="btn-sm btn-primary"><i class="fas fa-plus"></i> New Content</button>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button id="btn-lh-new-content" class="btn-sm btn-primary" data-type="article"><i class="fas fa-file-alt"></i> New Article</button>
|
||||
<button id="btn-lh-new-quiz" class="btn-sm" style="background:var(--amber-light);color:#92400e;border:1px solid var(--amber);border-radius:6px;padding:6px 12px;font-size:13px;cursor:pointer;"><i class="fas fa-clipboard-question"></i> New Quiz</button>
|
||||
<button id="btn-lh-new-pearl" class="btn-sm" style="background:var(--purple-light);color:var(--purple);border:1px solid var(--purple);border-radius:6px;padding:6px 12px;font-size:13px;cursor:pointer;"><i class="fas fa-gem"></i> New Pearl</button>
|
||||
</div>
|
||||
<div class="cms-search">
|
||||
<i class="fas fa-search"></i>
|
||||
<input type="text" id="cms-search" placeholder="Search content..." class="cms-input-sm">
|
||||
|
|
@ -108,10 +112,27 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Body editor -->
|
||||
<!-- Body editor with toolbar -->
|
||||
<div class="cms-body-section">
|
||||
<label class="cms-label">Body <span style="color:var(--g400);font-weight:400;">(supports basic HTML: bold, lists, tables, links)</span></label>
|
||||
<textarea id="lh-cms-edit-body" class="cms-body-editor" rows="16" placeholder="Write your content here... You can use HTML tags like <b>, <ul>, <ol>, <table>, <blockquote>, <a>, <h2>, <h3>, <code>, <p>..."></textarea>
|
||||
<label class="cms-label">Body</label>
|
||||
<div class="cms-editor-toolbar">
|
||||
<button type="button" class="cms-tb-btn" data-insert="b" title="Bold"><i class="fas fa-bold"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="i" title="Italic"><i class="fas fa-italic"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="u" title="Underline"><i class="fas fa-underline"></i></button>
|
||||
<span class="cms-tb-sep"></span>
|
||||
<button type="button" class="cms-tb-btn" data-insert="h2" title="Heading 2">H2</button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="h3" title="Heading 3">H3</button>
|
||||
<span class="cms-tb-sep"></span>
|
||||
<button type="button" class="cms-tb-btn" data-insert="ul" title="Bullet List"><i class="fas fa-list-ul"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="ol" title="Numbered List"><i class="fas fa-list-ol"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="blockquote" title="Quote"><i class="fas fa-quote-left"></i></button>
|
||||
<span class="cms-tb-sep"></span>
|
||||
<button type="button" class="cms-tb-btn" data-insert="a" title="Link"><i class="fas fa-link"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="code" title="Code"><i class="fas fa-code"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="table" title="Table"><i class="fas fa-table"></i></button>
|
||||
<button type="button" class="cms-tb-btn" data-insert="hr" title="Horizontal Rule"><i class="fas fa-minus"></i></button>
|
||||
</div>
|
||||
<textarea id="lh-cms-edit-body" class="cms-body-editor" rows="16" placeholder="Write your content here..."></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Quiz builder -->
|
||||
|
|
|
|||
|
|
@ -78,20 +78,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HIPAA -->
|
||||
<!-- Compliance -->
|
||||
<div class="settings-section card">
|
||||
<h3><i class="fas fa-lock"></i> HIPAA & Privacy</h3>
|
||||
<h3><i class="fas fa-shield-halved"></i> Compliance & Usage</h3>
|
||||
<div class="hipaa-info">
|
||||
<p><strong>Current Status:</strong> This tool processes data through third-party AI APIs.</p>
|
||||
<p><strong>AWS Bedrock</strong> is available with a Business Associate Agreement (BAA) for HIPAA-eligible workloads.</p>
|
||||
<ul>
|
||||
<li>✅ All connections use HTTPS/TLS encryption</li>
|
||||
<li>✅ Authentication required</li>
|
||||
<li>✅ No patient data stored on server</li>
|
||||
<li>✅ 2FA available</li>
|
||||
<li>⚠️ OpenRouter does not currently offer BAA</li>
|
||||
<li>⚠️ For full HIPAA: use Azure OpenAI or AWS Bedrock with BAA</li>
|
||||
<li>✅ Authentication with optional 2FA</li>
|
||||
<li>✅ No patient data stored on server beyond session</li>
|
||||
<li>✅ AWS Bedrock supports BAA for HIPAA compliance</li>
|
||||
<li>✅ Azure OpenAI supports BAA for HIPAA compliance</li>
|
||||
</ul>
|
||||
<p><strong>Recommendation:</strong> Do not enter real PHI until your organization has executed BAAs with all AI providers.</p>
|
||||
<p><strong>Important:</strong> Check with your institution's guidelines and policies before use. This tool is not intended for production clinical use without proper organizational authorization and provider BAAs in place. Use with caution.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -439,12 +439,16 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.shadess-flag-btn{font-size:11px;padding:2px 6px;}
|
||||
|
||||
/* Settings page */
|
||||
.settings-page{display:flex;flex-direction:column;gap:16px;max-width:800px;}
|
||||
.settings-page .settings-section{padding:20px;}
|
||||
.settings-page .settings-section h3{font-size:16px;font-weight:700;color:var(--g800);margin-bottom:12px;display:flex;align-items:center;gap:8px;}
|
||||
.settings-page .settings-section p{font-size:13px;color:var(--g600);margin-bottom:12px;}
|
||||
.settings-page{display:flex;flex-direction:column;gap:0;max-width:800px;}
|
||||
.settings-page .settings-section{padding:20px;margin-bottom:12px;border-radius:var(--radius);}
|
||||
.settings-page .settings-section h3{font-size:16px;font-weight:700;color:var(--g800);margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--g100);display:flex;align-items:center;gap:8px;}
|
||||
.settings-page .settings-section p{font-size:13px;color:var(--g600);margin-bottom:12px;line-height:1.6;}
|
||||
.settings-page .hipaa-info ul{margin:10px 0 10px 20px;font-size:13px;}
|
||||
.settings-page .hipaa-info li{margin-bottom:4px;}
|
||||
.settings-page .hipaa-info li{margin-bottom:6px;line-height:1.5;}
|
||||
.settings-page .form-group{margin-bottom:14px;}
|
||||
.settings-page .form-group label{font-size:13px;font-weight:600;color:var(--g600);margin-bottom:4px;display:block;}
|
||||
.settings-page .form-group input{width:100%;padding:8px 12px;border:1.5px solid var(--g300);border-radius:6px;font-size:13px;box-sizing:border-box;}
|
||||
.settings-page .form-group input:focus{border-color:var(--blue);outline:none;box-shadow:0 0 0 2px var(--blue-light);}
|
||||
|
||||
/* Inline load popover — compact dropdown, right-aligned under Load button */
|
||||
.enc-load-popover{position:absolute;right:0;top:calc(100% + 4px);width:360px;max-width:calc(100vw - 24px);background:white;border:1px solid var(--g300);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,0.15);z-index:600;display:flex;flex-direction:column;}
|
||||
|
|
@ -531,20 +535,23 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.lh-content-body th,.lh-content-body td{padding:8px 12px;border:1px solid var(--g200);font-size:13px;}
|
||||
.lh-content-body th{background:var(--g50);font-weight:600;}
|
||||
|
||||
/* Quiz */
|
||||
.lh-quiz-q{margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--g100);}
|
||||
.lh-quiz-q:last-child{border-bottom:none;margin-bottom:0;}
|
||||
.lh-quiz-q-header{display:flex;gap:8px;align-items:center;margin-bottom:6px;}
|
||||
.lh-quiz-q-num{font-size:12px;font-weight:700;color:var(--blue);background:var(--blue-light);padding:2px 8px;border-radius:6px;}
|
||||
.lh-quiz-q-type{font-size:11px;color:var(--g400);}
|
||||
.lh-quiz-q-text{font-size:14px;font-weight:500;margin-bottom:10px;color:var(--g800);}
|
||||
.lh-quiz-options{display:flex;flex-direction:column;gap:6px;}
|
||||
.lh-quiz-option{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1.5px solid var(--g200);border-radius:8px;cursor:pointer;transition:all 0.15s;font-size:13px;}
|
||||
.lh-quiz-option:hover{border-color:var(--blue-light);background:var(--g50);}
|
||||
.lh-quiz-option input[type="radio"]{accent-color:var(--blue);width:16px;height:16px;}
|
||||
/* Quiz — large, visual question cards */
|
||||
.lh-quiz-q{margin-bottom:24px;padding:20px;background:white;border:1.5px solid var(--g200);border-radius:12px;box-shadow:0 1px 4px rgba(0,0,0,0.04);}
|
||||
.lh-quiz-q:last-child{margin-bottom:0;}
|
||||
.lh-quiz-q-header{display:flex;gap:10px;align-items:center;margin-bottom:10px;}
|
||||
.lh-quiz-q-num{font-size:13px;font-weight:700;color:white;background:linear-gradient(135deg,var(--blue),var(--purple));padding:4px 12px;border-radius:8px;min-width:32px;text-align:center;}
|
||||
.lh-quiz-q-type{font-size:11px;color:var(--g400);background:var(--g100);padding:2px 8px;border-radius:4px;}
|
||||
.lh-quiz-q-text{font-size:16px;font-weight:600;margin-bottom:14px;color:var(--g800);line-height:1.5;}
|
||||
.lh-quiz-options{display:flex;flex-direction:column;gap:8px;}
|
||||
.lh-quiz-option{display:flex;align-items:center;gap:12px;padding:14px 18px;border:2px solid var(--g200);border-radius:10px;cursor:pointer;transition:all 0.2s;font-size:14px;line-height:1.4;background:white;}
|
||||
.lh-quiz-option:hover{border-color:var(--blue);background:var(--blue-light);transform:translateY(-1px);box-shadow:0 2px 8px rgba(37,99,235,0.1);}
|
||||
.lh-quiz-option input[type="radio"]{accent-color:var(--blue);width:18px;height:18px;flex-shrink:0;}
|
||||
.lh-quiz-option span{flex:1;}
|
||||
.lh-opt-correct{border-color:var(--green) !important;background:var(--green-light) !important;}
|
||||
.lh-opt-wrong{border-color:var(--red) !important;background:var(--red-light) !important;}
|
||||
.lh-opt-correct{border-color:var(--green) !important;background:var(--green-light) !important;box-shadow:0 0 0 2px rgba(16,185,129,0.2) !important;}
|
||||
.lh-opt-correct::after{content:'\\2713';position:absolute;right:14px;color:var(--green);font-weight:700;font-size:18px;}
|
||||
.lh-quiz-option.lh-opt-correct,.lh-quiz-option.lh-opt-wrong{position:relative;}
|
||||
.lh-opt-wrong{border-color:var(--red) !important;background:var(--red-light) !important;box-shadow:0 0 0 2px rgba(239,68,68,0.2) !important;}
|
||||
.lh-opt-wrong::after{content:'\\2717';position:absolute;right:14px;color:var(--red);font-weight:700;font-size:18px;}
|
||||
|
||||
/* Quiz results */
|
||||
.lh-result-item{margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid var(--g100);}
|
||||
|
|
@ -556,7 +563,7 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.lh-expl-general{background:var(--blue-light);color:#1e40af;}
|
||||
|
||||
/* CMS question builder */
|
||||
.lh-question-block{padding:12px;border:1px solid var(--g200);border-radius:8px;margin-bottom:8px;background:var(--g50);}
|
||||
.lh-question-block{padding:16px;border:1.5px solid var(--g200);border-radius:10px;margin-bottom:12px;background:white;box-shadow:0 1px 3px rgba(0,0,0,0.04);transition:outline 0.2s;}
|
||||
|
||||
/* ============================================================
|
||||
CONTENT MANAGER (WordPress-like CMS)
|
||||
|
|
@ -628,6 +635,13 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.cms-quiz-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;}
|
||||
.cms-quiz-header h3{margin:0;font-size:15px;color:var(--g700);}
|
||||
|
||||
/* Editor toolbar */
|
||||
.cms-editor-toolbar{display:flex;gap:2px;padding:6px 8px;background:var(--g50);border:1px solid var(--g300);border-bottom:none;border-radius:8px 8px 0 0;flex-wrap:wrap;}
|
||||
.cms-tb-btn{width:32px;height:28px;border:none;background:transparent;cursor:pointer;border-radius:4px;font-size:12px;color:var(--g600);display:flex;align-items:center;justify-content:center;font-family:inherit;font-weight:600;}
|
||||
.cms-tb-btn:hover{background:var(--g200);color:var(--g800);}
|
||||
.cms-tb-sep{width:1px;background:var(--g300);margin:2px 4px;align-self:stretch;}
|
||||
.cms-body-section .cms-body-editor{border-radius:0 0 8px 8px;}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media(max-width:768px){
|
||||
.cms-layout{grid-template-columns:1fr;}
|
||||
|
|
@ -640,7 +654,7 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.cms-stat{padding:8px 10px;}
|
||||
.cms-stat-value{font-size:18px;}
|
||||
}
|
||||
.lh-option-row{display:flex;align-items:center;gap:6px;margin-bottom:4px;}
|
||||
.lh-option-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;padding:6px 8px;border-radius:6px;background:var(--g50);}
|
||||
|
||||
@media(max-width:640px){
|
||||
.lh-feed-item-header{flex-direction:column;gap:6px;}
|
||||
|
|
|
|||
|
|
@ -74,12 +74,15 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
var tabEl = document.getElementById(tabName + '-tab');
|
||||
if (tabEl) {
|
||||
tabEl.classList.add('active');
|
||||
// Lazy-load component HTML if not yet loaded
|
||||
loadComponent(tabEl);
|
||||
// Lazy-load component HTML, then fire tabChanged after DOM is ready
|
||||
loadComponent(tabEl).then(function() {
|
||||
document.dispatchEvent(new CustomEvent('tabChanged', { detail: { tab: tabName } }));
|
||||
});
|
||||
} else {
|
||||
document.dispatchEvent(new CustomEvent('tabChanged', { detail: { tab: tabName } }));
|
||||
}
|
||||
// Persist last tab in localStorage (restored after login in auth.js)
|
||||
try { localStorage.setItem('ped_last_tab', tabName); } catch(e) {}
|
||||
document.dispatchEvent(new CustomEvent('tabChanged', { detail: { tab: tabName } }));
|
||||
// Close sidebar on mobile after tab click
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
if (sidebar && window.innerWidth <= 768) {
|
||||
|
|
|
|||
|
|
@ -56,12 +56,18 @@
|
|||
|
||||
// ── CMS events ─────────────────────────────
|
||||
if (e.target.closest('#btn-lh-add-cat')) { addCategory(); return; }
|
||||
if (e.target.closest('#btn-lh-new-content')) { openEditor(null); return; }
|
||||
if (e.target.closest('#btn-lh-new-content')) { openEditor(null, 'article'); return; }
|
||||
if (e.target.closest('#btn-lh-new-quiz')) { openEditor(null, 'quiz'); return; }
|
||||
if (e.target.closest('#btn-lh-new-pearl')) { openEditor(null, 'pearl'); return; }
|
||||
if (e.target.closest('#btn-lh-close-editor')) { closeEditor(); return; }
|
||||
if (e.target.closest('#btn-lh-save-content')) { saveContent(); return; }
|
||||
if (e.target.closest('#btn-lh-delete-content')) { deleteContent(); return; }
|
||||
if (e.target.closest('#btn-lh-add-question')) { addQuestionBlock(); return; }
|
||||
|
||||
// Editor toolbar buttons
|
||||
var tbBtn = e.target.closest('.cms-tb-btn');
|
||||
if (tbBtn && tbBtn.dataset.insert) { insertTag(tbBtn.dataset.insert); return; }
|
||||
|
||||
// CMS content item edit
|
||||
var cmsItem = e.target.closest('.lh-cms-content-item');
|
||||
if (cmsItem && cmsItem.dataset.id) { openEditor(cmsItem.dataset.id); return; }
|
||||
|
|
@ -554,7 +560,33 @@
|
|||
renderCmsContentList(filtered);
|
||||
}
|
||||
|
||||
function openEditor(contentId) {
|
||||
// Editor toolbar — insert HTML tags at cursor in textarea
|
||||
function insertTag(tag) {
|
||||
var ta = document.getElementById('lh-cms-edit-body');
|
||||
if (!ta) return;
|
||||
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||
var sel = ta.value.substring(start, end);
|
||||
var insert = '';
|
||||
switch(tag) {
|
||||
case 'b': case 'i': case 'u': case 'code': case 'h2': case 'h3':
|
||||
insert = '<' + tag + '>' + (sel || 'text') + '</' + tag + '>'; break;
|
||||
case 'a':
|
||||
var url = prompt('Enter URL:');
|
||||
if (!url) return;
|
||||
insert = '<a href="' + url + '">' + (sel || 'link text') + '</a>'; break;
|
||||
case 'ul': insert = '<ul>\n <li>' + (sel || 'item') + '</li>\n <li></li>\n</ul>'; break;
|
||||
case 'ol': insert = '<ol>\n <li>' + (sel || 'item') + '</li>\n <li></li>\n</ol>'; break;
|
||||
case 'blockquote': insert = '<blockquote>' + (sel || 'quote') + '</blockquote>'; break;
|
||||
case 'table': insert = '<table>\n<tr><th>Header 1</th><th>Header 2</th></tr>\n<tr><td>' + (sel || 'data') + '</td><td></td></tr>\n</table>'; break;
|
||||
case 'hr': insert = '<hr>'; break;
|
||||
default: return;
|
||||
}
|
||||
ta.value = ta.value.substring(0, start) + insert + ta.value.substring(end);
|
||||
ta.focus();
|
||||
ta.selectionStart = ta.selectionEnd = start + insert.length;
|
||||
}
|
||||
|
||||
function openEditor(contentId, contentType) {
|
||||
var editor = document.getElementById('lh-cms-editor');
|
||||
var listView = document.getElementById('cms-list-view');
|
||||
if (!editor) return;
|
||||
|
|
@ -567,11 +599,16 @@
|
|||
document.getElementById('lh-cms-edit-subject').value = '';
|
||||
document.getElementById('lh-cms-edit-body').value = '';
|
||||
document.getElementById('lh-cms-edit-category').value = '';
|
||||
document.getElementById('lh-cms-edit-type').value = 'article';
|
||||
document.getElementById('lh-cms-edit-type').value = contentType || 'article';
|
||||
document.getElementById('lh-cms-edit-published').value = 'false';
|
||||
document.getElementById('lh-cms-questions').innerHTML = '';
|
||||
document.getElementById('btn-lh-delete-content').classList.add('hidden');
|
||||
|
||||
// For quiz type, add a starter question
|
||||
if (contentType === 'quiz' && !contentId) {
|
||||
addQuestionBlock();
|
||||
}
|
||||
|
||||
if (!contentId) return;
|
||||
|
||||
// Load existing content
|
||||
|
|
@ -618,11 +655,14 @@
|
|||
|
||||
if (!title) { showToast('Title required', 'error'); return; }
|
||||
|
||||
// Gather questions
|
||||
// Gather questions with validation
|
||||
var questions = [];
|
||||
document.querySelectorAll('#lh-cms-questions .lh-question-block').forEach(function(qBlock) {
|
||||
var validationError = false;
|
||||
var qBlocks = document.querySelectorAll('#lh-cms-questions .lh-question-block');
|
||||
for (var qi = 0; qi < qBlocks.length; qi++) {
|
||||
var qBlock = qBlocks[qi];
|
||||
var qText = qBlock.querySelector('.lh-q-text').value.trim();
|
||||
if (!qText) return;
|
||||
if (!qText) continue;
|
||||
var qType = qBlock.querySelector('.lh-q-type').value;
|
||||
var qExpl = qBlock.querySelector('.lh-q-explanation').value.trim();
|
||||
var qId = qBlock.dataset.questionId || null;
|
||||
|
|
@ -638,6 +678,17 @@
|
|||
});
|
||||
});
|
||||
|
||||
// Validate: must have a correct answer marked
|
||||
var hasCorrect = options.some(function(o) { return o.is_correct; });
|
||||
if (options.length > 0 && !hasCorrect) {
|
||||
showToast('Question "' + qText.substring(0, 50) + '..." needs a correct answer marked', 'error');
|
||||
qBlock.style.outline = '2px solid var(--red)';
|
||||
qBlock.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
validationError = true;
|
||||
break;
|
||||
}
|
||||
qBlock.style.outline = '';
|
||||
|
||||
questions.push({
|
||||
id: qId,
|
||||
question_text: qText,
|
||||
|
|
@ -645,7 +696,8 @@
|
|||
explanation: qExpl,
|
||||
options: options
|
||||
});
|
||||
});
|
||||
}
|
||||
if (validationError) return;
|
||||
|
||||
var payload = { title: title, body: body, category_id: category_id, subject: subject, content_type: content_type, published: published };
|
||||
|
||||
|
|
@ -733,21 +785,28 @@
|
|||
block.className = 'lh-question-block';
|
||||
if (existingQ && existingQ.id) block.dataset.questionId = existingQ.id;
|
||||
|
||||
var qNum = container.querySelectorAll('.lh-question-block').length + 1;
|
||||
block.innerHTML =
|
||||
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;">' +
|
||||
'<span style="font-size:12px;font-weight:600;color:var(--g600);">Question</span>' +
|
||||
'<button class="btn-sm btn-ghost lh-rm-question" style="padding:2px 6px;font-size:11px;color:var(--red);"><i class="fas fa-trash"></i> Remove</button>' +
|
||||
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid var(--g200);">' +
|
||||
'<div style="display:flex;align-items:center;gap:8px;">' +
|
||||
'<span style="background:linear-gradient(135deg,var(--blue),var(--purple));color:white;font-size:12px;font-weight:700;padding:3px 10px;border-radius:6px;">Q' + qNum + '</span>' +
|
||||
'<select class="lh-q-type" style="font-size:12px;padding:4px 8px;border:1px solid var(--g300);border-radius:6px;">' +
|
||||
'<option value="mcq"' + (existingQ && existingQ.question_type === 'mcq' ? ' selected' : '') + '>Single Choice</option>' +
|
||||
'<option value="true_false"' + (existingQ && existingQ.question_type === 'true_false' ? ' selected' : '') + '>True / False</option>' +
|
||||
'</select>' +
|
||||
'</div>' +
|
||||
'<button class="btn-sm btn-ghost lh-rm-question" style="padding:2px 8px;font-size:12px;color:var(--red);"><i class="fas fa-trash"></i></button>' +
|
||||
'</div>' +
|
||||
'<input type="text" class="lh-q-text" placeholder="Question text..." value="' + esc(existingQ ? existingQ.question_text : '') + '" style="width:100%;font-size:13px;padding:7px;border:1px solid var(--g300);border-radius:6px;box-sizing:border-box;margin-bottom:6px;">' +
|
||||
'<div style="display:flex;gap:8px;margin-bottom:6px;">' +
|
||||
'<select class="lh-q-type" style="font-size:12px;padding:4px 8px;border:1px solid var(--g300);border-radius:6px;">' +
|
||||
'<option value="mcq"' + (existingQ && existingQ.question_type === 'mcq' ? ' selected' : '') + '>Multiple Choice</option>' +
|
||||
'<option value="true_false"' + (existingQ && existingQ.question_type === 'true_false' ? ' selected' : '') + '>True / False</option>' +
|
||||
'</select>' +
|
||||
'<input type="text" class="lh-q-explanation" placeholder="General explanation (shown after answering)" value="' + esc(existingQ ? existingQ.explanation || '' : '') + '" style="flex:1;font-size:12px;padding:4px 8px;border:1px solid var(--g300);border-radius:6px;">' +
|
||||
'<input type="text" class="lh-q-text" placeholder="Enter question text..." value="' + esc(existingQ ? existingQ.question_text : '') + '" style="width:100%;font-size:14px;font-weight:500;padding:10px;border:1.5px solid var(--g300);border-radius:8px;box-sizing:border-box;margin-bottom:8px;">' +
|
||||
'<div style="margin-bottom:8px;">' +
|
||||
'<label style="font-size:11px;font-weight:600;color:var(--g500);text-transform:uppercase;letter-spacing:0.3px;display:block;margin-bottom:4px;">Answer Options <span style="color:var(--green);">(check the correct answer)</span></label>' +
|
||||
'</div>' +
|
||||
'<div class="lh-options-list"></div>' +
|
||||
'<button class="btn-sm btn-ghost lh-add-option" style="margin-top:4px;font-size:12px;"><i class="fas fa-plus"></i> Add Option</button>';
|
||||
'<button class="btn-sm btn-ghost lh-add-option" style="margin-top:6px;font-size:12px;"><i class="fas fa-plus"></i> Add Option</button>' +
|
||||
'<div style="margin-top:8px;">' +
|
||||
'<label style="font-size:11px;font-weight:600;color:var(--g500);display:block;margin-bottom:3px;">Explanation (shown after answering)</label>' +
|
||||
'<input type="text" class="lh-q-explanation" placeholder="Explain the correct answer..." value="' + esc(existingQ ? existingQ.explanation || '' : '') + '" style="width:100%;font-size:12px;padding:6px 10px;border:1px solid var(--g300);border-radius:6px;box-sizing:border-box;">' +
|
||||
'</div>';
|
||||
|
||||
container.appendChild(block);
|
||||
|
||||
|
|
@ -768,13 +827,12 @@
|
|||
var row = document.createElement('div');
|
||||
row.className = 'lh-option-row';
|
||||
row.innerHTML =
|
||||
'<label style="display:flex;align-items:center;gap:4px;cursor:pointer;" title="Mark as correct">' +
|
||||
'<input type="checkbox" class="lh-opt-correct"' + (opt && opt.is_correct ? ' checked' : '') + '>' +
|
||||
'<i class="fas fa-check" style="font-size:11px;color:var(--green);"></i>' +
|
||||
'<label style="display:flex;align-items:center;gap:4px;cursor:pointer;min-width:28px;" title="Mark as correct answer">' +
|
||||
'<input type="checkbox" class="lh-opt-correct"' + (opt && opt.is_correct ? ' checked' : '') + ' style="accent-color:var(--green);width:16px;height:16px;">' +
|
||||
'</label>' +
|
||||
'<input type="text" class="lh-opt-text" placeholder="Option text" value="' + esc(opt ? opt.option_text : '') + '" style="flex:1;font-size:12px;padding:4px 8px;border:1px solid var(--g300);border-radius:6px;">' +
|
||||
'<input type="text" class="lh-opt-expl" placeholder="Why wrong (optional)" value="' + esc(opt ? opt.explanation || '' : '') + '" style="flex:1;font-size:12px;padding:4px 8px;border:1px solid var(--g300);border-radius:6px;">' +
|
||||
'<button class="btn-sm btn-ghost lh-rm-option" style="padding:2px 6px;font-size:11px;color:var(--red);"><i class="fas fa-times"></i></button>';
|
||||
'<input type="text" class="lh-opt-text" placeholder="Option text" value="' + esc(opt ? opt.option_text : '') + '" style="flex:2;font-size:13px;padding:6px 10px;border:1.5px solid var(--g300);border-radius:6px;">' +
|
||||
'<input type="text" class="lh-opt-expl" placeholder="Explanation if wrong" value="' + esc(opt ? opt.explanation || '' : '') + '" style="flex:1;font-size:12px;padding:6px 10px;border:1px solid var(--g300);border-radius:6px;color:var(--g600);">' +
|
||||
'<button class="btn-sm btn-ghost lh-rm-option" style="padding:2px 6px;font-size:12px;color:var(--g400);"><i class="fas fa-times"></i></button>';
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue