Commit Graph

1296 Commits

Author SHA1 Message Date
Fringg
262303d623 feat: add sales_stats RBAC permission section to frontend
- Update route guard and menu item to use sales_stats:read
- Add sales_stats:read to marketer preset
- Add i18n translations for sales_stats section (ru, en, fa, zh)
2026-03-05 05:46:07 +03:00
Fringg
2fc0759f89 feat: account merge flow — merge redirect, error handling, server-complete linking
- Добавлен merge_required + merge_token redirect в OAuthCallback и LinkTelegramCallback
- Server-complete OAuth linking для Mini App (внешний браузер)
- getErrorDetail: единый экстрактор ошибок из axios response
- LinkTelegramCallback: типизированный catch с getErrorDetail
- Удалён мёртвый экспорт getAndClearOAuthState
- CSRF валидация для Telegram и OAuth linking flows
- Типы ServerCompleteResponse, LinkCallbackResponse
2026-03-05 05:25:50 +03:00
Fringg
0d99ea0069 refactor: review round 2 — remove dead code, fix type safety, improve UX
- Remove LinkOAuthCallback.tsx (dead code) and its route from App.tsx
- Move LINK_OAUTH_* constants to OAuthCallback.tsx
- Replace local ServerLinkResult with LinkCallbackResponse from types
- Move merge navigate() from render body to useEffect
- Track errorMode to show correct CTA (Return to Telegram vs Back to Login)
- Remove non-null assertions with proper narrowing
- Extract getErrorDetail helper for error casting
- Add smart polling success detection (stop + toast when linked count increases)
2026-03-05 03:10:22 +03:00
Fringg
da1926f0e1 fix: review findings — polling fallback, sessionStorage cleanup, UX
- Add 5s polling for 90s after opening external browser link (Mini App)
- Show info toast "Continue in browser" when opening external OAuth
- Fix premature sessionStorage cleanup: peek-then-clear pattern
- Use useIsTelegram() hook instead of direct isInTelegramWebApp()
- Add continueInBrowser i18n key (ru, en, zh, fa)
2026-03-05 02:33:33 +03:00
Fringg
7c30a1eab6 feat: open OAuth linking in external browser from Telegram Mini App
- Rewrite OAuthCallback.tsx to handle 3 modes: login, link-browser,
  and link-server (external browser without JWT)
- Add linkServerComplete API method (no JWT, auth via state token)
- Update ConnectedAccounts to use platform.openLink() in Mini App
- Add server-complete endpoint to AUTH_ENDPOINTS (skip Bearer token)
- Enable refetchOnWindowFocus for linked-providers query
- Add returnToTelegram/openTelegram i18n keys (ru, en, zh, fa)
2026-03-05 02:24:28 +03:00
Fringg
9b4a8512c2 fix: remove unused linkTelegramWidget i18n key from all locales 2026-03-04 17:21:16 +03:00
Fringg
a6fabb1d9d feat: add Telegram account linking UI with CSRF protection
- TelegramLinkWidget component with Login Widget for browser users
- One-click initData linking for Mini App users
- LinkTelegramCallback page with CSRF state validation
- URL credential clearing via history.replaceState
- Merge flow support with replace navigation
- i18n keys for all 4 locales (ru, en, zh, fa)
2026-03-04 17:03:48 +03:00
Fringg
584f00297b fix: add Referrer-Policy to prevent merge token leakage via Referer header 2026-03-04 16:14:51 +03:00
Fringg
8ad0500cc8 fix: double-click guard on link, wall-clock timer, blur cleanup
- Add linkingProvider state to prevent double-click on Link button
- Use wall-clock based countdown timer to prevent drift
- Clean up onBlur setTimeout ref on unmount
2026-03-04 16:05:24 +03:00
Fringg
fba4481799 fix: move useState before useMutation for consistent hook ordering 2026-03-04 15:57:04 +03:00
Fringg
71198ab18a refactor: extract shared ProviderIcon, fix canUnlink hiding all buttons
- Extract TelegramIcon + EmailIcon to shared ProviderIcon component
- Remove duplicated icons from ConnectedAccounts and MergeAccounts
- Remove isPending from canUnlink (buttons already have disabled prop)
- Add onSettled to reset confirmingUnlink state after mutation
2026-03-04 15:46:53 +03:00
Fringg
3418ba9b8d fix: prevent onBlur race cancelling unlink confirmation
Add 150ms delay before resetting confirmation state so the click
event fires before blur resets it.
2026-03-04 15:35:45 +03:00
Fringg
d0c01a0e5c fix: replace window.confirm with inline confirmation for unlink
window.confirm() is silently suppressed in Telegram Mini Apps and iOS
WebView, making unlink completely non-functional on mobile. Replaced
with two-click inline confirmation: first click shows destructive
"Confirm disconnect?" button, second click executes unlink. Button
resets on blur.
2026-03-04 15:30:00 +03:00
Fringg
e447e993cb fix: accessibility, query cache clear, post-merge navigation
- Add aria-hidden="true" to all decorative SVGs (TelegramIcon, EmailIcon
  in MergeAccounts + ConnectedAccounts, all 4 OAuthProviderIcon SVGs)
