import { apiClient } from '../shared/api-client.js'; import { capabilitiesForRole } from '../../admin/js/role-capabilities.js'; export const SETTINGS_TABS = Object.freeze([ { id: 'general', title: 'Общие настройки' }, { id: 'time-slots', title: 'Временные слоты' }, { id: 'edu-forms', title: 'Формы обучения' }, { id: 'database', title: 'База данных' } ]); const APPLY_MODE_LABELS = Object.freeze({ DEFAULT: 'применяется по умолчанию', WEEKDAY: 'применяется автоматически', MANUAL: 'применяется вручную' }); const DAY_SHORT_LABELS = Object.freeze({ 1: 'Пн', 2: 'Вт', 3: 'Ср', 4: 'Чт', 5: 'Пт', 6: 'Сб', 7: 'Вс' }); export function settingsTabsForRole(role) { const capabilities = capabilitiesForRole(role); if (!capabilities || capabilities.settingsTabs.length === 0) return []; const allowed = new Set(capabilities.settingsTabs); return SETTINGS_TABS.filter(tab => allowed.has(tab.id)); } export function defaultSettingsTabForRole(role) { const capabilities = capabilitiesForRole(role); return capabilities ? capabilities.defaultSettingsTab : null; } export function applyModeLabel(mode) { return APPLY_MODE_LABELS[mode] || mode || '—'; } export function dayShort(dayOfWeek) { return DAY_SHORT_LABELS[Number(dayOfWeek)] || '-'; } export function scopeOptionLabel(scope) { const suffix = scope.applyMode === 'WEEKDAY' ? `, ${dayShort(scope.dayOfWeek)}` : ''; return `${scope.name} - ${applyModeLabel(scope.applyMode)}${suffix}`; } export function scopeBadgeLabel(scope) { if (scope.applyMode === 'DEFAULT') return 'Базовая'; if (scope.applyMode === 'WEEKDAY') return dayShort(scope.dayOfWeek); return 'Ручная'; } export function scopeBadgeClass(scope) { return scope.applyMode === 'DEFAULT' ? 'scope-badge scope-badge-base' : 'scope-badge'; } export function scopeSummaryText(scope, slots) { const mode = applyModeLabel(scope.applyMode); const day = scope.applyMode === 'WEEKDAY' ? `, ${dayShort(scope.dayOfWeek)}` : ''; const slotCount = slotsForScope(slots, scope.id).length; return `${mode}${day}. Слотов: ${slotCount}.`; } export function isSystemScope(scope) { return Boolean(scope && scope.systemScope); } export function defaultScopeId(scopes) { const found = (scopes || []).find(scope => scope.applyMode === 'DEFAULT'); return found ? found.id : (scopes || [])[0]?.id || null; } export function resolveActiveScopeId(scopes, preferredId) { const list = scopes || []; if (preferredId && list.some(scope => scope.id === preferredId)) return preferredId; return defaultScopeId(list); } export function slotsForScope(slots, scopeId) { return (slots || []) .filter(slot => slot.scopeId === scopeId) .sort((left, right) => (left.orderNumber || 0) - (right.orderNumber || 0)); } export function validateSlotPayload({ scopeId, orderNumber, startTime = '', endTime = '' } = {}) { if (!scopeId) return 'Выберите сетку времени'; if (!orderNumber || orderNumber <= 0) return 'Укажите номер пары'; if (!startTime || !endTime) return 'Укажите время начала и окончания'; if (startTime >= endTime) return 'Время начала должно быть раньше времени окончания'; return ''; } export function slotDurationMinutes(startTime = '', endTime = '') { if (!startTime || !endTime || startTime >= endTime) return null; const [startHour, startMinute] = startTime.split(':').map(Number); const [endHour, endMinute] = endTime.split(':').map(Number); return (endHour * 60 + endMinute) - (startHour * 60 + startMinute); } export function buildSlotPayload({ id = '', orderNumber, scopeId, startTime, endTime }) { return { id: id ? Number(id) : null, orderNumber: Number(orderNumber), scopeId, startTime, endTime }; } export function validateTenantFields({ name = '', domain = '', url = '' } = {}) { if (!name.trim() || !domain.trim() || !url.trim()) { return 'Заполните все обязательные поля'; } return ''; } export function normalizeDomain(domain = '') { return domain.trim().toLowerCase(); } export async function fetchScopes(client = apiClient) { return client.get('/api/admin/time-slots/scopes', { errorMessage: 'Не удалось загрузить сетки времени' }); } export async function createScope(name, client = apiClient) { return client.post( '/api/admin/time-slots/scopes', { name }, { errorMessage: 'Не удалось создать сетку времени' } ); } export async function deleteScope(id, client = apiClient) { return client.delete( `/api/admin/time-slots/scopes/${encodeURIComponent(id)}`, { errorMessage: 'Не удалось удалить сетку времени' } ); } export async function fetchTimeSlots(client = apiClient) { return client.get('/api/admin/time-slots', { errorMessage: 'Не удалось загрузить временные слоты' }); } export async function saveTimeSlot(payload, client = apiClient) { const options = { errorMessage: 'Не удалось сохранить временной слот' }; return payload.id ? client.put(`/api/admin/time-slots/${encodeURIComponent(payload.id)}`, payload, options) : client.post('/api/admin/time-slots', payload, options); } export async function deleteTimeSlot(id, client = apiClient) { return client.delete( `/api/admin/time-slots/${encodeURIComponent(id)}`, { errorMessage: 'Не удалось удалить временной слот' } ); } export async function fetchEducationForms(client = apiClient) { return client.get('/api/education-forms', { errorMessage: 'Не удалось загрузить формы обучения' }); } export async function createEducationForm(name, client = apiClient) { return client.post( '/api/education-forms', { name }, { errorMessage: 'Не удалось создать форму обучения' } ); } export async function deleteEducationForm(id, client = apiClient) { return client.delete( `/api/education-forms/${encodeURIComponent(id)}`, { errorMessage: 'Не удалось удалить форму обучения' } ); } export async function fetchDatabaseStatus(client = apiClient) { return client.get('/api/database/status', { errorMessage: 'Не удалось загрузить статус подключения' }); } export async function fetchTenants(client = apiClient) { return client.get('/api/database/tenants', { errorMessage: 'Не удалось загрузить список тенантов' }); } export async function testTenantConnection({ url, username, password }, client = apiClient) { return client.post( '/api/database/test', { password, url, username }, { errorMessage: 'Не удалось проверить подключение' } ); } export async function createTenant({ name, domain, url, username, password }, client = apiClient) { return client.post( '/api/database/tenants', { domain, name, password, url, username }, { errorMessage: 'Не удалось добавить тенант' } ); } export async function deleteTenant(domain, client = apiClient) { return client.delete( `/api/database/tenants/${encodeURIComponent(domain)}`, { errorMessage: 'Не удалось удалить тенант' } ); }