feat(feedback): improve feedback workflow
This commit is contained in:
+31
-17
@@ -25,24 +25,26 @@
|
||||
|
||||
function fbItemHtml(f) {
|
||||
const text = (f.text||'').trim();
|
||||
const short = text.length > 100 ? text.slice(0,97)+'…' : text;
|
||||
const del = f.deleted_at ? ' style="opacity:.5"' : '';
|
||||
return `<div class="feedback-item" data-id="${f.id}"${del}>
|
||||
<div class="col">${fmtDate(f.feedback_date)}</div>
|
||||
<div class="col">${escapeHtml(f.topic||'')}</div>
|
||||
<div class="col">${escapeHtml(f.resident||'')}</div>
|
||||
<div class="col">${fmtDay(f.feedback_date)}</div>
|
||||
<div class="col">${escapeHtml(f.group_name||'')}</div>
|
||||
<div class="col text">${escapeHtml(short)}</div>
|
||||
<div class="actions">
|
||||
const day = fmtDay(f.feedback_date);
|
||||
return `<div class="lesson-item feedback-item" data-id="${f.id}"${del}>
|
||||
<div class="lesson-item-head">
|
||||
<span class="lesson-group">${escapeHtml(f.group_name||'')}</span>
|
||||
<span class="lesson-when">${fmtDate(f.feedback_date)}${day ? ` · ${day}` : ''}</span>
|
||||
${f.deleted_at ? '<span class="lesson-badge">Удалён</span>' : ''}
|
||||
${aiBadge(f.ai_status)}
|
||||
${f.sent_at ? '<span class="ai-badge ai-badge-sent">Отправлено</span>' : ''}
|
||||
${f.ai_status === 'error' ? `<button class="btn-xs" data-retry="${f.id}">Повторить</button>` : ''}
|
||||
${f.deleted_at ? '' : `<button class="btn-xs ${f.sent_at ? 'sent-on' : ''}" data-sent="${f.id}">${f.sent_at ? 'Вернуть' : 'Отправлено'}</button>`}
|
||||
<button class="btn-xs" data-edit="${f.id}">Изменить</button>
|
||||
<button class="btn-xs danger" data-del="${f.id}">${f.deleted_at ? 'Удалить навсегда' : 'Удалить'}</button>
|
||||
${f.deleted_at ? `<button class="btn-xs" data-restore="${f.id}">Восстановить</button>` : ''}
|
||||
<div class="lesson-actions">
|
||||
${f.ai_status === 'error' ? `<button type="button" class="btn-link" data-retry="${f.id}">Повторить</button>` : ''}
|
||||
${f.deleted_at ? '' : `<button type="button" class="btn-link" data-sent="${f.id}">${f.sent_at ? 'Вернуть' : 'Отправлено'}</button>`}
|
||||
<button type="button" class="btn-link" data-edit="${f.id}">Изменить</button>
|
||||
<button type="button" class="btn-link danger" data-del="${f.id}">${f.deleted_at ? 'Удалить навсегда' : 'Удалить'}</button>
|
||||
${f.deleted_at ? `<button type="button" class="btn-link" data-restore="${f.id}">Восстановить</button>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
${f.resident ? `<div class="lesson-author">${escapeHtml(f.resident)}</div>` : ''}
|
||||
${f.topic ? `<div class="lesson-topic">${escapeHtml(f.topic)}</div>` : ''}
|
||||
${text ? `<div class="lesson-text">${escapeHtml(text)}</div>` : ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -175,7 +177,7 @@
|
||||
async function fetchShorts(q) {
|
||||
if (!q || q.length < 2) { shortsListCache = []; renderShorts([]); return; }
|
||||
try {
|
||||
const r = await fetch(`${API}/api/shorts?search=${encodeURIComponent(q)}&limit=50&deleted=0`, { headers: hdr() });
|
||||
const r = await fetch(`${API}/api/shorts?search=${encodeURIComponent(q)}&limit=50&deleted=0&used=0`, { headers: hdr() });
|
||||
if (r.ok) {
|
||||
const j = await r.json();
|
||||
shortsListCache = j.items || []; renderShorts(shortsListCache);
|
||||
@@ -183,6 +185,18 @@
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
async function loadLastPastReview() {
|
||||
const resident = document.getElementById('fbResident').value.trim();
|
||||
if (!resident) return;
|
||||
try {
|
||||
const r = await fetch(`${API}/api/feedbacks/last?resident=${encodeURIComponent(resident)}`, { headers: hdr() });
|
||||
if (r.ok) {
|
||||
const row = await r.json();
|
||||
if (row && row.text) document.getElementById('fbPastReview').value = row.text;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function renderShorts(items) {
|
||||
const wrap = document.getElementById('fbShortsWrap');
|
||||
const list = document.getElementById('fbShortsList');
|
||||
@@ -335,6 +349,7 @@
|
||||
document.getElementById('fbResident').addEventListener('change', applyResidentGroup);
|
||||
document.getElementById('fbPastCheck').addEventListener('change', e => {
|
||||
document.getElementById('fbPastReviewWrap').style.display = e.target.checked ? '' : 'none';
|
||||
if (e.target.checked) loadLastPastReview();
|
||||
});
|
||||
document.getElementById('fbText').addEventListener('input', () => {
|
||||
document.getElementById('fbTextHint').textContent = `${document.getElementById('fbText').value.length} / 5000`;
|
||||
@@ -370,11 +385,10 @@
|
||||
return;
|
||||
}
|
||||
});
|
||||
['fbSearch','fbGroupFilter','fbStatusFilter','fbDateFrom','fbDateTo'].forEach(id => {
|
||||
['fbSearch','fbGroupFilter','fbStatusFilter','fbDateFrom','fbDateTo','fbDeletedToggle'].forEach(id => {
|
||||
document.getElementById(id).addEventListener('change', () => { page = 1; loadFeedbacks(); });
|
||||
if (id === 'fbSearch') document.getElementById(id).addEventListener('input', () => { clearTimeout(searchTimer); searchTimer = setTimeout(() => { page = 1; loadFeedbacks(); }, 350); });
|
||||
});
|
||||
document.getElementById('fbDeletedToggle').addEventListener('change', () => { page = 1; loadFeedbacks(); });
|
||||
if (window.lucide) lucide.createIcons();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user