diff --git a/frontend/src/app/admin/leads/page.tsx b/frontend/src/app/admin/leads/page.tsx index cbdbef25..7c7e96c6 100644 --- a/frontend/src/app/admin/leads/page.tsx +++ b/frontend/src/app/admin/leads/page.tsx @@ -68,11 +68,6 @@ interface LeadsStats { } export default function AdminLeadsPage() { - const [token] = useState(() => - typeof window === "undefined" - ? "" - : (localStorage.getItem("admin_token") ?? ""), - ); const [statusFilter, setStatusFilter] = useState(""); const [sourceFilter, setSourceFilter] = useState(""); const [convertedFilter, setConvertedFilter] = useState(""); @@ -81,36 +76,24 @@ export default function AdminLeadsPage() { const limit = 50; const stats = useQuery({ - queryKey: ["admin-leads-stats", token], - queryFn: () => - apiFetch("/api/v1/admin/leads/stats?months=12", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + queryKey: ["admin-leads-stats"], + queryFn: () => apiFetch("/api/v1/admin/leads/stats?months=12"), }); const funnelBySource = useQuery({ - queryKey: ["admin-leads-funnel-source", token], + queryKey: ["admin-leads-funnel-source"], queryFn: () => apiFetch( "/api/v1/admin/leads/funnel/by-source?months=12", - { - headers: { "X-Admin-Token": token }, - }, ), - enabled: !!token, }); const funnelMonthly = useQuery({ - queryKey: ["admin-leads-funnel-monthly", token], + queryKey: ["admin-leads-funnel-monthly"], queryFn: () => apiFetch( "/api/v1/admin/leads/funnel/monthly?months=24", - { - headers: { "X-Admin-Token": token }, - }, ), - enabled: !!token, }); const sankeyOption = useMemo(() => { @@ -239,18 +222,13 @@ export default function AdminLeadsPage() { }, [funnelMonthly.data]); const sources = useQuery({ - queryKey: ["admin-leads-sources", token], - queryFn: () => - apiFetch("/api/v1/admin/leads/sources", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + queryKey: ["admin-leads-sources"], + queryFn: () => apiFetch("/api/v1/admin/leads/sources"), }); const leads = useQuery({ queryKey: [ "admin-leads", - token, statusFilter, sourceFilter, convertedFilter, @@ -265,11 +243,8 @@ export default function AdminLeadsPage() { if (sourceFilter) qs.set("source", sourceFilter); if (convertedFilter !== "") qs.set("converted", convertedFilter); if (search) qs.set("search", search); - return apiFetch(`/api/v1/admin/leads/?${qs.toString()}`, { - headers: { "X-Admin-Token": token }, - }); + return apiFetch(`/api/v1/admin/leads/?${qs.toString()}`); }, - enabled: !!token, }); const fmtMoney = (v: number | null) => @@ -279,18 +254,6 @@ export default function AdminLeadsPage() { ? `${(v / 1e6).toFixed(2)} М ₽` : v.toLocaleString("ru"); - if (!token) { - return ( -

- Введите Admin Token на странице{" "} - - Скрапер - {" "} - — он сохранится для всех админ-страниц. -

- ); - } - if (stats.isError || leads.isError) { const err = String(stats.error ?? leads.error ?? ""); return ( diff --git a/frontend/src/app/admin/scrape/all/page.tsx b/frontend/src/app/admin/scrape/all/page.tsx index b4feb6ff..d3635112 100644 --- a/frontend/src/app/admin/scrape/all/page.tsx +++ b/frontend/src/app/admin/scrape/all/page.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { apiFetch } from "@/lib/api"; -import { cardStyle, inputStyle, labelStyle, td, th } from "@/lib/adminStyles"; +import { cardStyle, labelStyle, td, th } from "@/lib/adminStyles"; import { BulkGeoPanel } from "@/components/admin/BulkGeoPanel"; import { JobSettingsPanel } from "@/components/admin/JobSettingsPanel"; @@ -67,46 +67,31 @@ function diffSecs(a: string | null, b: string | null): string { } export default function ScrapeAllAdminPage() { - const [token, setToken] = useState(() => - typeof window === "undefined" - ? "" - : (localStorage.getItem("admin_token") ?? ""), - ); const [filter, setFilter] = useState< "all" | "kn" | "nspd" | "objective" | "nspd_geo" >("all"); const [logsRunId, setLogsRunId] = useState(""); - const saveToken = (v: string) => { - setToken(v); - localStorage.setItem("admin_token", v); - }; - const runs = useQuery({ - queryKey: ["unified-runs", token, filter], + queryKey: ["unified-runs", filter], queryFn: () => { const q = filter !== "all" ? `?scraper_type=${filter}&limit=30` : "?limit=30"; - return apiFetch(`/api/v1/admin/scrape/all/runs${q}`, { - headers: { "X-Admin-Token": token }, - }); + return apiFetch(`/api/v1/admin/scrape/all/runs${q}`); }, - enabled: !!token, refetchInterval: 5000, }); const logs = useQuery({ - queryKey: ["unified-logs", token, filter, logsRunId], + queryKey: ["unified-logs", filter, logsRunId], queryFn: () => { const params = new URLSearchParams({ limit: "100" }); if (filter !== "all") params.set("scraper_type", filter); if (logsRunId !== "") params.set("run_id", String(logsRunId)); return apiFetch( `/api/v1/admin/scrape/all/logs?${params}`, - { headers: { "X-Admin-Token": token } }, ); }, - enabled: !!token, refetchInterval: 8000, }); @@ -146,19 +131,6 @@ export default function ScrapeAllAdminPage() { аудита.

-
- -
- {/* Сводка-плитки */}
- + {/* Bulk geo backfill */}
- +
{/* Logs */} diff --git a/frontend/src/app/admin/scrape/cadastre/page.tsx b/frontend/src/app/admin/scrape/cadastre/page.tsx index 95958980..0ca8c312 100644 --- a/frontend/src/app/admin/scrape/cadastre/page.tsx +++ b/frontend/src/app/admin/scrape/cadastre/page.tsx @@ -122,25 +122,14 @@ function reqPerSec(job: CadastreJob): string { // Query keys // --------------------------------------------------------------------------- -const jobsKey = (token: string) => ["admin", "cadastre", "jobs", token]; -const jobKey = (token: string, id: number) => [ - "admin", - "cadastre", - "job", - id, - token, -]; +const jobsKey = () => ["admin", "cadastre", "jobs"]; +const jobKey = (id: number) => ["admin", "cadastre", "job", id]; // --------------------------------------------------------------------------- // Component // --------------------------------------------------------------------------- export default function CadastreScrapeAdminPage() { - const [token, setToken] = useState(() => - typeof window === "undefined" - ? "" - : (localStorage.getItem("admin_token") ?? ""), - ); const [scope, setScope] = useState("pilot"); const [name, setName] = useState(""); const [quartersText, setQuartersText] = useState(""); @@ -152,35 +141,23 @@ export default function CadastreScrapeAdminPage() { const queryClient = useQueryClient(); - const saveToken = (v: string) => { - setToken(v); - if (typeof window !== "undefined") { - localStorage.setItem("admin_token", v); - } - }; - // ------------------------------------------------------------------------- // Queries // ------------------------------------------------------------------------- const jobs = useQuery({ - queryKey: jobsKey(token), + queryKey: jobsKey(), queryFn: () => - apiFetch("/api/v1/admin/cadastre/jobs?limit=30", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + apiFetch("/api/v1/admin/cadastre/jobs?limit=30"), refetchInterval: 5000, }); // Per-job detail (only fetched when row is expanded) const expandedJob = useQuery({ - queryKey: jobKey(token, expandedId ?? 0), + queryKey: jobKey(expandedId ?? 0), queryFn: () => - apiFetch(`/api/v1/admin/cadastre/jobs/${expandedId}`, { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token && expandedId !== null, + apiFetch(`/api/v1/admin/cadastre/jobs/${expandedId}`), + enabled: expandedId !== null, refetchInterval: expandedId !== null ? 5000 : false, }); @@ -204,17 +181,13 @@ export default function CadastreScrapeAdminPage() { "/api/v1/admin/cadastre/jobs", { method: "POST", - headers: { - "X-Admin-Token": token, - "Content-Type": "application/json", - }, body: JSON.stringify(body), }, ); }, onSuccess: (data) => { setLastResp(data); - void queryClient.invalidateQueries({ queryKey: jobsKey(token) }); + void queryClient.invalidateQueries({ queryKey: jobsKey() }); }, }); @@ -222,11 +195,11 @@ export default function CadastreScrapeAdminPage() { mutationFn: (id: number) => apiFetch<{ cancelled: boolean }>( `/api/v1/admin/cadastre/jobs/${id}/cancel`, - { method: "POST", headers: { "X-Admin-Token": token } }, + { method: "POST" }, ), onSuccess: (_data, id) => { - void queryClient.invalidateQueries({ queryKey: jobKey(token, id) }); - void queryClient.invalidateQueries({ queryKey: jobsKey(token) }); + void queryClient.invalidateQueries({ queryKey: jobKey(id) }); + void queryClient.invalidateQueries({ queryKey: jobsKey() }); }, }); @@ -234,11 +207,11 @@ export default function CadastreScrapeAdminPage() { mutationFn: (id: number) => apiFetch<{ resumed: boolean }>( `/api/v1/admin/cadastre/jobs/${id}/resume`, - { method: "POST", headers: { "X-Admin-Token": token } }, + { method: "POST" }, ), onSuccess: (_data, id) => { - void queryClient.invalidateQueries({ queryKey: jobKey(token, id) }); - void queryClient.invalidateQueries({ queryKey: jobsKey(token) }); + void queryClient.invalidateQueries({ queryKey: jobKey(id) }); + void queryClient.invalidateQueries({ queryKey: jobsKey() }); }, }); @@ -248,7 +221,6 @@ export default function CadastreScrapeAdminPage() { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - if (!token) return; if (scope === "manual_list" && !quartersText.trim()) { alert("Для Manual list укажите хотя бы один квартал"); return; @@ -662,22 +634,8 @@ export default function CadastreScrapeAdminPage() { незавершённых targets.

- {/* Admin Token */} -
- -
- {/* Create job form */} -
+

Запуск bulk harvest

@@ -760,7 +718,7 @@ export default function CadastreScrapeAdminPage() {
(() => - typeof window === "undefined" - ? "" - : (localStorage.getItem("admin_token") ?? ""), - ); const [overrideSqlitePath, setOverrideSqlitePath] = useState(""); const [lastTaskId, setLastTaskId] = useState(null); const [syncGroupsCsv, setSyncGroupsCsv] = useState(""); @@ -108,39 +103,26 @@ export default function ObjectiveEtlAdminPage() { const [showEtl, setShowEtl] = useState(false); const queryClient = useQueryClient(); - const saveToken = (v: string) => { - setToken(v); - localStorage.setItem("admin_token", v); - }; - const coverage = useQuery({ - queryKey: ["objective-coverage", token], + queryKey: ["objective-coverage"], queryFn: () => - apiFetch("/api/v1/admin/scrape/objective/coverage", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + apiFetch("/api/v1/admin/scrape/objective/coverage"), refetchInterval: 10000, }); const runs = useQuery({ - queryKey: ["objective-runs", token], + queryKey: ["objective-runs"], queryFn: () => apiFetch( "/api/v1/admin/scrape/objective/runs?limit=20", - { headers: { "X-Admin-Token": token } }, ), - enabled: !!token, refetchInterval: 5000, }); const cfg = useQuery({ - queryKey: ["objective-config", token], + queryKey: ["objective-config"], queryFn: () => - apiFetch("/api/v1/admin/scrape/objective/config", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + apiFetch("/api/v1/admin/scrape/objective/config"), refetchOnWindowFocus: false, }); @@ -155,10 +137,6 @@ export default function ObjectiveEtlAdminPage() { mutationFn: () => apiFetch("/api/v1/admin/scrape/objective", { method: "POST", - headers: { - "X-Admin-Token": token, - "Content-Type": "application/json", - }, body: JSON.stringify({ sqlite_path: overrideSqlitePath || null }), }), onSuccess: (data) => { @@ -178,10 +156,6 @@ export default function ObjectiveEtlAdminPage() { "/api/v1/admin/scrape/objective/sync-our", { method: "POST", - headers: { - "X-Admin-Token": token, - "Content-Type": "application/json", - }, body: JSON.stringify({ groups: groups.length ? groups : null }), }, ); @@ -196,10 +170,6 @@ export default function ObjectiveEtlAdminPage() { mutationFn: (patch: Partial) => apiFetch("/api/v1/admin/scrape/objective/config", { method: "PUT", - headers: { - "X-Admin-Token": token, - "Content-Type": "application/json", - }, body: JSON.stringify(patch), }), onSuccess: (data) => { @@ -223,22 +193,8 @@ export default function ObjectiveEtlAdminPage() { только как bootstrap-fallback (свёрнут ниже).

- {/* Token */} -
- -
- {/* Coverage */} -
+

📦 Состояние PG (источник истины)

{coverage.isLoading && (

Загрузка…

@@ -504,7 +460,7 @@ export default function ObjectiveEtlAdminPage() {
(() => - typeof window === "undefined" - ? "" - : (localStorage.getItem("admin_token") ?? ""), - ); const [region, setRegion] = useState(66); const [devs, setDevs] = useState(""); const [fetchFlats, setFetchFlats] = useState(true); const [extras, setExtras] = useState(true); const [downloadPhotos, setDownloadPhotos] = useState(false); const [forceRun, setForceRun] = useState(false); - const [catalogMaxObjects, setCatalogMaxObjects] = useState(""); const [showFailures, setShowFailures] = useState(false); const [failuresRunId, setFailuresRunId] = useState(""); const [logsRunId, setLogsRunId] = useState(""); const queryClient = useQueryClient(); const runs = useQuery({ - queryKey: ["scrape-runs", token], - queryFn: () => - apiFetch("/api/v1/admin/scrape/runs?limit=20", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + queryKey: ["scrape-runs"], + queryFn: () => apiFetch("/api/v1/admin/scrape/runs?limit=20"), refetchInterval: 5000, }); @@ -105,7 +88,6 @@ export default function ScrapeAdminPage() { mutationFn: () => apiFetch("/api/v1/admin/scrape/kn", { method: "POST", - headers: { "X-Admin-Token": token }, body: JSON.stringify({ region_code: region, developers: devs @@ -129,27 +111,6 @@ export default function ScrapeAdminPage() { }, }); - const catalogTrigger = useMutation({ - mutationFn: (force: boolean) => - apiFetch("/api/v1/admin/scrape/kn-catalog-objects", { - method: "POST", - headers: { "X-Admin-Token": token }, - body: JSON.stringify({ - region_code: region, - max_objects: catalogMaxObjects === "" ? null : catalogMaxObjects, - force, - }), - }), - onSuccess: (data) => { - console.log("[scrape] catalog queued:", data); - queryClient.invalidateQueries({ queryKey: ["scrape-runs"] }); - queryClient.invalidateQueries({ queryKey: ["scrape-queue"] }); - }, - onError: (err) => { - console.error("[scrape] catalog failed:", err); - }, - }); - const releaseLock = useMutation({ mutationFn: () => apiFetch<{ @@ -158,7 +119,6 @@ export default function ScrapeAdminPage() { released: boolean; }>("/api/v1/admin/scrape/release-lock", { method: "POST", - headers: { "X-Admin-Token": token }, body: JSON.stringify({ region_code: region, developers: devs @@ -180,12 +140,8 @@ export default function ScrapeAdminPage() { }); const queue = useQuery({ - queryKey: ["scrape-queue", token], - queryFn: () => - apiFetch("/api/v1/admin/scrape/queue", { - headers: { "X-Admin-Token": token }, - }), - enabled: !!token, + queryKey: ["scrape-queue"], + queryFn: () => apiFetch("/api/v1/admin/scrape/queue"), refetchInterval: 3000, }); @@ -201,7 +157,6 @@ export default function ScrapeAdminPage() { "/api/v1/admin/scrape/revoke", { method: "POST", - headers: { "X-Admin-Token": token }, body: JSON.stringify({ task_id, terminate }), }, ), @@ -232,30 +187,25 @@ export default function ScrapeAdminPage() { }; const logs = useQuery({ - queryKey: ["scrape-logs", logsRunId, token], + queryKey: ["scrape-logs", logsRunId], queryFn: () => { const q = logsRunId !== "" ? `?run_id=${logsRunId}&limit=200` : "?limit=200"; - return apiFetch(`/api/v1/admin/scrape/logs${q}`, { - headers: { "X-Admin-Token": token }, - }); + return apiFetch(`/api/v1/admin/scrape/logs${q}`); }, - enabled: !!token, refetchInterval: 3000, }); const failures = useQuery({ - queryKey: ["scrape-failures", failuresRunId, token], + queryKey: ["scrape-failures", failuresRunId], queryFn: () => { const q = failuresRunId !== "" ? `?run_id=${failuresRunId}&limit=100` : "?limit=100"; - return apiFetch(`/api/v1/admin/scrape/failures${q}`, { - headers: { "X-Admin-Token": token }, - }); + return apiFetch(`/api/v1/admin/scrape/failures${q}`); }, - enabled: !!token && showFailures, + enabled: showFailures, refetchInterval: showFailures ? 5000 : false, }); @@ -265,11 +215,6 @@ export default function ScrapeAdminPage() { } }; - const saveToken = (v: string) => { - setToken(v); - localStorage.setItem("admin_token", v); - }; - return ( <>

@@ -281,16 +226,6 @@ export default function ScrapeAdminPage() {

-
{releaseLock.isSuccess ? (
-
-

📦 Catalog-object (SSR)

-

- Заполняет wall_type, energy_eff, ceiling_height_m, parking_*, - playground_*, scores из публичной страницы каталога DOM.РФ. По - умолчанию пропускает объекты, обновлённые сегодня. -

-
- - - -
- {catalogTrigger.isError ? ( -
- Ошибка: {String(catalogTrigger.error)} -
- ) : null} - {catalogTrigger.isSuccess ? ( -
- ✓ Catalog-object queued. task_id={" "} - - {catalogTrigger.data.task_id} - {" "} - · регион {catalogTrigger.data.region_code} · force={" "} - {String(catalogTrigger.data.force)} · max_objects={" "} - {catalogTrigger.data.max_objects ?? "default"} -
- ) : null} -
-
- {!token ? ( -

- Введите Admin Token чтобы видеть состояние очереди. -

- ) : queue.isLoading ? ( + {queue.isLoading ? (

Загрузка…

) : queue.isError ? (

Ошибка: {String(queue.error)}

@@ -859,11 +664,7 @@ export default function ScrapeAdminPage() { style={{ ...inputStyle, width: 130 }} />
- {!token ? ( -

- Введите Admin Token чтобы видеть лог. -

- ) : logs.isLoading ? ( + {logs.isLoading ? (

Загрузка…

) : logs.isError ? (

Ошибка: {String(logs.error)}

@@ -937,7 +738,6 @@ export default function ScrapeAdminPage() { />