initial prototype based on nat-as-server
Some checks failed
PHPUnit / test (push) Has been cancelled
Some checks failed
PHPUnit / test (push) Has been cancelled
This commit is contained in:
108
website/js/pages/home.js
Normal file
108
website/js/pages/home.js
Normal file
@ -0,0 +1,108 @@
|
||||
import { apiGet } from '../api.js';
|
||||
import { getRole, pageHeaderHTML, showToast } from '../app.js';
|
||||
|
||||
export async function homeDashboardPage() {
|
||||
const app = document.getElementById('app');
|
||||
const role = getRole();
|
||||
const isAdmin = role === 'admin';
|
||||
|
||||
app.innerHTML = `
|
||||
${pageHeaderHTML('Overview', '', {
|
||||
subtitle: `Ressourcenbarometer administration for your ${role === 'admin' ? 'organization' : 'supervised counselors'}`,
|
||||
})}
|
||||
<div id="homeDashboardContent"><div class="spinner"></div></div>
|
||||
`;
|
||||
|
||||
try {
|
||||
const ov = await apiGet('analytics.php?overview=1');
|
||||
renderHomeDashboard(ov, isAdmin);
|
||||
} catch (e) {
|
||||
showToast(e.message, 'error');
|
||||
document.getElementById('homeDashboardContent').innerHTML =
|
||||
`<p class="error-text">${esc(e.message)}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
function renderHomeDashboard(ov, isAdmin) {
|
||||
const el = document.getElementById('homeDashboardContent');
|
||||
|
||||
const qPreview = (ov.questionnaires || []).slice(0, 6).map(q => `
|
||||
<tr>
|
||||
<td>${esc(q.name)}</td>
|
||||
<td>${q.completedCount ?? 0} / ${q.eligibleCount ?? 0}</td>
|
||||
<td>${q.completionRatio ?? 0}%</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
const links = [
|
||||
{ href: '#/questionnaires', label: 'Session measures', desc: 'Edit instruments, order, and categories' },
|
||||
{ href: '#/clients', label: 'Clients', desc: 'Client codes, counselors, response history' },
|
||||
{ href: '#/coaches', label: 'Counselor activity', desc: 'Uploads and workload per counselor' },
|
||||
{ href: '#/insights', label: 'Insights', desc: 'Charts, completion rates, follow-up' },
|
||||
{ href: '#/export', label: 'Export data', desc: 'Download CSV and bundles' },
|
||||
{ href: '#/assignments', label: 'Assign clients', desc: 'Move clients between counselors' },
|
||||
{ href: '#/users', label: 'Users', desc: 'Admins, supervisors, and counselors' },
|
||||
{ href: '#/translations', label: 'Translations', desc: 'German source and other languages' },
|
||||
];
|
||||
if (isAdmin) {
|
||||
links.push({ href: '#/dev', label: 'Admin settings', desc: 'Dev import, exports, database tools' });
|
||||
}
|
||||
|
||||
el.innerHTML = `
|
||||
<div class="insights-kpi-grid">
|
||||
<a href="#/clients" class="insights-kpi card home-kpi-link">
|
||||
<div class="insights-kpi-value">${ov.clientCount ?? 0}</div>
|
||||
<div class="insights-kpi-label">Clients</div>
|
||||
</a>
|
||||
<a href="#/insights" class="insights-kpi card home-kpi-link">
|
||||
<div class="insights-kpi-value">${ov.clientsWithCompletions ?? 0}</div>
|
||||
<div class="insights-kpi-label">With completions</div>
|
||||
</a>
|
||||
<a href="#/coaches" class="insights-kpi card home-kpi-link">
|
||||
<div class="insights-kpi-value">${ov.submissionsLast7d ?? 0}</div>
|
||||
<div class="insights-kpi-label">Uploads (7 days)</div>
|
||||
</a>
|
||||
<a href="#/coaches" class="insights-kpi card home-kpi-link">
|
||||
<div class="insights-kpi-value">${ov.submissionsLast30d ?? 0}</div>
|
||||
<div class="insights-kpi-label">Uploads (30 days)</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-top:20px">
|
||||
<h3 style="margin:0 0 12px">Quick links</h3>
|
||||
<div class="home-link-grid">
|
||||
${links.map(l => `
|
||||
<a href="${l.href}" class="home-link-card">
|
||||
<span class="home-link-title">${esc(l.label)}</span>
|
||||
<span class="home-link-desc">${esc(l.desc)}</span>
|
||||
</a>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-top:20px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
|
||||
<h3 style="margin:0">Measure completion</h3>
|
||||
<a href="#/insights" class="btn btn-sm">Full report</a>
|
||||
</div>
|
||||
${(ov.questionnaires || []).length ? `
|
||||
<div class="table-wrapper">
|
||||
<table class="data-table data-table-compact">
|
||||
<thead>
|
||||
<tr><th>Session measure</th><th>Completed</th><th>Rate</th></tr>
|
||||
</thead>
|
||||
<tbody>${qPreview}${(ov.questionnaires.length > 6)
|
||||
? `<tr><td colspan="3" class="data-toolbar-hint" style="text-align:center">+ ${ov.questionnaires.length - 6} more — see Insights</td></tr>`
|
||||
: ''}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
` : '<p class="data-toolbar-hint">No active session measures.</p>'}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function esc(s) {
|
||||
const d = document.createElement('div');
|
||||
d.textContent = s ?? '';
|
||||
return d.innerHTML;
|
||||
}
|
||||
Reference in New Issue
Block a user