import { useQuery } from '@tanstack/react-query'; import { useEffect, useState } from 'react'; import { api } from '../api.ts'; import { ErrorNote, Toggle } from '../components/ui.tsx'; import { useAction } from '../hooks.ts'; import { useCrm } from './i18n.ts'; interface Settings { enabled: boolean; freshDays: number; pauseSec: number; maxPages: number; quietHours: boolean; quietFrom: number; quietTo: number; categories: number[]; useKey: boolean; removalCheck: boolean; removalBatch: number; recheckHours: number; jinaKey: { source: 'settings' | 'env' | 'none'; tail: string | null }; allCategories: { id: number; propertyType: 'apartment' | 'house' | 'commercial' | 'land' | 'garage'; dealType: 'sale' | 'rent' }[]; } /** Настройки парсера для суперадмина. Применяются со следующего прохода, без перезапуска сервиса. */ export function ParserSettings() { const { c, t } = useCrm(); const x = c.ps; const loaded = useQuery({ queryKey: ['admin', 'parser', 'settings'], queryFn: () => api('/admin/parser/settings') }); const [f, setF] = useState(null); const [key, setKey] = useState(''); useEffect(() => { if (loaded.data) setF(loaded.data); }, [loaded.data]); const save = useAction( (body: object) => api('/admin/parser/settings', { method: 'PATCH', body }), ['admin', 'parser'], ); if (!f) return ; const number = (field: 'freshDays' | 'pauseSec' | 'maxPages' | 'removalBatch' | 'recheckHours', label: string, min: number, max: number, hint?: string) => (
setF({ ...f, [field]: Number(e.target.value) })} /> {hint &&

{hint}

}
); const toggleCategory = (id: number) => setF({ ...f, categories: f.categories.includes(id) ? f.categories.filter((v) => v !== id) : [...f.categories, id] }); return (
{ e.preventDefault(); const { jinaKey: _jinaKey, allCategories: _all, ...body } = f; save.mutate({ ...body, ...(key.trim() ? { jinaApiKey: key.trim() } : {}) }, { onSuccess: () => setKey('') }); }} >

{x.title}

{x.hint}

setF({ ...f, enabled: v })} label={x.enabled} />
{number('freshDays', x.freshDays, 1, 30, x.freshHint)} {number('pauseSec', x.pauseSec, 0, 3600)} {number('maxPages', x.maxPages, 1, 10, x.pagesHint)}

{x.quietTitle}

{x.quietHint}

setF({ ...f, quietHours: v })} label={x.quietOn} />
{(['quietFrom', 'quietTo'] as const).map((field) => (
))}
{f.quietHours && f.quietFrom === f.quietTo &&

{x.quietSame}

}
{x.categories}
{f.allCategories.map((cat) => { const on = f.categories.includes(cat.id); return ( ); })}

{x.keyTitle}

{x.keyHint}

setF({ ...f, useKey: v })} label={x.useKey} />
setKey(e.target.value)} />
{f.jinaKey.source === 'settings' && ( )}

{x.removalTitle}

setF({ ...f, removalCheck: v })} label={x.removalCheck} />
{number('recheckHours', x.recheckHours, 1, 720)} {number('removalBatch', x.removalBatch, 1, 100, x.batchHint(f.removalBatch * 144))}
{save.isSuccess && {t.settings.saved}}
); }