Commit Graph

25 Commits

Author SHA1 Message Date
c0mrade
bd8a4fad6e refactor(theming): replace amber-* with warning-* tokens
Sweep all amber-N color classes to warning-N (uniformly pending/warning semantics).
Yellow and orange left for per-file review (mixed Stars brand + semantic uses).
2026-05-26 11:10:50 +03:00
c0mrade
491f48a331 fix(a11y): switch semantics for user-flow toggles
Add role=switch + aria-checked + aria-label to the custom toggle buttons so screen
readers announce on/off state (WCAG 4.1.2): autopay (Subscription) and the custom-days
/ custom-traffic toggles (SubscriptionPurchase).
2026-05-25 23:57:36 +03:00
Fringg
e44a09312e fix(subscription): forward subscription_id to purchaseTariff to fix renew race
Companion to bedolaga-bot a527df23. Bot's purchase-tariff endpoint
now accepts optional subscription_id to resolve the EXACT target row
by ID instead of doing a (user_id, tariff_id) re-lookup that races
with concurrent panel webhooks (produces 'Тариф уже активен' +
refund + no extension).

Frontend changes:
* subscriptionApi.purchaseTariff() — new optional subscriptionId arg
  appended after trafficGb. Forwarded as subscription_id in POST body.
* SubscriptionPurchase.tsx — forwards URL searchParam subscriptionId
  (set when user lands here from 'Renew this subscription').
* SubscriptionCardExpired.tsx — passes subscription.id when renewing
  an expired daily tariff (the .purchaseTariff(tariff_id, 1) call).
2026-05-16 16:10:32 +03:00
Fringg
1d5ce2d4ea fix: complete is_limited status handling across all views
- SubscriptionListCard: show traffic progress bar for limited subs
  in multi-tariff list (was hidden because isActive excluded limited)
- SubscriptionListCard: amber border/background for limited status
  cards (was using default neutral style, inconsistent with rest of UI)
- Subscription page: hide delete button for limited subs in
  multi-tariff mode (limited subs still have valid days remaining)
- SubscriptionPurchase: allow tariff switch for limited subs
  (was blocked by is_active-only gate in canSwitch formula)
- AdminUserDetail: include limited status in "already purchased"
  tariff filter to prevent duplicate subscription creation
2026-04-23 04:04:11 +03:00
Dmitry Lunin
d75440bfe4 fix: wrap server display names with Twemoji for cross-platform emoji rendering 2026-04-21 23:03:20 +03:00
c0mrade
e6f6713b0e fix: batch bug fixes matching backend changes
- Promo code errors: add inactive/not_yet_valid translations (4 locales) + Balance.tsx parser
- Daily 100% discount: render price block when originalDailyPrice > 0
- Webvisor: enable in Yandex Metrika init config
- Referral attribution: consume campaign/referral slugs only after successful auth (all login methods)
- registerWithEmail: consume referral code after success
- AdminSettings: move TARIFF_MODE_SETTINGS to module scope (fix eslint warning)
2026-04-08 18:33:47 +03:00
c0mrade
207af81c95 fix: support 100% discount display + fix Telegram link widget race condition
- formatPrice shows "Бесплатно/Free" when price is 0 (SubscriptionPurchase, Subscription, RenewSubscription)
- Add subscription.free locale key (ru/en/zh/fa)
- Fix TelegramLinkWidget NS_BINDING_ABORTED: move legacy widget callback to ref pattern, remove unstable deps (showToast, t, navigate) from useEffect — prevents iframe destruction on re-render
- Clean up OIDC effect deps
2026-04-03 17:23:38 +03:00
Fringg
9546e0ffe6 fix: add missing balance cache invalidation after mutations
- Subscription.tsx: devicePurchase + trafficPurchase onSuccess → invalidate ['balance']
- RenewSubscription.tsx: renewMutation onSuccess → invalidate ['balance']
- SubscriptionPurchase.tsx: purchaseMutation onSuccess → invalidate ['balance'] + ['subscriptions-list']
- subscription.ts: refreshTraffic uses withSubId (already fixed, formatting)
2026-03-26 10:44:00 +03:00
c0mrade
31d0953c23 feat: add WebBackButton to all sub-pages, widen renew page layout
- New WebBackButton component: visible on web, hidden in Telegram
  (native back button handles navigation there)
