import { apiClient } from '../shared/api-client.js'; export const REQUEST_TABLE_COLUMNS = 7; export const REQUEST_PAGE_SIZES = [25, 50, 100]; export const REQUEST_STATUS_OPTIONS = Object.freeze([ { value: 'PENDING', label: 'Ожидают рассмотрения' }, { value: 'APPROVED', label: 'Одобрены' }, { value: 'REJECTED', label: 'Отклонены' }, { value: '', label: 'Все статусы' } ]); export function normalizeTeacherRequestsState(restored = {}) { const size = Number(restored.requestSize); return { query: restored.requestQuery || '', status: restored.requestStatus || 'PENDING', page: Math.max(Number(restored.requestPage) || 0, 0), size: REQUEST_PAGE_SIZES.includes(size) ? size : 25 }; } export function initialTeacherRequestsState(restored = {}) { return normalizeTeacherRequestsState(restored); } export function teacherRequestsQueryParams(state) { const params = new URLSearchParams({ query: state.query || '', page: String(state.page || 0), size: String(state.size || 25), sort: 'createdAt', direction: 'desc' }); if (state.status) params.set('status', state.status); return `/api/teacher-requests/page?${params}`; } export function teacherRequestsUrlState(state) { return { requestQuery: state.query || '', requestStatus: state.status === 'PENDING' ? '' : state.status, requestPage: state.page || '', requestSize: state.size === 25 ? '' : state.size }; } // --- Справочники --- export function fetchDepartments(client = apiClient) { return client.get('/api/departments', { errorMessage: 'Не удалось загрузить список кафедр' }); } // Кафедра в строке заявки подписывается только названием — как в legacy-реестре. export function requestDepartmentLabel(department) { return department.departmentName || department.name || department.id; } // --- Реестр заявок --- export function fetchTeacherRequestsPage(state, client = apiClient) { return client.get(teacherRequestsQueryParams(state), { errorMessage: 'Не удалось загрузить заявки преподавателей' }); } export function teacherRequestsEmptyMessage(state) { return state.query ? 'Заявки не найдены' : 'Заявок с выбранным статусом нет'; } export function reviewedStatusLabel(status) { return status === 'APPROVED' ? 'Одобрена' : 'Отклонена'; } // Счётчик в sidebar обновляется событием teacherRequestsChanged: он актуален // только когда реестр показывает нефильтрованный список ожидающих заявок. export function pendingCountDetail(state, totalItems) { return { count: state.status === 'PENDING' && !state.query ? Number(totalItems || 0) : undefined }; } // --- Одобрение и отклонение --- export function approvePayloadFromFields(fields) { const payload = { departmentId: Number(fields.departmentId), username: (fields.username || '').trim(), fullName: (fields.fullName || '').trim(), jobTitle: (fields.jobTitle || '').trim(), password: fields.password }; if (!payload.departmentId || !payload.username || !payload.fullName || !payload.password) { return { error: 'Заполните кафедру, логин, ФИО и пароль' }; } if (payload.password.length < 8) { return { error: 'Пароль должен быть не короче 8 символов' }; } return { payload }; } export function approveRequest(id, payload, client = apiClient) { return client.post( `/api/teacher-requests/${encodeURIComponent(id)}/approve`, payload, { errorMessage: 'Ошибка одобрения заявки' } ); } export function rejectRequest(id, reviewComment, client = apiClient) { return client.post( `/api/teacher-requests/${encodeURIComponent(id)}/reject`, { reviewComment }, { errorMessage: 'Ошибка отклонения заявки' } ); }