Add DualAreaChart to addons tab showing daily traffic purchases vs
device purchases with date-union merge. Add daily_devices field to
AddonsStats type and i18n keys for all 4 locales.
- Add DualAreaChart component for two-series visualization (registrations vs trials)
- Add MultiSeriesAreaChart component for N-series tariff breakdown with dynamic pivoting
- AddonsTab: add device purchases and device revenue stat cards
- SalesTab: add per-tariff daily sales chart using MultiSeriesAreaChart
- TrialsTab: replace single-series area chart with dual-series registrations + trials chart
- Update TypeScript interfaces to match backend schema changes
- Add i18n keys for all new UI elements across en, ru, zh, fa locales
- Extract shared chart constants to constants/charts.ts
- Add TREND_STYLES to stats/constants.ts for reuse
- Fix useChartColors with MutationObserver for theme changes
- Fix DailyChart date parsing to prevent timezone shift
- Add truncate to StatCard value for overflow safety
- Fix CampaignCard copy feedback inside try block
- Add NaN validation and staleTime to AdminCampaignStats
- Replace hardcoded strings with i18n keys in Referral page
- Add missing i18n keys across all 4 locales (en, ru, zh, fa)
- Add sales stats route to AdminPanel and App router
- Move shared chart components (DailyChart, PeriodComparison, StatCard) to src/components/stats/ with configurable label props
- Create shared types for chart data decoupled from partner API
- Add campaign chart data API client with deposits/spending split
- Enhance AdminCampaignStats with daily trends chart, period comparison, top registrations, and deposit/spending stat cards
- Add useChartColors hook with SSR guard and theme-aware CSS variable parsing
- Add cross-platform clipboard utility with execCommand fallback for Telegram WebView
- Add i18n keys for chart analytics across all 4 locales (en, ru, zh, fa)
- Responsive fixes: truncation for long names/values, responsive text sizing, touch-friendly copy buttons
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.
- 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)
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
1. Add desired commission percent field to partner application form
and admin review page (Bug 1)
2. Add prominent "Requested Amount" row in admin withdrawal detail (Bug 2)
3. Switch withdrawal input from kopecks to rubles with auto-conversion
on submit (Bug 3)
Includes i18n updates for all 4 locales (ru, en, zh, fa).
- New ConnectionQR page with fullscreen QR display (no modal)
- QR button in InstallationGuide header next to platform selector
- Respects hideLink setting: shows URL below QR only when visible
- i18n translations for ru, en, zh, fa
- Add has_subscription to WheelConfig type
- Disable spin button when user has no subscription
- Add noSubscription guard in handleUnifiedSpin handler
- Show warning banner directing user to activate subscription
- Prevent banner stacking (noSubscription takes priority over daily limit)
- Add noSubscription i18n keys for ru, en, zh, fa
- Rewrite TrafficProgressBar with multi-segment gradient fill, flex-based
zone tints, shimmer + highlight overlays, radial glow at fill edge
- Rewrite SubscriptionCardActive with zone header, big percentage on right,
connect device card with device dots, tariff/days-left two-column row,
sparkline placeholder, traffic refresh controls
- Rewrite SubscriptionCardExpired with red glow, grid pattern, gradient
renew button, outline tariffs button
- Rewrite TrialOfferCard with animated glow background, grid pattern,
icon glow animation, price tag with old price, gradient CTA buttons
- Rewrite StatsGrid with 2x2 card layout, icon+label+chevron header,
big value numbers, zone-colored balance/earnings cards
- Update Sparkline with color prop and last-point dot indicator
- Update useAnimatedNumber to use easeOutExpo matching prototype
- Add formatTraffic utility for MB/GB/TB unit formatting
- Add mainHex to trafficZone for inline style support
- Update animations to match prototype timing
- Add new i18n keys for redesigned components
Decompose monolithic Dashboard into SubscriptionCardActive,
SubscriptionCardExpired, TrialOfferCard, and StatsGrid sub-components.
Replace Subscription page progress bar with TrafficProgressBar compact.
Add i18n keys for traffic zones, stats labels, expired/trial states.
- Move RBAC translations from banSystem to admin namespace in all 4 locales
- Fix AccessPolicy type: action (string) -> actions (string[])
- Fix AuditLogEntry type to match backend: add status, request_method, request_path, resource_type, user info
- Fix AuditLogFilters: resource -> resource_type, add status filter
- Handle null details safely in audit log expanded view
- Fix policy form submission and display to use actions array
- Add global settings section (CHANNEL_IS_REQUIRED_SUB, trial/paid toggles)
at top of AdminChannelSubscriptions page
- Add per-channel disable_trial_on_leave and disable_paid_on_leave toggles
in each channel card with inline Toggle controls
- Update RequiredChannel type and API request interfaces with new fields
- Add translations for globalSettings and perChannel in en/ru/fa/zh locales
- Admin panel: added Edit button on channel cards with inline edit form
(title, link, sort order) using existing PATCH API
- Subscription screen: filter out already-subscribed channels so users
only see what they still need to subscribe to
- Updated channelIdHint to remove @username reference (numeric only)
- Added i18n keys: edit, editing, form.save (en/ru/fa/zh)
- Channel subscription blocking screen with per-channel status display
- Safe URL handling with protocol validation (no open redirect)
- Race-condition-safe subscription check with useRef guard
- Admin channel management page with create, toggle, delete
- Error handlers on all admin mutations with haptic feedback
- Proper type guard for channel subscription error detection
- Accessibility: aria-labels on icon-only buttons
- Localization: en, ru, zh, fa translations
Add 60-second cooldown timer on resend verification email button to
prevent spam. Remove auth_type restriction on change email button so
OAuth users can also change their email.
servers_count already represents squad count on backend.
Renamed display labels to "locations" on tariff cards and
confirmation view. Server names still shown in subscription card.
- Add partner badge to campaigns list
- Add partner selector dropdown in campaign edit
- Support ?partnerId= query param in campaign create (replaces separate page)
- Filter already-assigned campaigns in partner assign flow
- Show taken campaigns greyed out with partner name
- Delete AdminPartnerCampaignCreate (replaced by query param approach)
- Add partner translations (ru, en, zh, fa)
- New AdminPartnerSettings page with validation (pattern from AdminTicketSettings)
- Settings gear button on AdminPartners header
- Hide partner/withdrawal sections when partner_section_visible is false
- Use custom requisites_text as label in withdrawal form
- i18n keys for ru/en
- Add blocked_count to Broadcast interface
- 4-column stats grid with blocked card (warning color)
- Show blocked count in broadcast list when > 0
- Fetch single broadcast by ID instead of listing all
- Add i18n keys for blocked/blockedShort in ru/en/zh/fa
- extract formatDate, statusBadgeConfig, getRiskColor to shared utils
- use explicit unknown fallback for unrecognized status values
- add missing 'unknown' i18n keys for withdrawal status
1. Remove is_active filter from campaign assign page so inactive
campaigns are also visible (with badge)
2. Redesign partner campaign cards with separate bot/cabinet links,
detailed bonus descriptions, and per-link copy buttons
- Admin partners page: list partners, view applications, approve/reject
- Admin partner detail: stats, commission management, campaign assignment
- Admin withdrawals page: list with risk scoring, status filters including cancelled
- Admin withdrawal detail: fraud analysis, approve/reject/complete actions
- Partner API client with full TypeScript interfaces
- Withdrawal API client with admin and user endpoints
- Referral page: partner application form, withdrawal balance and history
- Navigation: partners and withdrawals in admin panel marketing group
- i18n: full translations for ru, en, zh, fa locales
- Neutral fallbacks for unknown status badges
- Add campaign.ts utility (capture from URL, localStorage with TTL, validation)
- Pass campaign_slug in all auth API methods (telegram, widget, email, oauth)
- Consume slug in auth store login methods, set pendingCampaignBonus state
- Add CampaignBonusNotifier component (toast on bonus, mounted in AppShell)
- Show web_link alongside bot deep_link in AdminCampaignStats
- Add CampaignBonusInfo type with union bonus_type
- Fix VerifyEmail: ref guard against StrictMode double-fire, setTimeout cleanup
- Fix AdminCampaignStats: setTimeout refs with cleanup, i18n-aware locale
- Wrap all localStorage access in try/catch (Safari private browsing safety)
- Add campaignBonus translations (ru/en/fa/zh)
- Extract normalizeConfig() for consistent response normalization
- Add onError handlers to mutations with useNotify
- Add window.confirm before destructive reset action
- Add resetConfirm translation key to all locales
- Add Toggle per section card to show/hide button in main menu
- Add collapsible locale label inputs (ru, en, ua, zh, fa) per section
- Normalize server response for backward compatibility with older API
- Update all 4 locale files with new translation keys
Adds a 'default' style option that removes color from buttons, showing
Telegram's native default style. Updates type, UI chip, preview, and
translations for all 4 locales.
Visual editor in admin settings for configuring Telegram button colors
and custom emoji IDs per menu section. Includes API client, draft state
management, save/reset, and translations for ru/en/fa/zh locales.
- API client with full CRUD, broadcast, activate/deactivate, unpin endpoints
- List page with active/inactive badges, action buttons, pagination
- Create/edit form with content editor, media upload, display settings toggles
- Routes and navigation in admin marketing group
- i18n translations for ru, en, fa, zh
- Fix falsy check: selectedTrafficPackage !== null instead of truthy
(gb=0 for unlimited was evaluated as false, hiding the buy button)
- Show "Buy Unlimited" instead of "Buy 0 GB" for unlimited packages
- Add buyUnlimited translation key to all 4 locales
Update delete mutation to use affected_subscriptions from API response.
Show contextual success notification with subscription count.
Add deleteSuccessWithSubscriptions translation key in all 4 locales.
Show different messages depending on user role:
- Regular users see a friendly "check back later" message
- Admins see a prompt with a link to /admin/apps settings