- TariffFilter dropdown with checkboxes for filtering by tariff
- Column resizing via TanStack Table resize handles
- Add allTariffs locale key to all 4 languages
- Pass tariffs param to API
Add AdminTrafficUsage page showing per-user traffic statistics by node
with period filtering (1/3/7/14/30d), server-side sorting, search,
pagination, and CSV export. Uses @tanstack/react-table with manual
sorting and dynamic node columns.
- Info tab: promo group card with inline dropdown to change/remove group
- Balance tab: active promo offer display with deactivate button
- Balance tab: send promo offer form (discount %, valid hours)
- Add deactivateDiscount API method to promocodesApi
- Add locale keys for ru/en/zh/fa
- Fix race condition in subscription create (stale state read)
- Fix unhandled promise in handleInlineConfirm
- Remove unused legacy adminUsers block from ru.json
- Fix formatContent to handle mixed content (inline HTML + newlines)
- Only skip paragraph conversion for content with block-level HTML
- Add sanitizer support for <s>, <del>, <ins>, <tg-spoiler>
- Add prose styles for underline, strikethrough, and spoiler tags
- Light theme variants included
- Load panel + node data once on tab open (not per period change)
- Compute 7/14/30 day totals locally from cached daily data
- Add refresh button to subscription section
- No API calls when switching periods
- Add country_code to UserNodeUsageItem type
- Add getCountryFlag helper for country code to emoji mapping
- Show country flag next to node name in usage bars
- Add campaign card and referrals list to info tab
- Add panel config/links, live traffic, connection info to subscription tab
- Add node usage bars with 7/14/30 day period selector
- Add getPanelInfo/getNodeUsage API methods and types
- Add 18 new i18n keys across 4 languages
Replace ticket navigation with inline chat view. Clicking a ticket
opens the conversation directly within the user detail page with
message history, media support, and reply form.
Add ability to view user's tickets directly from the user detail page.
Backend gets user_id filter on tickets endpoint, frontend shows ticket
list with status badges, message preview and navigation to ticket.
Replace single channel radio with independent toggles allowing both
channels to be enabled at once with separate audiences and content.
When both enabled, sends two sequential API requests.
Replace generic placeholder icons with designs based on actual favicon
assets from payment provider websites. Updated icons for Platega,
Tribute, WATA, CloudPayments, Kassa AI, YooKassa, CryptoBot, Heleket,
MulenPay, PAL24, and Freekassa with correct brand colors and marks.
savedColorsRef was unconditionally updated in the serverColors sync
effect, including when queryClient.setQueryData was called from
updateDraftColor for live preview. This made hasUnsavedChanges always
false, hiding the save/cancel buttons. Move savedColorsRef update
inside the sync condition so it only updates when no local edits exist.
Trial users saw an "insufficient balance" prompt suggesting to top up
rubles, but the wheel only accepts Telegram Stars (via invoice) or
subscription days. Stars payment via invoice doesn't require ruble
balance, so the spin button should not be disabled for it.
- Add OAuthProvider type and extend User.auth_type union
- Add OAuth API methods (providers, authorize, callback)
- Add loginWithOAuth to auth store
- Create OAuthCallback page with state validation
- Create OAuthProviderIcon component with brand SVGs
- Add OAuth buttons to Login page between Telegram and Email
- Add OAuth callback route to App.tsx
- Add translations for ru, en, zh, fa
Onboarding tutorial was appearing on top of the channel subscription
screen because Dashboard still mounts behind BlockingOverlay.
Added blockingType check to prevent onboarding from triggering.