import { useEffect, useRef, useState } from 'react' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { Link } from 'react-router-dom' import { createCategory, deleteCategory, listCategories, reorderCategories, updateCategory } from '../api/client' import Icon from '../components/Icon' function Categories() { const queryClient = useQueryClient() const [newName, setNewName] = useState('') const [editingId, setEditingId] = useState(null) const [editingName, setEditingName] = useState('') const [deletingId, setDeletingId] = useState(null) const cancelDeleteRef = useRef(null) useEffect(() => { if (deletingId !== null) cancelDeleteRef.current?.focus() }, [deletingId]) const categoriesQuery = useQuery({ queryKey: ['categories'], queryFn: listCategories }) const invalidate = () => { queryClient.invalidateQueries({ queryKey: ['categories'] }); queryClient.invalidateQueries({ queryKey: ['channels'] }); queryClient.invalidateQueries({ queryKey: ['feed'] }) } const createMutation = useMutation({ mutationFn: createCategory, onSuccess: () => { setNewName(''); invalidate() } }) const updateMutation = useMutation({ mutationFn: ({ id, name }: { id: number; name: string }) => updateCategory(id, name), onSuccess: () => { setEditingId(null); invalidate() } }) const deleteMutation = useMutation({ mutationFn: deleteCategory, onSuccess: () => { setDeletingId(null); invalidate() } }) const reorderMutation = useMutation({ mutationFn: reorderCategories, onSuccess: invalidate }) const categories = categoriesQuery.data ?? [] const deleting = categories.find((category) => category.id === deletingId) function move(index: number, direction: -1 | 1) { const target = index + direction if (target < 0 || target >= categories.length) return const ids = categories.map((category) => category.id) ;[ids[index], ids[target]] = [ids[target], ids[index]] reorderMutation.mutate(ids) } return
Настройки

Моя лента

Категории

Создавай темы и меняй порядок в меню.

{ event.preventDefault(); if (newName.trim()) createMutation.mutate(newName.trim()) }}> setNewName(event.target.value)} />
{createMutation.isError &&

Не удалось создать категорию. Возможно, такое имя уже есть.

} {reorderMutation.isError &&

Не удалось изменить порядок категорий.

} {categoriesQuery.isLoading &&
{Array.from({ length: 3 }, (_, index) =>
)}
} {categoriesQuery.isError &&

Не удалось загрузить категории

} {categories.length > 0 &&
    {categories.map((category, index) =>
  • {editingId === category.id ?
    { event.preventDefault(); if (editingName.trim()) updateMutation.mutate({ id: category.id, name: editingName.trim() }) }}> setEditingName(event.target.value)} autoFocus />
    : <>
    {category.name}{category.channel_count} каналов
    }
  • )}
} {updateMutation.isError &&

Не удалось переименовать категорию.

} {!categoriesQuery.isLoading && !categoriesQuery.isError && categories.length === 0 &&

Категорий пока нет

Создай первую тему и добавь в неё каналы.

} {deleting &&
setDeletingId(null)} onKeyDown={(event) => { if (event.key === 'Escape') setDeletingId(null) }}>
event.stopPropagation()}>

Удалить «{deleting.name}»?

Каналы останутся в подписках. Они просто больше не будут относиться к этой категории.

{deleteMutation.isError &&

Не удалось удалить категорию.

}
}
} export default Categories