- Added to: Subscription detail, SubscriptionPurchase, RenewSubscription
- RenewSubscription: removed max-w-lg, grid layout for period cards
2026-03-24 14:01:55 +03:00
c0mrade
10824b7322 fix: show missing balance amount on renew page, no tariff switch in multi-tariff
- RenewSubscription: display actual missing amount instead of {{missing}} placeholder
- SubscriptionPurchase: suppress "switch tariff" title in multi-tariff mode
  (only renewal exists, no tariff switching)
2026-03-24 10:58:37 +03:00
c0mrade
82eb03dec9 feat: separate renewal and purchase flows in multi-tariff mode
Renewal flow (per-subscription):
- New /subscriptions/:id/renew page showing only period options for
  the specific tariff with balance display and renew button
- PurchaseCTAButton links to /renew in multi-tariff mode

Purchase flow (new tariffs only):
- Hide already purchased tariffs (is_purchased flag from backend)
- Fallback UI when all tariffs are owned
- Types: added is_purchased, all_tariffs_purchased fields
2026-03-24 10:47:49 +03:00
c0mrade
9d3fb37d60 fix: remove duplicate back buttons, improve multi-subscription UX
- Remove custom back buttons from Subscription detail and SubscriptionPurchase
  pages — native Telegram mini-app back button already handles navigation
- SubscriptionListCard: distinct trial badge with star icon and amber styling,
  trial cards get amber border/background for visual differentiation
- SubscriptionPurchase: change "Купить тариф" to "Новый тариф" when adding
  a new tariff in multi-subscription mode
