import { apiClient } from '../shared/api-client.js'; export const SUBJECT_TABLE_COLUMNS = 6; export const SUBJECT_PAGE_SIZES = [25, 50, 100]; export const SUBJECT_SORT_OPTIONS = Object.freeze([ { value: 'name,asc', label: 'По названию А–Я' }, { value: 'name,desc', label: 'По названию Я–А' }, { value: 'code,asc', label: 'По коду' }, { value: 'departmentId,asc', label: 'По кафедре' } ]); const DEFAULT_STATE = Object.freeze({ query: '', departmentId: '', page: 0, size: 25, sort: 'name,asc' }); export function normalizeSubjectsState(restored = {}) { const size = Number(restored.subjectSize); return { query: restored.subjectQuery || '', departmentId: restored.subjectDepartment || '', page: Math.max(Number(restored.subjectPage) || 0, 0), size: SUBJECT_PAGE_SIZES.includes(size) ? size : 25, sort: SUBJECT_SORT_OPTIONS.some(option => option.value === restored.subjectSort) ? restored.subjectSort : 'name,asc' }; } export function initialSubjectsState(restored = {}) { return normalizeSubjectsState(restored); } export function defaultSubjectsState() { return { ...DEFAULT_STATE }; } export function subjectsQueryParams(state) { const [sort, direction] = String(state.sort || 'name,asc').split(','); const params = new URLSearchParams({ query: state.query || '', page: String(state.page || 0), size: String(state.size || 25), sort, direction }); if (state.departmentId) params.set('departmentId', state.departmentId); return `/api/subjects/page?${params}`; } export function subjectsUrlState(state) { return { subjectQuery: state.query || '', subjectDepartment: state.departmentId || '', subjectPage: state.page || '', subjectSize: state.size === 25 ? '' : state.size, subjectSort: state.sort === 'name,asc' ? '' : state.sort }; } export function fetchDepartments(client = apiClient) { return client.get('/api/departments', { errorMessage: 'Не удалось загрузить список кафедр' }); } export function fetchSubjectsPage(state, client = apiClient) { return client.get(subjectsQueryParams(state), { errorMessage: 'Не удалось загрузить дисциплины' }); } export function teacherAssignmentsEndpoint(subjectIds) { const params = new URLSearchParams(); (subjectIds || []).forEach(subjectId => params.append('subjectId', subjectId)); return `/api/teacher-subjects?${params}`; } export function fetchTeacherAssignments(subjectIds, client = apiClient) { if (!(subjectIds || []).length) return Promise.resolve([]); return client.get( teacherAssignmentsEndpoint(subjectIds), { errorMessage: 'Не удалось загрузить привязки преподавателей' } ); } export function createSubject({ name, code, departmentId }, client = apiClient) { return client.post( '/api/subjects', { name, code, departmentId: Number(departmentId) }, { errorMessage: 'Ошибка создания' } ); } export function archiveSubject(id, client = apiClient) { return client.delete(`/api/subjects/${id}`, { errorMessage: 'Ошибка архивирования' }); } export function assignTeacher({ userId, subjectId }, client = apiClient) { return client.post( '/api/teacher-subjects', { userId: Number(userId), subjectId: Number(subjectId) }, { errorMessage: 'Ошибка привязки' } ); } export function removeTeacherAssignment({ userId, subjectId }, client = apiClient) { return client.delete('/api/teacher-subjects', { json: { userId: Number(userId), subjectId: Number(subjectId) }, errorMessage: 'Ошибка удаления привязки' }); } export function teachersSearchEndpoint(query, selectedId) { const params = new URLSearchParams({ query, limit: '30' }); if (selectedId) params.set('selectedId', selectedId); return `/api/users/teachers/options?${params}`; } export function departmentLabel(departments, departmentId) { const department = (departments || []).find(item => String(item.id) === String(departmentId)); if (!department) return departmentId || '-'; return department.departmentName || department.name || departmentId; } export function departmentOptionLabel(department) { const name = department.departmentName || department.name || 'Без названия'; const code = department.departmentCode || department.code || department.id; return `${name} (${code})`; } export function groupTeachersBySubject(assignments) { const grouped = new Map(); (assignments || []).forEach(assignment => { const key = String(assignment.subjectId); if (!grouped.has(key)) grouped.set(key, []); grouped.get(key).push(assignment); }); return grouped; } export function subjectContextLabel(subject) { return `${subject.code ? `${subject.code} · ` : ''}${subject.name}`; } export function subjectsEmptyMessage(state) { return state.query || state.departmentId ? 'Дисциплины не найдены' : 'Дисциплин пока нет'; } export function normalizePageState(state, page) { const nextPage = Number(page); return { ...state, page: Number.isFinite(nextPage) && nextPage > 0 ? nextPage : 0 }; }