109 lines
6.3 KiB
JavaScript
109 lines
6.3 KiB
JavaScript
import { esc } from './sanitize.js';
|
|
|
|
export function renderCmsCategoryList(categories) {
|
|
if (!categories || categories.length === 0) {
|
|
return '<div style="font-size:12px;color:var(--g400);">No categories yet</div>';
|
|
}
|
|
|
|
return categories.map(function(c) {
|
|
return '<div class="cms-cat-item lh-cms-cat-filter" data-id="' + c.id + '">' +
|
|
'<span class="cms-cat-name">' +
|
|
'<i class="fas fa-folder" style="color:var(--amber);margin-right:6px;font-size:11px;"></i>' +
|
|
esc(c.name) +
|
|
'</span>' +
|
|
'<span class="cms-cat-count">' + c.content_count + '</span>' +
|
|
'<button class="lh-cms-del-cat" data-id="' + c.id + '" ' +
|
|
'style="border:none;background:none;cursor:pointer;color:var(--g400);font-size:11px;padding:2px;" title="Delete">' +
|
|
'<i class="fas fa-times"></i>' +
|
|
'</button>' +
|
|
'</div>';
|
|
}).join('');
|
|
}
|
|
|
|
export function renderCmsContentEmpty() {
|
|
return '<div style="text-align:center;padding:40px;color:var(--g400);">' +
|
|
'<i class="fas fa-file-circle-plus" style="font-size:24px;display:block;margin-bottom:8px;"></i>' +
|
|
'No content yet. Click "New Content" to get started.' +
|
|
'</div>';
|
|
}
|
|
|
|
export function renderCmsContentRow(item) {
|
|
var statusBadge = item.published
|
|
? '<span class="cms-badge cms-badge-pub">Published</span>'
|
|
: '<span class="cms-badge cms-badge-draft">Draft</span>';
|
|
var typeLabel = item.content_type === 'quiz' ? 'Quiz'
|
|
: item.content_type === 'pearl' ? 'Pearl'
|
|
: item.content_type === 'presentation' ? 'Slides'
|
|
: 'Article';
|
|
var qBadge = item.question_count > 0
|
|
? ' <span style="color:var(--amber);">' + item.question_count + 'Q</span>'
|
|
: '';
|
|
var date = item.updated_at ? new Date(item.updated_at).toLocaleDateString() : '';
|
|
|
|
return '<div class="cms-table-row lh-cms-content-item" data-id="' + item.id + '">' +
|
|
'<span class="cms-col-title">' + esc(item.title) + qBadge +
|
|
'<br><span class="cms-title-sub">' + esc(item.subject || '') + '</span>' +
|
|
'</span>' +
|
|
'<span class="cms-col-cat">' + esc(item.category_name || 'Uncategorized') + '</span>' +
|
|
'<span class="cms-col-type">' + typeLabel + '</span>' +
|
|
'<span class="cms-col-status">' + statusBadge + '</span>' +
|
|
'<span class="cms-col-date">' + date + '</span>' +
|
|
'<span class="cms-col-actions"><i class="fas fa-pen" style="color:var(--g400);"></i></span>' +
|
|
'</div>';
|
|
}
|
|
|
|
export function renderQuestionBlockShell(existingQ, qNum) {
|
|
var qBadgeStyle = 'background:linear-gradient(135deg,var(--blue),var(--purple));color:white;' +
|
|
'font-size:12px;font-weight:700;padding:3px 10px;border-radius:6px;';
|
|
var qTextStyle = '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;resize:vertical;font-family:inherit;';
|
|
var qExplStyle = 'width:100%;font-size:12px;padding:6px 10px;border:1px solid var(--g300);' +
|
|
'border-radius:6px;box-sizing:border-box;resize:vertical;font-family:inherit;';
|
|
|
|
return '<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="' + qBadgeStyle + '">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"' + selectedQuestionType(existingQ, 'mcq') + '>Single Choice</option>' +
|
|
'<option value="multi"' + selectedQuestionType(existingQ, 'multi') + '>Multiple Select</option>' +
|
|
'<option value="true_false"' + selectedQuestionType(existingQ, 'true_false') + '>True / False</option>' +
|
|
'</select>' +
|
|
'<button type="button" class="lh-richtext-btn" data-target="question">Rich Text</button>' +
|
|
'</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>' +
|
|
'<textarea class="lh-q-text" placeholder="Enter question text..." rows="3" style="' + qTextStyle + '"></textarea>' +
|
|
'<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: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>' +
|
|
'<textarea class="lh-q-explanation" placeholder="Explain the correct answer..." rows="2" style="' + qExplStyle + '"></textarea>' +
|
|
'</div>';
|
|
}
|
|
|
|
export function renderOptionRowShell(opt) {
|
|
var optTextStyle = 'width:100%;font-size:13px;padding:6px 10px;border:1.5px solid var(--g300);' +
|
|
'border-radius:6px;box-sizing:border-box;';
|
|
var optExplStyle = 'flex:1;font-size:12px;padding:6px 10px;border:1px solid var(--g300);' +
|
|
'border-radius:6px;color:var(--g600);';
|
|
|
|
return '<label style="display:flex;align-items:center;gap:4px;cursor:pointer;min-width:28px;padding-top:6px;" 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>' +
|
|
'<div style="flex:2;display:flex;flex-direction:column;gap:3px;">' +
|
|
'<input type="text" class="lh-opt-text" placeholder="Option text" style="' + optTextStyle + '">' +
|
|
'<button type="button" class="lh-richtext-btn" data-target="option" style="align-self:flex-start;">Rich</button>' +
|
|
'</div>' +
|
|
'<input type="text" class="lh-opt-expl" placeholder="Explanation if wrong" value="' + esc(opt ? opt.explanation || '' : '') + '" style="' + optExplStyle + '">' +
|
|
'<button class="btn-sm btn-ghost lh-rm-option" style="padding:2px 6px;font-size:12px;color:var(--g400);margin-top:4px;"><i class="fas fa-times"></i></button>';
|
|
}
|
|
|
|
function selectedQuestionType(existingQ, type) {
|
|
return existingQ && existingQ.question_type === type ? ' selected' : '';
|
|
}
|