Много разных изменений
This commit is contained in:
@@ -1,36 +1,72 @@
|
||||
import { api } from '../api.js';
|
||||
import { escapeHtml, hideAlert, renderTableMessage, showAlert } from '../utils.js';
|
||||
import { promptAction } from '../dialog.js';
|
||||
import { renderPagination } from '../pagination.js';
|
||||
import { debounce, readUrlState, writeUrlState } from '../url-state.js';
|
||||
import { markTableReady, renderTableEmpty, renderTableError, renderTableLoading } from '../view-state.js';
|
||||
import { trackUxEvent } from '../../../telemetry.js';
|
||||
|
||||
export async function initTeacherRequests() {
|
||||
const requestsTbody = document.getElementById('teacher-requests-tbody');
|
||||
const refreshButton = document.getElementById('teacher-requests-refresh');
|
||||
const requestsCount = document.getElementById('teacher-requests-count');
|
||||
const searchInput = document.getElementById('teacher-requests-search');
|
||||
const statusSelect = document.getElementById('teacher-requests-status');
|
||||
const pagination = document.getElementById('teacher-requests-pagination');
|
||||
let departments = [];
|
||||
const restored = readUrlState({ requestQuery: '', requestStatus: 'PENDING', requestPage: '0', requestSize: '25' });
|
||||
const state = {
|
||||
query: restored.requestQuery,
|
||||
status: restored.requestStatus,
|
||||
page: Math.max(Number(restored.requestPage) || 0, 0),
|
||||
size: [25, 50, 100].includes(Number(restored.requestSize)) ? Number(restored.requestSize) : 25
|
||||
};
|
||||
searchInput.value = state.query;
|
||||
statusSelect.value = state.status;
|
||||
|
||||
async function loadDepartments() {
|
||||
departments = await api.get('/api/departments');
|
||||
}
|
||||
|
||||
async function loadRequests() {
|
||||
requestsTbody.innerHTML = '<tr><td colspan="7" class="loading-row">Загрузка...</td></tr>';
|
||||
renderTableLoading(requestsTbody, 7, 'Загрузка заявок...');
|
||||
hideAlert('teacher-requests-alert');
|
||||
try {
|
||||
const requests = await api.get('/api/teacher-requests?status=PENDING');
|
||||
const normalizedRequests = Array.isArray(requests) ? requests : [];
|
||||
const params = new URLSearchParams({
|
||||
query: state.query,
|
||||
page: String(state.page),
|
||||
size: String(state.size),
|
||||
sort: 'createdAt',
|
||||
direction: 'desc'
|
||||
});
|
||||
if (state.status) params.set('status', state.status);
|
||||
const page = await api.get(`/api/teacher-requests/page?${params}`);
|
||||
if (!(page.items || []).length && page.totalItems > 0 && state.page > 0) {
|
||||
state.page = Math.max(0, page.totalPages - 1);
|
||||
return loadRequests();
|
||||
}
|
||||
const normalizedRequests = page.items || [];
|
||||
renderRequests(normalizedRequests);
|
||||
updateCount(normalizedRequests.length);
|
||||
updateCount(Number(page.totalItems || 0));
|
||||
renderPagination(pagination, page, {
|
||||
label: 'заявок',
|
||||
onPage: nextPage => { state.page = nextPage; loadRequests(); },
|
||||
onSize: size => { state.size = size; state.page = 0; loadRequests(); }
|
||||
});
|
||||
persistState();
|
||||
document.dispatchEvent(new CustomEvent('teacherRequestsChanged', {
|
||||
detail: { count: normalizedRequests.length }
|
||||
detail: { count: state.status === 'PENDING' && !state.query ? Number(page.totalItems || 0) : undefined }
|
||||
}));
|
||||
trackUxEvent('реестр_заявок_загружен', { total: Number(page.totalItems || 0), page: state.page });
|
||||
} catch (error) {
|
||||
renderTableMessage(requestsTbody, 7, 'Не удалось загрузить заявки преподавателей');
|
||||
renderTableError(requestsTbody, 7, 'Не удалось загрузить заявки преподавателей', loadRequests);
|
||||
updateCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
function renderRequests(requests) {
|
||||
if (!requests.length) {
|
||||
requestsTbody.innerHTML = '<tr><td colspan="7" class="loading-row">Нет заявок на рассмотрении</td></tr>';
|
||||
renderTableEmpty(requestsTbody, 7, state.query ? 'Заявки не найдены' : 'Заявок с выбранным статусом нет');
|
||||
return;
|
||||
}
|
||||
requestsTbody.innerHTML = requests.map(request => `
|
||||
@@ -51,12 +87,15 @@ export async function initTeacherRequests() {
|
||||
<td>${escapeHtml(request.comment || '-')}</td>
|
||||
<td>
|
||||
<div class="teacher-request-actions">
|
||||
<button type="button" class="btn btn-sm btn-primary teacher-request-approve">Одобрить</button>
|
||||
<button type="button" class="btn btn-sm btn-danger-subtle teacher-request-reject">Отклонить</button>
|
||||
${request.status === 'PENDING' ? `
|
||||
<button type="button" class="btn btn-sm btn-primary teacher-request-approve">Одобрить</button>
|
||||
<button type="button" class="btn btn-sm btn-danger-subtle teacher-request-reject">Отклонить</button>
|
||||
` : `<span class="badge">${escapeHtml(request.status === 'APPROVED' ? 'Одобрена' : 'Отклонена')}</span>`}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
markTableReady(requestsTbody);
|
||||
}
|
||||
|
||||
function updateCount(count) {
|
||||
@@ -98,7 +137,18 @@ export async function initTeacherRequests() {
|
||||
}
|
||||
|
||||
async function rejectRequest(requestId) {
|
||||
const reviewComment = prompt('Причина отклонения');
|
||||
const reviewComment = await promptAction({
|
||||
title: 'Отклонить заявку?',
|
||||
message: 'Комментарий увидит кафедра, отправившая заявку.',
|
||||
confirmLabel: 'Отклонить',
|
||||
danger: true,
|
||||
input: {
|
||||
label: 'Причина отклонения',
|
||||
placeholder: 'Укажите, что нужно исправить',
|
||||
required: true,
|
||||
requiredMessage: 'Укажите причину отклонения'
|
||||
}
|
||||
});
|
||||
if (reviewComment === null) return;
|
||||
try {
|
||||
await api.post(`/api/teacher-requests/${encodeURIComponent(requestId)}/reject`, { reviewComment });
|
||||
@@ -110,6 +160,16 @@ export async function initTeacherRequests() {
|
||||
}
|
||||
|
||||
refreshButton?.addEventListener('click', loadRequests);
|
||||
searchInput.addEventListener('input', debounce(() => {
|
||||
state.query = searchInput.value.trim();
|
||||
state.page = 0;
|
||||
loadRequests();
|
||||
}));
|
||||
statusSelect.addEventListener('change', () => {
|
||||
state.status = statusSelect.value;
|
||||
state.page = 0;
|
||||
loadRequests();
|
||||
});
|
||||
|
||||
requestsTbody.addEventListener('click', async (event) => {
|
||||
const approveButton = event.target.closest('.teacher-request-approve');
|
||||
@@ -133,4 +193,13 @@ export async function initTeacherRequests() {
|
||||
} catch (error) {
|
||||
renderTableMessage(requestsTbody, 7, 'Не удалось загрузить заявки преподавателей');
|
||||
}
|
||||
|
||||
function persistState() {
|
||||
writeUrlState({
|
||||
requestQuery: state.query,
|
||||
requestStatus: state.status === 'PENDING' ? '' : state.status,
|
||||
requestPage: state.page || '',
|
||||
requestSize: state.size === 25 ? '' : state.size
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user