- Add role="radiogroup" with aria-label to subscription choice container
- Clear react-query cache after merge to prevent stale data
- Wrap checkAdminStatus() in try-catch to prevent throw after token set
- Navigate to /profile/accounts after merge instead of /
- Import useQueryClient for cache management
2026-03-04 15:02:08 +03:00
Fringg
579f47e563 fix(merge): accessibility, token guard, state cleanup
- Add role="radio" + aria-checked to subscription radio buttons
- Add aria-hidden="true" to decorative SVG icons
- Treat success=true with null tokens as error (show error toast)
- Guard auto-select useEffect from overwriting user's manual choice
- Clear sessionStorage on OAuth state validation failure
2026-03-04 08:12:18 +03:00
Fringg
aa26059e00 fix: second round review fixes for merge UI
- Fix false success toast when response.success is false (CRITICAL)
- Remove mergeToken! non-null assertion in queryFn
- Add early return for missing mergeToken param
- Zero-pad minutes in formatCountdown (MM:SS format)
- Clamp negative seconds in formatCountdown
- Block all unlink buttons while any unlink mutation is pending
- Clear OAuth state only after validation succeeds (not before)
- Split getAndClearLinkOAuthState into read + clear functions
2026-03-04 07:56:19 +03:00
Fringg
58cf1e3b50 fix: harden merge UI and improve error handling
- MergeAccounts: guard mutationFn against null token/userId
- MergeAccounts: call checkAdminStatus after successful merge
- MergeAccounts: add fallback when success but tokens null
- MergeAccounts: fix ErrorState showing "expired" for all errors
- MergeAccounts: fix formatCountdown dead ternary and hardcoded English
- MergeAccounts: add staleTime/refetchOnWindowFocus to preview query
- MergeAccounts: remove manual useCallback (React Compiler handles it)
- LinkOAuthCallback: add toast feedback on all error/success paths
- ConnectedAccounts: use invalidateQueries instead of refetch
- ConnectedAccounts: add error state rendering
- ConnectedAccounts/LinkOAuthCallback: share sessionStorage key constants
- i18n: add missing profile.accounts.linking key to zh and fa locales
2026-03-04 07:47:36 +03:00
Fringg
93f97d45be feat: account linking and merge UI for cabinet
Add Connected Accounts page (link/unlink OAuth providers), Link OAuth
Callback handler, and Merge Accounts page with subscription comparison
and user choice. Includes API methods, TypeScript types, routes in
App.tsx, navigation from Profile, and i18n for all 4 locales (ru, en,
zh, fa). Merge page works without JWT auth (validated by merge token).
2026-03-04 07:25:45 +03:00
Egor
126443f194 Merge pull request #247 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.23.1
2026-03-04 06:15:08 +03:00
github-actions[bot]
7e190543dd chore(main): release 1.23.1 2026-03-04 03:14:28 +00:00
Egor
4359202f76 Merge pull request #246 from BEDOLAGA-DEV/dev
Dev
2026-03-04 06:14:06 +03:00
Fringg
8157ca5f02 fix: ordered list numbering in Info page shows correct sequence
Each numbered rule (1, 2, 3...) was rendered as separate <ol> elements
all starting from 1. Added start attribute to preserve original numbering
and allowed it through DOMPurify sanitization.
2026-03-04 04:49:40 +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
Egor
f74a67037b Merge pull request #244 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.23.0
2026-03-02 22:27:47 +03:00
github-actions[bot]
c6dd2f5484 chore(main): release 1.23.0 2026-03-02 19:27:27 +00:00
Egor
a1dc5744f6 Merge pull request #243 from BEDOLAGA-DEV/dev
Dev
2026-03-02 22:26:41 +03:00
Fringg
f652936d78 fix: tile noise texture instead of stretching on large screens
Add background-size: 200px and background-repeat: repeat so the SVG
noise pattern tiles at its native resolution instead of stretching
across the entire viewport on high-res displays.
2026-03-02 22:22:00 +03:00
Fringg
f012710df0 feat: add daily deposits by payment method chart
Add MultiSeriesAreaChart showing daily deposit amounts per payment
method with human-readable labels and currency formatting. Memoize
all derived data before early returns for React Compiler compat.
2026-03-02 22:08:16 +03:00
Fringg
2235b3cb77 feat: add daily traffic & device purchase chart to addons stats
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.
2026-03-02 21:57:18 +03:00
Fringg
4622b4b200 feat: enhance sales stats with device stats, per-tariff charts, and dual-series trials
- 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
2026-03-02 21:42:25 +03:00
Fringg
14e5f436ce fix: bar chart white hover cursor on dark theme
Recharts BarChart default tooltip cursor renders a white Rectangle
on hover which washes out the dark theme. Set cursor fill to grid
color with low opacity for a subtle theme-appropriate highlight.
Fixes addons "By package" and deposits "By payment method" charts.
2026-03-02 21:09:36 +03:00
Fringg
a47c222310 feat: add admin sales statistics dashboard with 5 analytics tabs
- Add sales stats API client with typed interfaces for all endpoints
- Implement AdminSalesStats page with summary cards and period selector
- Add TrialsTab with provider breakdown donut chart and daily area chart
- Add SalesTab with tariff/period breakdown and daily revenue chart
- Add RenewalsTab with period comparison and trend indicators
- Add AddonsTab with package breakdown bar chart
- Add DepositsTab with payment method breakdown bar chart
- Add SimpleBarChart, SimpleAreaChart, DonutChart components
- Add PeriodSelector with preset periods and custom date range
- Full responsive design (mobile/tablet/desktop/TG Mini App)
- ARIA accessibility (tablist, tab, tabpanel, aria-selected)
- Error handling with isError on all queries
- Empty data guards on all chart components
- i18n support across all 4 locales (en, ru, zh, fa)
2026-03-02 20:34:39 +03:00
Fringg
673de08dd4 fix: improve campaign stats, shared chart components, and i18n coverage
- 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
2026-03-02 20:34:24 +03:00
Fringg
c7d05c4809 feat: add recharts analytics to admin campaign stats page
- 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
2026-03-02 06:10:20 +03:00
Fringg
60f16e64e8 fix: support VK ID OAuth 2.1 device_id in frontend
- Extract device_id from VK callback URL query params
- Pass device_id through store → API → backend
- Add useRef guard to prevent useEffect double-fire
- Fix URL validation catch-block anti-pattern in Login
- Improve error extraction in OAuthCallback (show Error.message)
2026-03-02 04:10:05 +03:00
Fringg
3f050396b8 fix: align RecentPaymentItem types with backend schema
- telegram_id: number → number | null (email-only users)
- Add email field
- Fix username, payment_method, description nullability
2026-03-02 02:42:14 +03:00
Fringg
11343f4f12 fix: align TypeScript types with backend referral schemas
- Add campaign_name field to ReferralEarning interface
- Fix telegram_id to number | null in TopReferrerItem (email-only users)
- Add email field to TopReferrerItem
2026-03-02 02:35:00 +03:00
Fringg
75a6149e2d feat: display per-campaign stats on partner detail page
- Add registrations_count, referrals_count, earnings_kopeks to campaign type
- Show per-campaign stats grid (registrations, referrals, earnings) under each campaign card
- Use conditional coloring for zero earnings (neutral instead of green)
2026-03-02 01:09:55 +03:00
Fringg
a933f661e4 perf: optimize animated backgrounds for mobile — reduce GPU load and memory pressure
- Add useAnimationLoop hook with FPS throttling (30fps mobile/60fps desktop),
  Page Visibility API pause, and Telegram WebApp activated/deactivated events
