import React, { useState, useEffect, useRef, useCallback } from 'react'; import { Table, Button, Tag, Space, Modal, Form, Select, Spin, Input, Tooltip, Card, Col, Row, Statistic } from 'antd'; import { InfoCircleOutlined, EditOutlined, DeleteOutlined, CalendarOutlined } from '@ant-design/icons'; import { Link, useNavigate } from 'react-router-dom'; import { useCalendars, useUpdateCalendar, useDeleteCalendar, useCalendar, useCalendarStats } from '../../hooks/useCalendars'; import { Calendar, CalendarListParams } from '../../types/api'; import type { ColumnsType, SorterResult } from 'antd/es/table/interface'; const CalendarListPage: React.FC = () => { const navigate = useNavigate(); const [params, setParams] = useState({ limit: 20, offset: 0, sort: 'created_at', order: 'desc' }); const { data, isLoading } = useCalendars(params); const { data: stats } = useCalendarStats(); const updateCalendar = useUpdateCalendar(); const deleteCalendar = useDeleteCalendar(); const [editModal, setEditModal] = useState<{ open: boolean; calendarId: string | null }>({ open: false, calendarId: null, }); const { data: editingCalendar, isLoading: loadingCalendar } = useCalendar(editModal.calendarId || ''); const [editForm] = Form.useForm(); const [editHasErrors, setEditHasErrors] = useState(true); const originalCalendarRef = useRef(null); const validateEditForm = useCallback(() => { const title = editForm.getFieldValue('title'); const status = editForm.getFieldValue('status'); setEditHasErrors(!title || !status); }, [editForm]); const handleEdit = (id: string) => { setEditModal({ open: true, calendarId: id }); }; const handleSaveEdit = () => { editForm.validateFields().then((values) => { if (!editModal.calendarId || !originalCalendarRef.current) return; const original = originalCalendarRef.current; const cleanedValues: Record = {}; const allKeys = new Set([...Object.keys(values), ...Object.keys(original)]); allKeys.forEach((key) => { const newVal = values[key]; if (newVal === '' || newVal === undefined || newVal === null) { const origVal = (original as unknown as Record)[key]; if (origVal && origVal !== '-' && origVal !== '' && origVal !== undefined && origVal !== null) { cleanedValues[key] = null; } return; } if (newVal === '-') return; cleanedValues[key] = newVal; }); const payload = Object.fromEntries( Object.entries(cleanedValues).filter(([key, v]) => { const origVal = (original as unknown as Record)[key]; return JSON.stringify(v) !== JSON.stringify(origVal === '-' ? undefined : origVal); }) ); updateCalendar.mutate( { id: editModal.calendarId, data: payload }, { onSuccess: () => setEditModal({ open: false, calendarId: null }) } ); }); }; useEffect(() => { if (editingCalendar && editModal.open) { originalCalendarRef.current = editingCalendar; const clean = (val: unknown) => (val === '-' || val === 'undefined' ? undefined : val); setTimeout(() => { editForm.setFieldsValue({ title: clean(editingCalendar.title), description: clean(editingCalendar.description), type: clean(editingCalendar.type), status: clean(editingCalendar.status), category: clean(editingCalendar.category), reason: clean(editingCalendar.reason), }); validateEditForm(); }, 0); } }, [editingCalendar, editModal.open, editForm, validateEditForm]); const handleDelete = (id: string) => { Modal.confirm({ title: 'Удалить календарь?', okText: 'Удалить', okType: 'danger', cancelText: 'Отмена', onOk: () => deleteCalendar.mutate(id), }); }; const handleTableChange = ( pagination: { current?: number; pageSize?: number }, _filters: unknown, sorter: SorterResult | SorterResult[] ) => { const s = Array.isArray(sorter) ? sorter[0] : sorter; setParams(prev => ({ ...prev, sort: s.field as string, order: s.order === 'ascend' ? 'asc' : s.order === 'descend' ? 'desc' : undefined, offset: ((pagination.current || 1) - 1) * (pagination.pageSize || prev.limit || 20), limit: pagination.pageSize || prev.limit, })); }; const columns: ColumnsType = [ { title: , key: 'detail', width: 48, align: 'center', render: (_, record) => (