- Subscription detail: show tariff name as title in multi-tariff mode
2026-03-23 21:38:04 +03:00
c0mrade
f4de6d8ad8 fix: multi-subscription UI audit fixes and cache invalidation improvements
- Fix AdminUserDetail multi-subscription display with useMemo optimization
- Update Dashboard subscription cards and purchase entry points
- Fix WebSocket notification handlers for multi-subscription context
- Update SubscriptionPurchase cache invalidation for multi-tariff mode
- Fix Subscriptions list page and navigation patterns
- Update App routing, DeepLinkRedirect, and CommandPalette for multi-sub
- Add SubscriptionListCard component
- Fix TopUpResult and PromoOffersSection navigation
2026-03-23 18:57:05 +03:00
c0mrade
bcbfa4191e feat: multi-tariff purchase UX - disable switch, show Buy for new tariffs, correct page title 2026-03-23 18:57:05 +03:00
c0mrade
820ba46cc4 feat: multi-subscription frontend support
- Add SubscriptionListItem and SubscriptionsListResponse types
- Add getSubscriptions/getSubscriptionById API methods
- Add optional subscriptionId parameter to all 30+ API methods
- Create /subscriptions page with subscription list cards
- Add /subscription/:subscriptionId route for per-subscription management
- Dashboard: show multi-tariff navigation block when user has 2+ subscriptions
- Subscription page: read subscriptionId from URL params, pass to all queries
- SubscriptionPurchase: accept subscriptionId from query params
- SubscriptionCardExpired: pass subscription.id to API calls
- Full backward compatibility: without subscriptionId, works as before
2026-03-23 18:57:05 +03:00
Fringg
9d519fb5ec fix: show error state instead of blank page on purchase-options failure
When the purchase-options API call failed (e.g. for email-registered
users), the page rendered only the header with no content. Now shows
an error message with retry button. Also adds a fallback for when
the API returns no available tariffs or periods.
2026-03-22 04:45:19 +03:00
Fringg
d34f5e8559 fix: hide trial banner when subscription expired banner is active 2026-03-20 07:18:11 +03:00
Fringg
ea06ad1d8f fix: show fallback when tariff has no available periods for renewal
When all periods are removed from a tariff, users saw an empty
purchase form with no way to renew. Now shows a message explaining
the situation and a button to choose a different tariff.
2026-03-10 01:27:48 +03:00
Fringg
69a8fe8e03 fix: force fresh balance data on purchase-options query
Added staleTime: 0 and refetchOnMount: 'always' to purchase-options
queries in SubscriptionPurchase and Subscription pages to prevent
stale balance_kopeks from causing incorrect insufficient funds display.
2026-03-09 01:07:49 +03:00
Fringg
8b5d777f0a feat: публичные лендинг-страницы для быстрой покупки VPN-подписок
- QuickPurchase: публичная страница покупки с выбором тарифа/периода/оплаты
- PurchaseSuccess: статус покупки с поллингом и копированием ссылки
- AdminLandings: управление лендингами (создание, сортировка, удаление)
- AdminLandingEditor: полнофункциональный редактор лендинга
- API-клиент landings.ts для всех эндпоинтов
- Роутинг /buy/:slug и /buy/success/:token
- Локализация ru/en/zh/fa для всех текстов лендинга
- Санитизация HTML/CSS, rate limit защита, DOMPurify
2026-03-06 07:02:21 +03:00
Fringg
d526d095de fix: заменить хардкодный зелёный (#3EDBB0) на акцентный цвет из темы
Все вхождения #3EDBB0, #2BC49A и rgba(62,219,176,...) заменены на
CSS-переменные --color-accent-400/500 из системы тем.

Затронутые компоненты:
- TrialOfferCard: кнопка, бордер, свечение, иконка
- Subscription: лейблы, иконки, кнопки паузы/копирования
- SubscriptionCardActive: бордер карточки, бейдж статуса
- SubscriptionPurchase: градиент триал-блока
- PurchaseCTAButton: градиент кнопки, иконка
- TrafficProgressBar: цвета прогресс-бара
- StatsGrid: убрана зависимость от useTrafficZone, используется accent напрямую
- trafficZone.ts: добавлены mainVar/mainVarRaw для CSS-переменных
- tailwind.config.js: trialGlow keyframes на accent цвет
2026-03-05 10:56:45 +03:00
Fringg
a3ddddfa8c fix: replace hardcoded green with theme-aware accent color
Normal traffic zone now uses configurable accent palette instead of
hardcoded success/green. Added useTrafficZone hook that resolves
mainHex dynamically from theme colors. Replaced emerald/teal classes
with success palette in SuccessNotificationModal. Fixed hardcoded
green hex values in Subscription and SubscriptionPurchase pages.
2026-03-04 02:50:28 +03:00
Fringg
4a68347ae8 revert: remove user-facing reset traffic toggle
Reset traffic on tariff switch is an admin-only setting.
Backend handles it via admin settings system (data-driven, no frontend code needed).
Reverted all user-facing toggle UI, API params, types, and translations.
2026-02-27 09:50:13 +03:00
Fringg
49fff8e855 feat: add reset traffic toggle on tariff switch
- Add reset_traffic parameter to previewTariffSwitch and switchTariff API calls
- Add reset_traffic_available/reset_traffic_default fields to TariffSwitchPreview type
- Add toggle switch in tariff switch preview modal (shown when backend enables it)
- Initialize toggle from server default (reset_traffic_default)
- Pass reset_traffic flag on switch execution
- Add translations for all 4 locales (ru, en, zh, fa)
2026-02-27 09:48:28 +03:00
Fringg
126f9ab9b9 refactor: extract purchase/renewal flow to separate page
Move ~1900 lines of purchase/renewal logic from Subscription.tsx into
a new SubscriptionPurchase.tsx page at /subscription/purchase.

- Create SubscriptionPurchase.tsx with tariffs grid, classic mode wizard,
  switch preview modal, and promo handling
- Create PurchaseCTAButton.tsx with animated gradient border, state-aware
  colors and context-aware text
- Create subscriptionHelpers.ts with shared utilities
- Add CopyIcon to shared icons module
- Register /subscription/purchase route with lazy loading
- Update SubscriptionCardExpired and PromoOffersSection navigators
- Add CTA translation keys to ru.json and en.json
- Remove all scrollToExtend references
2026-02-27 06:47:30 +03:00