Commit Graph
62 Commits
Author SHA1 Message Date
DenozordecandCursor 836c8a2936 feat(web): связка страны и города в форме VPS
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 02:18:18 +07:00
DenozordecandCursor a954591493 feat(web): ReUI Autocomplete для страны/города и вертикальная раскладка локации
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 02:11:45 +07:00
DenozordecandCursor f681f72e8c fix(web): флаги стран, FormDatePicker и плоские таблицы без двойной рамки
SVG-флаги через flagcdn и resolveCountryCode; поле «Оплачено до» — компактный Popover+Calendar на русском; DataGridCard без вложенной обводки.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 01:59:50 +07:00
DenozordecandCursor 4c7dfc45d6 feat(web): иконки заголовков и rich cells во всех таблицах
Lucide-иконки в заголовках, двухстрочные ячейки аккаунтов, флаги локации VPS, favicon хостеров.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 01:42:45 +07:00
DenozordecandCursor a6f202f659 feat(web): ReUI DataGrid — Column Icons, оболочка и хелперы ячеек
DataGridColumnHeader в columnDefFromDataTable, bordered-контейнер, русская пагинация, хелперы dataGridCellStack/WithIcon/WithFlag.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 01:42:39 +07:00
DenozordecandCursor bbb6de29be fix(web): поиск VPS на отдельной строке над фильтрами
Строка поиска вынесена выше кнопки «Фильтр» и чипов активных фильтров для более понятной иерархии тулбара.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 01:27:58 +07:00
DenozordecandCursor af9bd44d44 fix(web): кнопка «Фильтр» в тулбаре VPS — явный trigger для ReUI Filters
Без пропа trigger компонент Filters рендерил пустую кнопку, из-за чего фильтры были невидимы на странице.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 00:51:20 +07:00
DenozordecandCursor b1315ffe0a feat(web): миграция таблиц на @reui/data-grid (TanStack Table + virtualization + pinning)
- Установлен @reui/data-grid через shadcn CLI: зависимости @tanstack/react-table,
  @tanstack/react-virtual, @dnd-kit/* добавлены в apps/web
- Поправлены type-only импорты во всех файлах data-grid (verbatimModuleSyntax),
  убран unused параметр table в DataGridTableVirtualBody
- Создана shared-обёртка apps/web/src/components/data-grid-card.tsx (замена
  DataTableCard) с типизированными ColumnDef<TData>, сортировкой, пагинацией
  (>25 строк), column pinning, optional virtualization (DataGridScrollArea +
  DataGridTableVirtual), footer-контентом и хелпером columnDefFromDataTable
- Мигрированы все 7 страниц: vps, dashboard, payments, balance, accounts,
  tariffs, providers — DataTableCard/TableCard+Table → DataGridCard
- Virtualization включена для VPS и payments при >200 строк (height 560)
- Column pinning последней колонки (actions) — vps, payments, balance, accounts,
  providers
- Footer rows с итогами: balance (приходы/списания/итого), payments (по валютам)
- build + tsc --noEmit без ошибок

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 00:06:59 +07:00
DenozordecandCursor 63da57687d feat(web): фильтры VPS в стиле reui.io + ReUI-компоненты в форме
- Регистр @reui в components.json (URL https://reui.io/r/{style}/{name}.json)
- Установлены @reui/filters, @reui/autocomplete, @reui/number-field,
  @reui/date-selector и shadcn slider через shadcn CLI
- Поправлены TS-импорты в ReUI-исходниках (type-only) и удалены неиспользуемые
  объявления; в packages/ui добавлены react-day-picker и date-fns для calendar
- Новый VpsFiltersToolbar: тулбар с поиском, кнопкой «Фильтр» (ReUI Filters),
  chips с операторами, Popover «Вид» (группировка/компактность/пресеты)
- vps-filters.tsx переписан под массивы значений (мультивыбор) с поддержкой
  операторов is_any_of / contains / gte; applyVpsFilters принимает как state,
  так и Filter[] (stateToActiveFilters)
- В форме VPS vcpu/ramGb/diskGb/monthlyRate/dailyRate — @reui/number-field
  через Controller, paidUntil — @reui/date-selector (одиночная дата)
- AutoCompleteInput: отступы флага size-4 leading-none, CommandList py-1,
  CommandItem gap-2.5, PopoverContent min-w-[220px]
- build + tsc --noEmit без ошибок

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 23:53:16 +07:00
DenozordecandCursor b87d7c6fad fix(web): AutoCompleteInput — canonical shadcn Combobox, без браузерных подсказок
- переделан по документации shadcn: Button trigger + Popover + Command
  с CommandInput внутри (вместо нативного Input в триггере)
- CommandInput с autoComplete="off" / autoCorrect="off" / spellCheck=false —
  браузерные подсказки больше не появляются
- поддержан произвольный ввод: пункт «Использовать: <запрос>» при отсутствии
  совпадений

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 23:03:20 +07:00
DenozordecandCursor db1d26d324 feat(web): стандартизированный справочник стран и городов в @cfdm/shared/geo
- packages/shared/src/geo: страны ISO 3166-1 alpha-2 + топ-города по странам
- vps.tsx: countryOptions/cityOptions из справочника + существующих VPS,
  города фильтруются по выбранной стране
- auto-complete-input: убран onBlur-хак с setTimeout, фильтрация по
  основному полю, initialFocus=false чтобы popover не закрывался
- vite.config.ts + tsconfig.json: алиас @cfdm/shared/geo

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 22:56:54 +07:00
DenozordecandCursor a51b5f3594 feat(web): страна/город в форме и фильтрах VPS — автокомплит + флаг
- Новый компонент AutoCompleteInput (Popover + Command/cmdk):
  ввод с подсказками, поддержка leading-иконки (эмодзи-флаг).
- Страна: в списке вариантов и в самом инпуте показывается
  эмодзи-флаг через getCountryFlagEmoji.
- Город: автокомплит без флага.
- Источник данных — уникальные значения из snapshot.vps
  (server-side API для стран/городов отсутствует).
- Подключено в форме VPS и в фильтрах страницы.
- Добавлены shadcn-компоненты command, popover, input-group;
  зависимость cmdk в packages/ui.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 22:39:33 +07:00
DenozordecandCursor 6310ed8e02 fix(web): форма VPS — возвращены поля Страна/Город/Дата-центр
Поля country/city/datacenter были потеряны при миграции формы на shadcn.
Добавлены в zod-схему, EMPTY_FORM, openEdit и в JSX формы (грид из 3
колонок после «Проект»).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 22:36:17 +07:00
DenozordecandCursor 7ef42ee7e8 fix(web): VPS — корректная валюта тарифа и конвертация курсов в таблице
Раньше в колонке тарифа вызывался formatInBaseCurrency с ratesData=null,
поэтому 0.8 EUR отображались как «0,80 ₽» (без конвертации, но в базовой
валюте). Теперь:
- ratesData грузится через ratesQueryOptions (как на dashboard/reports);
- валюта тарифа определяется через effectiveVpsTariffCurrency (приоритет
  baseCurrency провайдера, затем vps.currency);
- форматирование через formatInProviderCurrency — учитывает курсы
  провайдера (usdRate/eurRate) и глобальные курсы, при их отсутствии
  показывает сумму в исходной валюте, а не в базовой.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 22:33:44 +07:00
DenozordecandCursor ee5d5b228b fix(web): VPS — дробные значения в полях ставок (step="any")
Ставка/мес и Ставка/день теперь принимают дробные значения (например,
0.8 EUR), а не только целые. Раньше browser-native валидация type=number
со step=1 блокировала сохранение.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 22:28:00 +07:00
DenozordecandCursor e43cdc1b85 fix(ui): позиция выпадающего списка Select — снизу, а не поверх триггера
В SelectContent по умолчанию было alignItemWithTrigger=true (стиль macOS:
поповер перекрывает триггер) и align=center. Заменил на align=start и
alignItemWithTrigger=false — меню появляется под триггером, как в
стандартном shadcn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 22:22:26 +07:00
DenozordecandCursor 525eff0d09 feat(web): фильтры на странице VPS — полный набор + пресеты
Восстановлены фильтры, потерянные при миграции на shadcn:
поиск, хостер/аккаунт, проект (с опцией «Без проекта»), статус,
окружение, тип тарифа, мониторинг/бэкап, страна/город/дата-центр,
минимумы vCPU/RAM/Disk, группировка по проекту, компактная таблица.
Пресеты сохраняются в localStorage. Добавлен shadcn-компонент checkbox.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 17:31:45 +07:00
DenozordecandCursor 8b38021200 docker: оптимизация образа — 2 стадии вместо 3, один COPY-слой в runtime
- убран отдельный deps-stage: build + pnpm prune --prod в одном RUN
- удаление src/tsconfig/.vite-temp и лишних файлов в node_modules (md/map/ts/LICENSE/...)
- runtime: alpine + nodejs, один COPY --from=build /app (symlink’и pnpm сохраняются)
- итого: 2 стадии, ~1 COPY-слой в runtime вместо ~17

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 16:08:34 +07:00
DenozordecandCursor bc0da072ee fix(web): SelectField использует стандартные shadcn Select-компоненты с w-full
- SelectField переписан на переиспользование Select/SelectTrigger/
  SelectValue/SelectContent/SelectItem из @cfdm/ui (вместо дубля стилей)
- triggerClassName по умолчанию w-full — триггер виден в формах
  (для horizontal field в settings передаётся w-32)
- items prop в Select.Root — SelectValue рендерит label выбранного элемента

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 15:57:11 +07:00
DenozordecandCursor b2611d951b fix(web): селекты показывают label вместо технического значения; редактирование VPS подтягивает данные
- SelectField: обёртка над base-ui Select с items prop
  (Select.Value рендерит label выбранного элемента, а не raw value)
- все Select в forms (vps/providers/accounts/payments/balance/settings)
  переписаны на SelectField
- FormSheetRhf: useEffect reset(defaultValues) при открытии sheet
  — теперь форма редактирования заполняется текущими данными

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 15:54:35 +07:00
DenozordecandCursor 3e57728ddc feat(web): тёмная тема (system/manual) и фикс логотипа в icon-режиме сайдбара
- ThemeProvider (next-themes, attribute=class, defaultTheme=system)
- ModeToggle в header: светлая / тёмная / системная
- suppressHydrationWarning на <html> против FOUC
- логотип в SidebarHeader через SidebarMenuButton size="lg"
  (корректное схлопывание в icon-режиме, aspect-square для иконки)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 15:50:30 +07:00
DenozordecandCursor 3026f1d1ce fix(docker): копирование apps/api/db.js и routes/ в образ; пути к web/dist и seed
- Dockerfile: добавлены COPY для db.js, routes/, apps/web/public (seed)
- apps/api/index.js: distPath → ../web/dist (раньше ../dist)
- apps/api/db/index.js: DB_PATH/SEED_DIR/dataDir — на 3 уровня вверх
  (apps/api/db/ → корень) и seed из apps/web/public/data

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 13:51:19 +07:00
DenozordecandCursor 6fbd1a9113 refactor(repo): переход на pnpm monorepo с shadcn/ui и Fastify+Drizzle
Frontend:
- apps/web (Vite+TS, TanStack Router/Query, shadcn/ui @cfdm/ui base-nova)
- 10 страниц в routes/_auth/, Recharts через shadcn Chart, lucide-react
- формы на RHF + Zod (FormSheet/FormField)
- удалены Tabler, Chart.js, react-router-dom

Backend (параллельный трек):
- apps/api (Fastify 5 + Drizzle + better-sqlite3)
- packages/db: Drizzle-схема и repositories по сущностям
- packages/shared: Zod-контракты
- роуты с валидацией и единым форматом ошибок { error: { code, message } }
- sync/backup — заглушки 501 (billmanager-адаптеры переносятся отдельно)
- legacy Express оставлен как runtime по умолчанию (RUNTIME=express)

Infra:
- Dockerfile multi-stage под pnpm workspaces
- .dockerignore и docker-compose обновлены под monorepo

Rules:
- удалены нерелевантные правила (rust, cloudflare, server/frontend-conventions)
- project-structure.mdc и AGENTS.md переписаны под monorepo
- frontend-shadcn.mdc, shadcn-ui-production.mdc, sqlite.mdc обновлены

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 13:42:05 +07:00
Denozordec 8408155be6 feat(accounts): «Хостер / аккаунт» в журнале синхронизации; журнал баланса — только имя аккаунта
Made-with: Cursor
2026-03-23 23:14:39 +07:00
Denozordec 24e1b8f4ef fix(currency): глобальный курс при нулевой сумме (не «курсы не загружены»)
Made-with: Cursor
2026-03-23 23:05:34 +07:00
Denozordec 0b4507e2d2 fix(rates): fallback на прямой fetch если прокси недоступен
Made-with: Cursor
2026-03-23 23:00:52 +07:00
Denozordec 6bf270d715 feat(dashboard): подпись «хостер / аккаунт» в таблице остатков
Made-with: Cursor
2026-03-23 22:53:44 +07:00
Denozordec 92a986c858 fix(rates): серверный прокси /api/rates-proxy и бейдж «Курсы не загружены»
- Добавлен /api/rates-proxy для загрузки курсов без CORS
- Фронтенд загружает курсы через прокси, а не напрямую
- convertWithProviderRate возвращает source=no-rates при отсутствии ratesData
- ConvertedAmount показывает «Курсы не загружены» (жёлтый) вместо ложного «Глобальный курс»

Made-with: Cursor
2026-03-23 21:45:02 +07:00
Denozordec a97ec8c121 refactor(currency): валюта тарифа = валюта хостера, не VPS
- effectiveVpsTariffCurrency всегда берёт provider.baseCurrency
- Убран селектор валюты из формы VPS (подпись из хостера)
- DashboardPage, ResourcesPage, ReportsPage: вместо item.currency — baseCurrency провайдера
- Конвертация по глобальным курсам теперь корректно находит EUR/USD

Made-with: Cursor
2026-03-23 21:32:46 +07:00
Denozordec c161eaf84a fix(currency): глобальные курсы без явного курса хостера и нормализация Valute ЦБ
- parseProviderFxRate: пусто/auto/невалид → конвертация по ссылке из настроек
- normalizeRatesPayload + App: JSON ЦБ с Valute → base+rates как у latest.js
- Подсказка в форме хостера про курсы USD/EUR

Made-with: Cursor
2026-03-23 21:25:01 +07:00
Denozordec a4752d4379 fix(currency): глобальная конвертация и effectiveVpsTariffCurrency для BM
- baseCurrency хостера не подставлять при пустой валюте VPS, если есть API (дефолт RUB)
- Подстановка валюты хостера только для провайдеров без API
- RUR → RUB для курсов ЦБ; проверка курсов через Number.isFinite

Made-with: Cursor
2026-03-23 21:17:19 +07:00
Denozordec f4517f03fc feat(balance): подпись аккаунта «хостер / имя» как в фильтрах VPS
- Вынесен accountSelectLabel в src/lib/account-select-label.js
- Модалка списания, таблица баланса и журнал на BalancePage
- VpsPage переведён на общий модуль

Made-with: Cursor
2026-03-23 21:06:52 +07:00
Denozordec 524cbba5e7 fix(vps): валюта тарифа — effectiveVpsTariffCurrency и поле в форме
- Для хостеров без API USD в VPS трактуется как дефолт формы, берётся baseCurrency хостера
- В форме VPS добавлен выбор валюты тарифа; при смене хостера подставляется его валюта
- Прогноз по проектам и ConvertedAmount для тарифа используют effectiveVpsTariffCurrency

Made-with: Cursor
2026-03-23 21:03:34 +07:00
Denozordec d717719e35 Revert "perf: replace @tabler packages with lucide-react and static CSS (-70 MB node_modules)"
Docker / build (push) Failing after 17s
This reverts commit a1227a13e8.
2026-03-21 02:15:20 +07:00
Denozordec a1227a13e8 perf: replace @tabler packages with lucide-react and static CSS (-70 MB node_modules)
Docker / build (push) Failing after 16s
Made-with: Cursor
2026-03-21 02:11:28 +07:00
Denozordec 5cd11fc454 docker: revert to apk add nodejs (smaller than full node binary)
Docker / build (push) Failing after 17s
Made-with: Cursor
2026-03-21 01:43:47 +07:00
Denozordec 3c950db2ad docker: copy node binary instead of apk add nodejs for smaller image
Docker / build (push) Failing after 16s
Made-with: Cursor
2026-03-21 01:41:51 +07:00
Denozordec 116632aa9e docker: оптимизация образа (alpine+nodejs, очистка node_modules)
Docker / build (push) Failing after 16s
Made-with: Cursor
2026-03-21 01:38:01 +07:00
Denozordec 43c1a0dc81 docker: final stage back to node:22-alpine (fewer base layers than distroless)
Made-with: Cursor
2026-03-21 01:31:09 +07:00
Denozordec 446d70d3dc docker: minimal runtime image — UI in devDeps, distroless final, slim bundle
Docker / build (push) Failing after 16s
Made-with: Cursor
2026-03-21 01:27:26 +07:00
Denozordec dae8bb8066 docker: drop npm cache clean after ci (fixes exit 254 with BuildKit cache mount)
Docker / build (push) Failing after 18s
Made-with: Cursor
2026-03-21 01:19:53 +07:00
Denozordec 87cc899486 docker: fewer final image layers, npm cache mount, trim build context
Docker / build (push) Failing after 18s
Made-with: Cursor
2026-03-21 01:18:37 +07:00
Denozordec 18de957c61 refactor: simplify ProvidersPage by removing unused API connection logic
Docker / build (push) Failing after 18s
Removed unnecessary state variables and connection testing logic from ProvidersPage. Updated the UI to clarify API login and password handling, directing users to the appropriate section for account credentials. This streamlines the component and enhances user experience.
2026-03-21 01:07:36 +07:00
Denozordec ec038242bf feat: consolidate provider API sources with heuristic support
Docker / build (push) Failing after 18s
Updated the database migration logic to consolidate provider API sources from both accounts and heuristic methods for BILLmanager URLs. Replaced direct calls to `consolidateProviderApiFromAccounts` with `consolidateAllProviderApiSources` in relevant routes to ensure comprehensive API data handling.
2026-03-21 01:01:09 +07:00
Denozordec 28d723983e feat: BILLmanager API на уровне хостера, миграция со старых аккаунтов
Docker / build (push) Failing after 18s
Made-with: Cursor
2026-03-21 00:52:49 +07:00
Denozordec 2da1f6a6f0 docs: add docker run equivalent for compose setup
Docker / build (push) Failing after 17s
Made-with: Cursor
2026-03-21 00:29:39 +07:00
Denozordec 51974b2669 fix(vps): disambiguate account filter labels across hosters
Docker / build (push) Failing after 32s
Made-with: Cursor
2026-03-21 00:27:37 +07:00
Denozordec e20349cb4e chore: docker-compose использует образ GHCR, обновлён README
Made-with: Cursor
2026-03-20 23:42:00 +07:00
Denozordec 01c2cfa5c3 docs: пользовательская инструкция для Linux в README
Made-with: Cursor
2026-03-20 23:29:18 +07:00
Denozordec 8646487f35 docs: указать образ GHCR ghcr.io/denozordec/vps-tracker в README
Made-with: Cursor
2026-03-20 23:27:04 +07:00