- Add useAnimationPause hook for CSS/Framer Motion components
- Validate animation config with type allowlist, numeric clamping, JSON size guard
- Move ctx.setTransform from per-frame to init/resize across all canvas backgrounds
- Move ctx.lineCap to init/resize in vortex, replace Float32Array.set with direct writes
- Pre-compute shooting star delay instead of per-frame Math.random
- Cap DPR to 1.5 on mobile, reduce particle counts, cap blur to 4px
- Disable aurora CSS animation on mobile, remove blur on mobile spotlight
- Remove mix-blend-hard-light on mobile gradient-animation
- Add NaN/Infinity guard to clampNumber, remove dead CSS variables
- Add conditional unmount for Framer Motion backgrounds when paused
- Add animationPlayState pause for CSS-animated backgrounds
2026-03-01 22:36:57 +03:00
Fringg
430b703bbe fix: improve light theme visibility for inner panels on subscription page
Replace hardcoded dark-800/50 backgrounds and dark-700/50 borders with
isDark-conditional classes using champagne palette for light mode:
- Collapsed accordion buttons (4x)
- Expanded panels (4x)
- Traffic/server selector unselected state (2x)
- Info/warning boxes (2x)
- Section divider (1x)
2026-03-01 19:29:27 +03:00
Fringg
4cdff9730b fix: improve light theme visibility for dashboard and subscription cards
- Increase card opacity and shadow contrast in glassTheme for light mode
- Add accent-tinted borders and shadows to subscription cards (active, expired, trial)
- Fix grid patterns to use dark lines instead of white in light mode
- Fix trial CTA button: solid green with dark text instead of invisible transparent
- Fix trial icon background: light accent gradient instead of hardcoded dark
- Add + prefix to referral earnings in StatsGrid
2026-02-28 06:37:40 +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
d2f02d605c fix: clean up expired trial card - remove redundant badge and subtitle
- Remove red "Пробный период" badge from expired trial card
- Remove "Пробный период завершен" subtitle text
- Simplify header layout (no justify-between needed without badge)
- Change "Тарифы" button link to /subscription/purchase
2026-02-27 09:38:33 +03:00
Fringg
396f814cbd fix: remove devices stat block, stretch countdown to full width
Remove the separate devices count card from the stats row since device
info is already shown in the connect-device card above. Stretch the
countdown timer to full width with timer on the left and expiry date
on the right. Revert squeezed font sizes now that space is available.
2026-02-27 09:31:22 +03:00
Fringg
d567817e05 fix: show progress bar instead of dots when device_limit > 10
Match the Dashboard behavior: show individual dots for <= 10 devices,
switch to a compact progress bar for higher limits (e.g. 18 devices).
Prevents dot overflow breaking the connect-device card layout on mobile.
2026-02-27 09:27:36 +03:00
Fringg
96bcc76d69 fix: prevent countdown timer overflow on narrow mobile screens
Add min-w-0 + overflow-hidden to the countdown card to prevent it from
blowing out the grid column. Reduce number font from 20px to 18px on
mobile (20px on sm+), tighten gaps and colon sizes to fit within the
50% grid column on 375px screens.
2026-02-27 08:51:56 +03:00
Fringg
d89c534c0b fix: rewrite BackgroundBoxes from 225 DOM divs to single canvas element
Root cause: 225 individually animated DOM elements forced Chrome's
compositor to create separate paint regions per element. Any hover
state change on page content triggered re-compositing of all 225
regions, causing visible flickering on all pages.

