/** * @fileoverview Calendar API - обертка над API календаря с кешированием * @module api/calendarApi */ import { dataManager } from '../managers/dataManager.js'; import { authHeaders } from '../utils/authUtils.js'; import { API_URLS, API_DEFAULTS } from '../constants/apiUrls.js'; /** * Получить события календаря * @param {Object} params - Параметры запроса * @param {string} params.start - Дата начала (YYYY-MM-DD) * @param {string} params.end - Дата конца (YYYY-MM-DD) * @param {number} [params.department_id] - ID отдела (опционально) * @param {number} [ttl] - Time to live кеша в мс * @returns {Promise} Массив событий */ export async function getCalendarEvents(params, ttl = API_DEFAULTS.TTL.EVENTS) { // Создаем уникальный ключ для кеша const sortedParams = Object.keys(params).sort().reduce((acc, key) => { acc[key] = params[key]; return acc; }, {}); const key = `calendar:events:${JSON.stringify(sortedParams)}`; return dataManager.fetch( key, async () => { const url = new URL(API_URLS.EVENTS, window.location.origin); Object.keys(params).forEach(k => { if (params[k] != null) { url.searchParams.set(k, String(params[k])); } }); const response = await fetch(url.toString(), { headers: authHeaders() }); if (response.status === 401) { console.warn('[CalendarAPI] 401 Unauthorized'); return []; } if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); // Поддержка разных форматов ответа return Array.isArray(data) ? data : data.results || data.items || data.events || []; }, ttl ); } /** * Получить событие по ID * @param {number|string} eventId - ID события * @param {number} [ttl] - Time to live кеша в мс * @returns {Promise} Событие */ export async function getCalendarEvent(eventId, ttl = API_DEFAULTS.TTL.EVENT_DETAIL) { const key = `calendar:event:${eventId}`; return dataManager.fetch( key, async () => { const url = API_URLS.EVENT_DETAIL(eventId); const response = await fetch(url, { headers: authHeaders(false) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return response.json(); }, ttl ); } /** * Инвалидировать кеш событий календаря * @param {Object} [params] - Параметры для инвалидации (если не указаны, инвалидируется весь кеш) */ export function invalidateCalendarEvents(params = null) { if (params) { const sortedParams = Object.keys(params).sort().reduce((acc, key) => { acc[key] = params[key]; return acc; }, {}); const key = `calendar:events:${JSON.stringify(sortedParams)}`; dataManager.invalidate(key); } else { // Инвалидируем все события календаря dataManager.invalidatePattern(/^calendar:events:/); } } /** * Инвалидировать кеш конкретного события * @param {number|string} eventId - ID события */ export function invalidateCalendarEvent(eventId) { dataManager.invalidate(`calendar:event:${eventId}`); } /** * Пре-загрузить события в кеш (например, из SSR данных) * @param {Object} params - Параметры запроса * @param {Array} events - Данные событий */ export function preloadCalendarEvents(params, events) { const sortedParams = Object.keys(params).sort().reduce((acc, key) => { acc[key] = params[key]; return acc; }, {}); const key = `calendar:events:${JSON.stringify(sortedParams)}`; dataManager.preload(key, events); }