import { apiGet, apiPut, apiDelete } from '../api.js';
import { canEdit, showToast, getRole } from '../app.js';
import { navigate } from '../router.js';
export async function dashboardPage() {
const app = document.getElementById('app');
app.innerHTML = `
`;
if (canEdit()) {
document.getElementById('headerActions').innerHTML = `
+ New Questionnaire
`;
}
try {
const data = await apiGet('questionnaires.php');
renderGrid(data.questionnaires || []);
} catch (e) {
showToast(e.message, 'error');
document.getElementById('qGrid').innerHTML = `${e.message}
`;
}
}
function renderGrid(questionnaires) {
const grid = document.getElementById('qGrid');
if (!questionnaires.length) {
grid.innerHTML = `
No questionnaires yet
Create your first questionnaire to get started.
`;
return;
}
grid.innerHTML = questionnaires.map(q => {
const stateClass = `badge-${(q.state || 'draft').toLowerCase().replace(/\s+/g, '_')}`;
const showPts = parseInt(q.showPoints || 0, 10);
return `
v${esc(q.version || '—')}
${q.questionCount || 0} question${q.questionCount == 1 ? '' : 's'}
#${q.orderIndex ?? '—'}
${showPts ? 'pts' : ''}
`;
}).join('');
grid.querySelectorAll('.q-card').forEach(card => {
card.addEventListener('click', (e) => {
if (e.target.closest('.q-card-actions') || e.target.closest('.drag-handle')) return;
navigate(`#/questionnaire/${card.dataset.id}`);
});
});
grid.querySelectorAll('.delete-q-btn').forEach(btn => {
btn.addEventListener('click', async (e) => {
e.stopPropagation();
if (!confirm('Delete this questionnaire and all its data?')) return;
try {
await apiDelete('questionnaires.php', { questionnaireID: btn.dataset.id });
showToast('Questionnaire deleted', 'success');
btn.closest('.q-card').remove();
} catch (err) {
showToast(err.message, 'error');
}
});
});
if (canEdit()) initGridDrag(questionnaires);
}
function initGridDrag(questionnaires) {
const grid = document.getElementById('qGrid');
if (!grid) return;
let dragItem = null;
grid.addEventListener('dragstart', (e) => {
const card = e.target.closest('.q-card');
if (!card || !e.target.closest('.drag-handle')) { e.preventDefault(); return; }
dragItem = card;
card.style.opacity = '0.5';
e.dataTransfer.effectAllowed = 'move';
});
grid.addEventListener('dragover', (e) => {
e.preventDefault();
if (!dragItem) return;
const cards = [...grid.querySelectorAll('.q-card:not([style*="opacity"])')];
const afterCard = cards.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = e.clientY - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) return { offset, element: child };
return closest;
}, { offset: Number.NEGATIVE_INFINITY }).element;
if (afterCard) grid.insertBefore(dragItem, afterCard);
else grid.appendChild(dragItem);
});
grid.addEventListener('dragend', async () => {
if (!dragItem) return;
dragItem.style.opacity = '';
const newOrder = [...grid.querySelectorAll('.q-card')].map(el => el.dataset.id);
dragItem = null;
for (let i = 0; i < newOrder.length; i++) {
const id = newOrder[i];
const q = questionnaires.find(q => q.questionnaireID === id);
if (q && parseInt(q.orderIndex, 10) !== i) {
try {
await apiPut('questionnaires.php', { questionnaireID: id, orderIndex: i });
q.orderIndex = i;
} catch (e) {
showToast(e.message, 'error');
return;
}
}
}
showToast('Order saved', 'success');
});
}
function esc(s) {
const d = document.createElement('div');
d.textContent = s ?? '';
return d.innerHTML;
}