Canvas fix: single <canvas> element renders the entire grid effect
via requestAnimationFrame. Canvas content is pixel-based and cannot
be affected by DOM hover state changes on other elements.

Additional fixes:
- Fix z-index collision: portal z-index -1 → -2 (was same as body::before noise)
- Replace all transition-all with specific properties on .btn, .btn-icon,
  .input, .nav-item, .bottom-nav-item, checkbox
- Remove backdrop-blur-sm from desktop .bento-card and .card
  (forced Chrome to re-sample animated background pixels on every hover)
2026-02-27 08:46:22 +03:00
Fringg
fe32322c32 perf: remove permanent GPU layer promotion from cards to fix flickering
Remove translateZ(0) from base states of .bento-card, .card, .glass
and their light theme variants. Remove transform-gpu from Card.tsx.
Change bentoFadeIn animation to end with transform:none instead of
translateY(0). GPU promotion now only occurs during hover/active
interactions, preventing Chrome from creating excessive compositing
layers that cause flickering with animated backgrounds.
2026-02-27 08:27:07 +03:00
Fringg
7f17d95ed6 fix: replace framer-motion with CSS keyframes in boxes background
The boxes background was creating 225 motion.div elements, each running
independent opacity animations via framer-motion JS on the main thread.
This blocked hover transitions on cards, causing visible flickering.

CSS @keyframes run on the compositor thread and have zero main-thread
cost, eliminating the interference with user interactions.
2026-02-27 08:18:24 +03:00