From 946b78d98991b24fbfe59a5cc2f3da44ca004e8a Mon Sep 17 00:00:00 2001 From: ZProger Date: Wed, 2 Sep 2026 02:21:05 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7=D1=8B?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=B2=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA?= =?UTF-8?q?=D0=B0=D1=85,=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=201.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Версии бэкенда и фронтенда были не синхронизированы и нигде не отображались в интерфейсе — непонятно было, обновилось ли приложение после пересборки. Теперь единая версия 1.1.0 приходит с бэкенда через /api/health и мелким текстом выводится внизу страницы настроек. --- backend/app/core/config.py | 7 ++++--- backend/app/main.py | 5 ++++- frontend/package.json | 2 +- frontend/src/api/health.ts | 6 ++++++ frontend/src/hooks/useHealth.ts | 8 ++++++++ frontend/src/lib/i18n.ts | 2 ++ frontend/src/pages/SettingsPage.tsx | 12 ++++++++++++ frontend/src/types/index.ts | 5 +++++ 8 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 frontend/src/api/health.ts create mode 100644 frontend/src/hooks/useHealth.ts diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 1e59a34..0e183e1 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -4,9 +4,10 @@ from functools import lru_cache from pydantic_settings import BaseSettings, SettingsConfigDict # Single source of truth for the running app's version — surfaced in the API -# title and embedded in exported backups so an old file can be told apart -# from a current one. -APP_VERSION = "0.20.0" +# title, /api/health (which the frontend reads to show it in Settings), and +# embedded in exported backups so an old file can be told apart from a +# current one. +APP_VERSION = "1.1.0" class Settings(BaseSettings): diff --git a/backend/app/main.py b/backend/app/main.py index 14e00ec..ce2dacd 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -88,4 +88,7 @@ app.include_router(crypto.router, prefix="/api") @app.get("/api/health") async def health() -> dict[str, str]: - return {"status": "ok"} + # version rides along so the frontend's Settings page can show which + # release is actually running without a separate authenticated endpoint — + # this route is already auth_basic-exempt for Docker's HEALTHCHECK. + return {"status": "ok", "version": APP_VERSION} diff --git a/frontend/package.json b/frontend/package.json index 0c78088..ed56531 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "aurum-frontend", "private": true, - "version": "0.26.0", + "version": "1.1.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/api/health.ts b/frontend/src/api/health.ts new file mode 100644 index 0000000..d6f395b --- /dev/null +++ b/frontend/src/api/health.ts @@ -0,0 +1,6 @@ +import { api } from "@/api/client"; +import type { HealthStatus } from "@/types"; + +export function fetchHealth() { + return api.get("/health"); +} diff --git a/frontend/src/hooks/useHealth.ts b/frontend/src/hooks/useHealth.ts new file mode 100644 index 0000000..310f818 --- /dev/null +++ b/frontend/src/hooks/useHealth.ts @@ -0,0 +1,8 @@ +import { useQuery } from "@tanstack/react-query"; +import { fetchHealth } from "@/api/health"; + +// The running version only changes on a deploy (a full page reload), so +// there's no need to ever refetch within a session. +export function useHealth() { + return useQuery({ queryKey: ["health"], queryFn: fetchHealth, staleTime: Infinity }); +} diff --git a/frontend/src/lib/i18n.ts b/frontend/src/lib/i18n.ts index e6d4f09..f3abaf6 100644 --- a/frontend/src/lib/i18n.ts +++ b/frontend/src/lib/i18n.ts @@ -341,6 +341,7 @@ const ru = { "Восстановить данные из «{{filename}}»?\n\nЭто ПОЛНОСТЬЮ заменит все текущие счета, категории, транзакции и активы данными из файла. Отменить это действие нельзя — если хотите сохранить текущие данные, сначала сделайте экспорт.", "backup.footerWarning": "Восстановление полностью заменяет текущие данные содержимым файла — это нельзя отменить.", + "settings.version": "Aurum v{{version}}", "insights.negativeCashFlow": "Расходы превышают доходы {{months}} мес. подряд (по последним завершённым месяцам)", "insights.netWorthDecline": "Капитал снижается {{months}} мес. подряд", @@ -823,6 +824,7 @@ const en: Record = { "Restore data from “{{filename}}”?\n\nThis will COMPLETELY replace all current accounts, categories, transactions, and assets with the data from the file. This action cannot be undone — if you want to keep your current data, export it first.", "backup.footerWarning": "Restoring completely replaces your current data with the file's contents — this cannot be undone.", + "settings.version": "Aurum v{{version}}", "insights.negativeCashFlow": "Expenses have exceeded income for {{months}} months in a row (based on the last completed months)", "insights.netWorthDecline": "Net worth has been declining for {{months}} months in a row", diff --git a/frontend/src/pages/SettingsPage.tsx b/frontend/src/pages/SettingsPage.tsx index 16255ae..d2ee61c 100644 --- a/frontend/src/pages/SettingsPage.tsx +++ b/frontend/src/pages/SettingsPage.tsx @@ -2,14 +2,26 @@ import { AlertThresholdsCard } from "@/components/settings/AlertThresholdsCard"; import { BackupCard } from "@/components/settings/BackupCard"; import { CurrencyCard } from "@/components/settings/CurrencyCard"; import { PreferencesCard } from "@/components/settings/PreferencesCard"; +import { useHealth } from "@/hooks/useHealth"; +import { t } from "@/lib/i18n"; export function SettingsPage() { + // Purely informational — if /api/health hasn't answered yet (or is + // unreachable), just show nothing rather than a loading/error state for + // one line of fine print. + const { data: health } = useHealth(); + return (
+ {health?.version && ( +

+ {t("settings.version", { version: health.version })} +

+ )}
); } diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index b1c124a..dc85c4e 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -517,3 +517,8 @@ export interface AppSettings { idle_cash_threshold_days: number; } +export interface HealthStatus { + status: string; + version: string; +} +