import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import {
Alert,
Autocomplete,
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Grid2 as Grid,
IconButton,
TextField,
Tooltip,
Typography,
} from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import ChecklistIcon from '@mui/icons-material/Checklist';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import DeleteIcon from '@mui/icons-material/DeleteOutline';
import EditIcon from '@mui/icons-material/EditOutlined';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '../api/client';
import type { Checklist, ChecklistItemRow } from '../api/types';
import { useAuth } from '../auth/AuthContext';
import { useChecklists } from '../lib/queries';
import { useConfirm, useNotify } from '../ui/feedback';
import { Card, EmptyState, ErrorState, LoadingState, PageHeader } from '../ui/layout';
import { colors } from '../ui/theme';
// Пункт в форме: сохранённый (id) или новый текст. usedIn — во скольких чеклистах компании он есть.
type ItemForm = { key: string; id?: string; text: string; usedIn: number };
type Form = { name: string; description: string; items: ItemForm[] };
const toForm = (c: Checklist): Form => ({
name: c.name,
description: c.description || '',
items: c.items.map((i) => ({ key: i.id, id: i.id, text: i.text, usedIn: i.usedIn })),
});
// Сравнение текстов — как на сервере: без регистра, пробелов по краям и «ё»/«е».
const norm = (s: string) => s.trim().replace(/\s+/g, ' ').toLowerCase().replace(/ё/g, 'е');
export function ChecklistsPage() {
const { checklistId } = useParams();
const navigate = useNavigate();
const { can } = useAuth();
const list = useChecklists();
return (
<>
} onClick={() => navigate('/checklists/new')}>
Новый чеклист
)
}
/>
{list.isLoading ? (
) : list.isError ? (
list.refetch()} />
) : (
{list.data?.length === 0 && checklistId !== 'new' && (
Чеклистов пока нет.
)}
{list.data?.map((c) => (
navigate(`/checklists/${c.id}`)}
sx={{
p: 1.75,
borderRadius: '12px',
cursor: 'pointer',
bgcolor: '#fff',
border: `1px solid ${checklistId === c.id ? colors.brand : colors.line}`,
boxShadow: checklistId === c.id ? `0 0 0 3px ${colors.brandSoft}` : 'none',
}}
>
{c.name}
Пунктов: {c.items.length} · {c.checkpointsCount ? `на точках: ${c.checkpointsCount}` : 'не прикреплён к точкам'}
))}
{checklistId ? (
c.id === checklistId)} />
) : (
{can('routes.manage') ? 'или создайте новый. Чеклисты прикрепляются к контрольным точкам на странице «Маршруты».' : null}
)}
)}
>
);
}
function ChecklistForm({ checklistId, existing }: { checklistId: string; existing?: Checklist }) {
const isNew = checklistId === 'new';
const navigate = useNavigate();
const qc = useQueryClient();
const notify = useNotify();
const confirm = useConfirm();
const { can } = useAuth();
const editable = can('routes.manage');
const [form, setForm] = useState