From 2f127c431637f928c04db97915dbdc1cea86cc2f Mon Sep 17 00:00:00 2001 From: bot-backend Date: Fri, 3 Jul 2026 11:18:31 +0000 Subject: [PATCH] =?UTF-8?q?feat(site-finder):=20=D0=BA=D0=BD=D0=BE=D0=BF?= =?UTF-8?q?=D0=BA=D0=B0=20=C2=AB=D0=9F=D0=BE=D0=BB=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=BE=D1=82=D1=87=D1=91=D1=82=20(PDF)=C2=BB=20(#2259=20PR-E,?= =?UTF-8?q?=20=D1=84=D0=B8=D0=BD=D0=B0=D0=BB=20=D1=8D=D0=BF=D0=B8=D0=BA?= =?UTF-8?q?=D0=B0)=20(#2288)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- .../site-finder/analysis/ExportButtons.tsx | 75 +++++- .../ptica/reports/PticaReports.tsx | 62 ++++- frontend/src/hooks/useFullReport.ts | 233 ++++++++++++++++++ 4 files changed, 356 insertions(+), 16 deletions(-) create mode 100644 frontend/src/hooks/useFullReport.ts diff --git a/.gitignore b/.gitignore index ef5a392e..53ceef6e 100644 --- a/.gitignore +++ b/.gitignore @@ -89,7 +89,7 @@ data/osrm/* # Full PDF report bind-source (#2259 PR-D) — worker пишет PDF в ./reports:/app/reports. # Артефакты рантайма, не коммитим (untracked и так выживает при deploy git reset --hard). -reports/ +/reports/ # Log cruft at repo root debug.log diff --git a/frontend/src/components/site-finder/analysis/ExportButtons.tsx b/frontend/src/components/site-finder/analysis/ExportButtons.tsx index f8f09d08..a4e784aa 100644 --- a/frontend/src/components/site-finder/analysis/ExportButtons.tsx +++ b/frontend/src/components/site-finder/analysis/ExportButtons.tsx @@ -9,9 +9,14 @@ */ import { useState } from "react"; -import { Download, FileText } from "lucide-react"; +import { Download, FileText, FileBarChart } from "lucide-react"; import { API_BASE_URL } from "@/lib/api"; import { triggerDownload } from "@/lib/download"; +import { + useFullReport, + formatElapsed, + formatReportDate, +} from "@/hooks/useFullReport"; import type { ParcelAnalyzeResponse, ParcelEgrn } from "@/lib/site-finder-api"; interface Props { @@ -51,10 +56,7 @@ function buildCsvRows( if (egrn) { rows.push( ["Адрес", egrn.address], - [ - "Площадь м²", - Number.isFinite(egrn.area_m2) ? String(egrn.area_m2) : "", - ], + ["Площадь м²", Number.isFinite(egrn.area_m2) ? String(egrn.area_m2) : ""], ["ВРИ", egrn.vri], ["Категория", egrn.category], ["Форма собственности", egrn.owner_type], @@ -97,6 +99,11 @@ export function ExportButtons({ cad, analyzeData, egrn }: Props) { const [csvLoading, setCsvLoading] = useState(false); const [error, setError] = useState(null); + // Полный PDF-отчёт (#2259 PR-E) — общий хук enqueue → poll → download. + const fullReport = useFullReport(cad); + const reportBuilding = fullReport.uiState === "building"; + const reportReady = fullReport.uiState === "ready"; + async function handlePdfDownload() { setPdfLoading(true); setError(null); @@ -193,8 +200,66 @@ export function ExportButtons({ cad, analyzeData, egrn }: Props) { {csvLoading ? "Генерация..." : "Скачать CSV"} + + {/* Full-report PDF — async job (#2259 PR-E): enqueue → poll → download */} + + {/* Full-report timeout / enqueue-error note (contract has no "failed") */} + {fullReport.uiState === "timeout" && ( +

+ Сборка затянулась — попробуйте позже +

+ )} + {fullReport.uiState === "error" && ( +

+ Не удалось поставить сборку отчёта — повторите +

+ )} + {/* Error message */} {error && (

- {/* Full-report DOCX — NO endpoint → honest disabled «скоро» */} -

+ fullReport.uiState === "ready" + ? fullReport.download() + : fullReport.start() + } + disabled={fullReport.uiState === "building"} + aria-label={ + fullReport.uiState === "ready" + ? "Скачать полный отчёт в формате PDF" + : "Собрать и скачать полный отчёт в формате PDF" + } > - DOCX + PDF - Полный отчёт - скоро + {fullReport.uiState === "building" + ? `Готовится… ${formatElapsed(fullReport.elapsedMs)}` + : fullReport.uiState === "ready" + ? `Скачать отчёт (${formatReportDate( + fullReport.reportGeneratedAt, + )})` + : "Полный отчёт"} + + + {fullReport.uiState === "timeout" + ? "Сборка затянулась — попробуйте позже" + : fullReport.uiState === "error" + ? "Не удалось поставить сборку — повторите" + : "Все секции · PDF"} - Редактируемый Word - -
+ {fullReport.uiState === "building" ? ( +