/* ============================================================ assessments.js — Assessments listing & assign ============================================================ */ window.Views = window.Views || {}; window.Assessments = {}; Views.assessments = function () { const filters = { q: '', status: '', type: '' }; let table; const stats = { total: DB.assessments.length, completed: DB.assessments.filter(a => a.status === 'Completed').length, pending: DB.assessments.filter(a => ['Pending', 'In Progress'].includes(a.status)).length, avg: Math.round(DB.assessments.filter(a => a.score).reduce((s, a) => s + a.score, 0) / (DB.assessments.filter(a => a.score).length || 1)) }; function apply() { const rows = DB.assessments.filter(a => { if (filters.status && a.status !== filters.status) return false; if (filters.type && a.type !== filters.type) return false; if (filters.q && !(a.candidate + a.jobTitle + a.type).toLowerCase().includes(filters.q.toLowerCase())) return false; return true; }); table.update(rows); } table = UI.dataTable({ pageSize: 8, rows: DB.assessments, columns: [ { key: 'candidate', label: 'Candidate', sortable: true, render: a => `
${UI.avatar(a.candidate, a.initials, a.color)}
${a.candidate}
${a.jobTitle}
` }, { key: 'type', label: 'Assessment', sortable: true, render: a => `
${a.type}
${a.duration}
` }, { key: 'assigned', label: 'Assigned', sortable: true, sortValue: a => a.assigned.getTime(), render: a => `${DB.fmtShort(a.assigned)}` }, { key: 'due', label: 'Due', sortable: true, sortValue: a => a.due.getTime(), render: a => `${DB.fmtShort(a.due)}` }, { key: 'score', label: 'Score', sortable: true, align: 'center', render: a => a.score !== null ? UI.scoreChip(a.score) : '' }, { key: 'status', label: 'Status', sortable: true, render: a => UI.badge(a.status) }, { key: '_a', label: 'Actions', align: 'right', render: a => `
` } ] }); const statusOpts = [''].concat(['Completed', 'In Progress', 'Pending', 'Expired'].map(s => ``)).join(''); const typeOpts = [''].concat([...new Set(DB.assessments.map(a => a.type))].map(t => ``)).join(''); const statCard = (label, val, icn, cls) => `
${label}${UI.icon(icn)}
${val}
`; const html = `

Assessments

Coding tests, take-homes, and evaluations

${statCard('Total Assigned', stats.total, 'file', 'i-indigo')} ${statCard('Completed', stats.completed, 'check-circle', 'i-green')} ${statCard('In Progress / Pending', stats.pending, 'clock', 'i-amber')} ${statCard('Average Score', stats.avg + '%', 'target', 'i-teal')}
${table.html}
`; return { html, onMount() { table.mount(); const s = document.getElementById('asSearch'); s.oninput = () => { filters.q = s.value; apply(); }; document.getElementById('asStatus').onchange = e => { filters.status = e.target.value; apply(); }; document.getElementById('asType').onchange = e => { filters.type = e.target.value; apply(); }; } }; }; Assessments.view = function (id) { const a = DB.assessments.find(x => x.id === id); const body = `
${UI.avatar(a.candidate, a.initials, a.color, 'avatar-lg')}
${a.candidate}
${a.type} · ${a.jobTitle}
${UI.badge(a.status)}
Type
${a.type}
Duration
${a.duration}
Assigned
${DB.fmtDate(a.assigned)}
Due
${DB.fmtDate(a.due)}
${a.score !== null ? `
${a.score}%
Overall Score
${UI.pbar(a.score)}
Section Breakdown
${['Problem Solving', 'Code Quality', 'Communication', 'Time Management'].map(sec => { const sc = DB.int(60, 98); return `
${sec}
${UI.pbar(sc)}
${sc}%
`; }).join('')}` : `
${UI.icon('clock')}

Assessment not completed

Results will appear once the candidate submits.

`}`; const footer = ` `; UI.modal({ title: 'Assessment Result', subtitle: a.id, body, footer }); }; Assessments.assign = function () { const opt = arr => arr.map(o => ``).join(''); const body = `
`; const footer = ` `; UI.modal({ title: 'Assign Assessment', subtitle: 'Send an evaluation to a candidate', body, footer }); };