/** * @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); }