From dd64d5f540f68dbb25d648afe74f341b9b1a9165 Mon Sep 17 00:00:00 2001 From: igor_nadein Date: Tue, 24 Feb 2026 18:12:28 +0300 Subject: [PATCH] feat: replace old calendar with django-scheduler in frontend - Removed legacy calendar with department_id/employee_id filters - New CalendarCard loads calendars from django-scheduler API - Events filtered by calendar ID instead of legacy params - Removed unused SidebarCalendarOption type --- backend/api/v1/urls.py | 18 +---- backend/eusrr_backend/settings.py | 3 +- frontend/src/components/AppShell.tsx | 111 +++++++++++++-------------- 3 files changed, 58 insertions(+), 74 deletions(-) diff --git a/backend/api/v1/urls.py b/backend/api/v1/urls.py index 98865207..78baa6e8 100644 --- a/backend/api/v1/urls.py +++ b/backend/api/v1/urls.py @@ -1,13 +1,7 @@ from django.urls import include, path from rest_framework.routers import DefaultRouter -from .calendar.views import ( - CalendarEventsViewSet, - CalendarSubscriptionViewSet, - CalendarViewSet, -) - -# django-scheduler ViewSets (новая система, проверенный код) +# django-scheduler ViewSets (проверенная библиотека для календаря) from .schedule.views import ( ScheduleCalendarViewSet, ScheduleEventViewSet, @@ -38,15 +32,7 @@ app_name = "v1" router = DefaultRouter() -router.register(r"calendar/events", CalendarEventsViewSet, basename="events") -router.register(r"calendar/calendars", CalendarViewSet, basename="calendars") -router.register( - r"calendar/subscriptions", - CalendarSubscriptionViewSet, - basename="subscriptions", -) - -# django-scheduler endpoints (новая система) +# django-scheduler endpoints (проверенная библиотека) router.register(r"schedule/calendars", ScheduleCalendarViewSet, basename="schedule-calendars") router.register(r"schedule/events", ScheduleEventViewSet, basename="schedule-events") router.register(r"schedule/rules", ScheduleRuleViewSet, basename="schedule-rules") diff --git a/backend/eusrr_backend/settings.py b/backend/eusrr_backend/settings.py index 2f7b8e47..20e41669 100644 --- a/backend/eusrr_backend/settings.py +++ b/backend/eusrr_backend/settings.py @@ -42,8 +42,7 @@ INSTALLED_APPS = [ "employees.apps.EmployeesConfig", "api.apps.ApiConfig", "hikcentral.apps.HikcentralConfig", - "calendar_app.apps.CalendarAppConfig", - "schedule", # django-scheduler (новая система, параллельно с calendar_app) + "schedule", # django-scheduler (проверенная библиотека для календаря) "documents.apps.DocumentsConfig", "requests_app.apps.RequestsAppConfig", "feed.apps.FeedConfig", diff --git a/frontend/src/components/AppShell.tsx b/frontend/src/components/AppShell.tsx index 77afdaad..7197542c 100644 --- a/frontend/src/components/AppShell.tsx +++ b/frontend/src/components/AppShell.tsx @@ -48,14 +48,6 @@ type SidebarCalendarEvent = { color?: string | null; }; -type SidebarCalendarOption = { - id: string; - title: string; - color?: string | null; - /** Параметры для запроса событий */ - queryParams: Record; -}; - const pad = (v: number) => String(v).padStart(2, "0"); const formatDateKey = (date: Date) => `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`; @@ -296,48 +288,54 @@ function LeftNav() { } function CalendarCard() { - const { user } = useUser(); const [monthDate, setMonthDate] = useState(() => { const now = new Date(); return new Date(now.getFullYear(), now.getMonth(), 1); }); const [events, setEvents] = useState([]); - const [selectedCalendarKey, setSelectedCalendarKey] = useState("company"); + const [calendars, setCalendars] = useState>([]); + const [selectedCalendarId, setSelectedCalendarId] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); - // Строим список вариантов из данных пользователя (legacy: department_id / employee_id) - const calendarOptions = useMemo(() => { - const opts: SidebarCalendarOption[] = [ - { id: "company", title: "Компания", queryParams: {} }, - ]; - - // Отделы пользователя - if (user?.departments) { - user.departments.forEach((dept) => { - opts.push({ - id: `dept-${dept.id}`, - title: dept.name, - queryParams: { department_id: dept.id }, - }); - }); - } - - // Личный календарь - if (user?.id) { - opts.push({ - id: "personal", - title: "Личный", - queryParams: { employee_id: user.id }, - }); - } - - return opts; - }, [user]); - + // Загрузка списка календарей при монтировании useEffect(() => { let cancelled = false; + async function loadCalendars() { + try { + const result = await apiClient.getCalendars(); + if (!cancelled) { + const cals = Array.isArray(result) ? result : []; + setCalendars(cals); + // Автоматически выбираем первый календарь + if (cals.length > 0 && selectedCalendarId === null) { + setSelectedCalendarId(cals[0].id); + } + } + } catch (err) { + if (!cancelled) { + console.error("Ошибка загрузки календарей:", err); + } + } + } + + loadCalendars(); + + return () => { + cancelled = true; + }; + }, []); + + // Загрузка событий выбранно календаря + useEffect(() => { + if (selectedCalendarId === null) { + setEvents([]); + return; + } + + let cancelled = false; + const start = new Date(monthDate.getFullYear(), monthDate.getMonth(), 1); const end = new Date(monthDate.getFullYear(), monthDate.getMonth() + 1, 1); const weekStart = startOfWeekMonday(new Date()); @@ -352,13 +350,10 @@ function CalendarCard() { setLoading(true); setError(null); - const selected = calendarOptions.find((c) => c.id === selectedCalendarKey); - const extraParams = selected?.queryParams ?? {}; - const result = await apiClient.getCalendarEvents({ start: formatDateKey(fetchStart), end: formatDateKey(fetchEnd), - ...extraParams, + calendar: selectedCalendarId, }); if (!cancelled) { @@ -369,7 +364,7 @@ function CalendarCard() { const message = err instanceof Error ? err.message : String(err || ""); const isNetworkLike = message === "NetworkError" || /fetch failed/i.test(message); if (!isNetworkLike) { - console.error("Ошибка загрузки календаря:", err); + console.error("Ошибка загрузки событий календаря:", err); } setError("Не удалось загрузить события"); setEvents([]); @@ -386,7 +381,7 @@ function CalendarCard() { return () => { cancelled = true; }; - }, [monthDate, selectedCalendarKey, calendarOptions]); + }, [monthDate, selectedCalendarId]); const monthLabel = useMemo(() => { const label = monthDate.toLocaleDateString("ru-RU", { @@ -450,17 +445,21 @@ function CalendarCard() { <>

Календарь

- + {calendars.length === 0 ? ( +

Календарей нет

+ ) : ( + + )}