import { unwrap } from '@pipu/core'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useId } from 'react'; import { useTranslation } from 'react-i18next'; import { useSession, useUser } from '../../app/session'; import { useErrorText } from '../../shared/lib/errors'; import { refreshIcon } from '../../shared/ui/icons'; import { Button, FormError } from '../../shared/ui/ui'; import s from '../page.module.css'; import l from './library.module.css'; import { ScanLine, StatusBadge } from './ScanStatus'; /** Состояние библиотеки: счётчики, хранилища и сканы (admin, moderator), ошибки чтения (admin). */ export function LibraryPage() { const { t } = useTranslation(['admin', 'common']); const session = useSession(); const user = useUser(); const errorText = useErrorText(); const admin = user.role === 'admin'; const status = useQuery({ queryKey: ['library-status'], queryFn: async () => unwrap(await session.client.GET('/api/v1/admin/library/status')), refetchInterval: (q) => (q.state.data?.sources.some((x) => x.scan?.running) ? 2000 : 15000), }); const errors = useQuery({ queryKey: ['library-errors'], enabled: admin, queryFn: async () => unwrap(await session.client.GET('/api/v1/admin/library/errors', { params: { query: { limit: 50 } } })), }); const reindex = useMutation({ mutationFn: async () => unwrap(await session.client.POST('/api/v1/admin/search/reindex')), }); const queryClient = useQueryClient(); const retry = useMutation({ mutationFn: async () => unwrap(await session.client.POST('/api/v1/admin/library/analysis/retry')), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['library-status'] }), }); const d = status.data; const tiles = d ? ([ ['artists', d.artists], ['albums', d.albums], ['tracks', d.tracks], ['files', d.files], ['missing', d.missing_files], ['errors', d.file_errors], ] as const) : []; return (
{t('library.subtitle')}
| {t('library.wave_model')} | {t('library.wave_served')} | {t('library.wave_listen')} | {t('library.wave_early_skip')} | {t('library.wave_likes')} |
|---|---|---|---|---|
| {m.model_ver || '—'} | {m.served.toLocaleString()} | {pct(m.listen_through_rate)} | {pct(m.early_skip_rate)} | {m.like_rate === null ? '—' : m.like_rate.toFixed(1)} |