- 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
- 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 URL.revokeObjectURL on unmount and media removal in
AdminBroadcastCreate, AdminPinnedMessageCreate, Support
- Track blob URLs via refs to revoke before creating new ones
- Add clearCreateAttachment/clearReplyAttachment helpers in Support
to properly revoke blob URLs when clearing attachments
- Cap adminTraffic cache at 20 entries with FIFO eviction to prevent
unbounded memory growth from different filter combinations
Mirrors campaign.ts localStorage pattern to capture ?ref= from URL and pass
referral_code to backend during Telegram Widget, OAuth, email login, and
Mini App authentication. Fixes redirect loop when email auth is disabled.
- 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
- 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)
- Branding cache moved from localStorage to sessionStorage so it clears
when the mini-app is closed, preventing stale names after admin updates
- Added initialDataUpdatedAt: 0 to all branding queries so fresh data is
always fetched on page refresh while showing cached data instantly
- One-time migration moves existing localStorage value to sessionStorage
- Aurora component now checks WebGL availability upfront, skipping all
hooks and subscriptions when WebGL is not supported
- 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
Skip code-based flow for unverified emails — replace email directly
and send verification to the new address. Show success step immediately
instead of asking for a verification code.
- Validate authorize_url is HTTPS before redirect (open redirect prevention)
- encodeURIComponent on provider name in API URL paths (path traversal prevention)
- encodeURIComponent on referralCode in t.me deep link
- Gate console.warn behind import.meta.env.DEV (no info leak in prod)
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 connected devices in subscription tab with ability to:
- View device platform, model, HWID and connection date
- Delete individual devices
- Reset all devices at once
Logo images were exposing the backend API URL in the DOM via <img src>.
Now preloadLogo() fetches the image as a blob and serves it through
URL.createObjectURL(), so only blob: URLs appear in the page source.
Blob is invalidated on logo upload/delete.
- Add CountryFilter dropdown with flag emoji + node count per country
- Country filter merges with node filter for both table and CSV export
- Pass total/node GB/day thresholds to backend for risk columns in CSV
- CSV now includes Risk Level, Risk Ratio, Risk GB/day when thresholds set
- Add NodeFilter component with flag emojis and checkbox dropdown
- Add StatusFilter component with colored status dots
- Add custom date range picker (calendar toggle, from/to date inputs)
- Wire all filters to backend params (nodes, statuses, start_date, end_date)
- CSV export passes all active filters and date range
- Add displayNodes memo for table column filtering
- Add i18n keys for nodes, statuses, dates in ru/en/zh/fa
- Add NodeFilter dropdown with flag emojis and checkbox selection
- Add StatusFilter dropdown with colored status dots
- Add DateRangePicker with From/To date inputs, toggle from period mode
- Devices column now shows N/M (connected/limit) with accent color
- Export CSV passes all active filters to backend
- New i18n keys for nodes, statuses, dates in ru/en/zh/fa
- Add 5-min in-memory cache in API layer keyed by request params
- Replace blocking spinner with animated progress bar during refresh
- Keep stale data visible while fetching (opacity dim)
- Prefetch all periods in background for instant switching
- 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
- 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
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.
- 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
- Add fullDeleteUser API method calling DELETE /admin/users/{id}/full
- Add Reset trial, Reset subscription, Disable, Delete buttons to AdminUserDetail info tab
- Implement inline confirm pattern (click → "Are you sure?" → execute, 3s timeout)
- Delete now calls /full endpoint removing user from bot DB and Remnawave panel
- Remove UserActionsMenu dropdown, ConfirmationModal and related code from AdminUsers list
- Update delete confirmation text in ru/en locales to reflect full deletion
- Skip token refresh/Bearer header for auth endpoints in request interceptor
- Wait for auth store initialization before attempting Telegram login
- Clear stale session tokens when init data changes (WebView persistence)
- Show backend error details instead of generic messages
Implement DnD reorder for tariffs using @dnd-kit, matching the
pattern from AdminPaymentMethods. Add updateOrder API method
and i18n keys for all locales.
- Add svgIconKey to RemnawavePlatform and RemnawavePlatformData types
- Render platform OS icons from svgLibrary in AdminApps tabs and Connection page
- Replace platform dropdown with icon pill buttons on connection page
- Use .card class with colored left border for block cards
- Unify all back buttons with AdminBackButton pattern (border + bg)
- Fix app chips and platform tabs to not blend with background (btn-secondary style)
- Use accent outlined style for block action buttons matching original RemnaWave UI
- Use btn-secondary for tutorial button