Commit Graph

1835 Commits

Author SHA1 Message Date
Fringg
b4eb0fa859 feat: add Lava payment provider support
- METHOD_LABELS entry for lava
- Custom SVG icon: dark base with orange-red lava flow and ember dots
- Admin settings tree node: payments_lava
- Locale strings (ru/en/zh/fa) for descriptions and admin labels
2026-05-04 20:16:01 +03:00
Fringg
7def84718b feat: add Jupiter and Donut payment provider support
- METHOD_LABELS entries for jupiter and donut
- Custom SVG icons: Jupiter (planet with ring), Donut (glazed donut)
- Admin settings tree nodes: payments_jupiter, payments_donut
- Locale strings (ru/en/zh/fa) for descriptions and admin labels
2026-05-04 19:36:35 +03:00
Fringg
60c835301d fix: move reissue button to standalone block outside device_limit guard
The reissue button was inside the Additional Options card which is gated
by device_limit !== 0, so it was hidden when device_limit was 0. Move it
to its own card block with independent visibility condition.
2026-05-04 17:41:21 +03:00
Fringg
f7cc445127 feat: add subscription reissue button with cooldown timer
- Add revokeSubscription API method
- Add reissue button in Additional Options with amber styling,
  destructive confirm dialog, 15-min cooldown with countdown timer,
  localStorage persistence across page reloads
- Add i18n keys in all 4 locales (en, ru, zh, fa)
2026-05-04 17:22:05 +03:00
Fringg
7d940091fa feat: add Antilopay payment provider support
- Add antilopay to METHOD_LABELS for stats charts
- Add PaymentMethodIcon case with amber gradient SVG
- Add payments_antilopay to admin settings tree
- Add i18n keys in all 4 locales (en, ru, zh, fa)
2026-05-04 07:44:52 +03:00
Fringg
85a34b1947 feat: add Etoplatezhi payment provider support
- Add etoplatezhi to METHOD_LABELS for stats charts
- Add PaymentMethodIcon case with green gradient SVG
- Add payments_etoplatezhi to admin settings tree
- Add i18n keys in all 4 locales (en, ru, zh, fa)
2026-05-04 07:18:14 +03:00
Fringg
7d29285ff6 fix(i18n): add missing broadcast preview locale keys
Add preview, previewEmpty, btnBalance, btnPartners, btnPromocode,
btnConnect, btnSubscription, btnSupport, btnHome keys to en.json
and ru.json under admin.broadcasts.
2026-05-04 06:27:41 +03:00
Fringg
65f94931c5 feat: add TV Quick Connect to connection page for Android TV / Apple TV
When user selects Android TV or Apple TV platform (from non-TV device),
shows 5-char code input + QR scanner to send subscription to TV via
Happ TV API. Hybrid QR strategy: native Telegram scanner on mobile,
html5-qrcode CDN fallback on desktop. i18n keys for ru/en/zh/fa.

Based on PR #415 by @smediainfo.
2026-05-04 06:22:29 +03:00
Fringg
d21c6637bf feat(admin/broadcasts): add preview buttons for Telegram + Email broadcasts
Add BroadcastPreview component with local rendering of Telegram messages
(HTML tokenizer with tag whitelist, no dangerouslySetInnerHTML) and Email
preview (sandboxed iframe). Preview buttons appear in broadcast create page
section headers, disabled when content is empty.

Based on PR #416 by @smediainfo.
2026-05-04 06:18:12 +03:00
Fringg
58887138fc feat: add Apple IAP (apple_iap) payment method support
Add apple_iap across all payment surfaces: method label, icon (Apple
logo SVG), admin settings tree (APPLE_IAP category), and all four
locale files (en, ru, fa, zh) with payment description + tree label.
2026-05-04 06:01:20 +03:00
Egor
f0c60e0bff Merge pull request #414 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.50.0
2026-04-29 12:13:38 +03:00
github-actions[bot]
400d9be345 chore(main): release 1.50.0 2026-04-29 09:13:13 +00:00
Egor
945c829a98 Merge pull request #413 from BEDOLAGA-DEV/dev
Dev
2026-04-29 12:12:34 +03:00
Fringg
afffab17d3 feat: bulk delete subscription protection for active paid subs
Add force_delete_active_paid guard to prevent accidental deletion of
active paid subscriptions. Shows warning with count and requires
explicit checkbox confirmation. Also fixes allVisibleSubscriptionIds
to use filteredUsers and getFilteredSubs to respect trialOnly filter
on subscription sub-rows.
2026-04-29 11:48:59 +03:00
Fringg
ae55a18fc9 feat: dedicated RBAC permissions for bulk actions, info pages, news 2026-04-29 11:14:38 +03:00
Fringg
020f4c95e2 feat: landing analytics goals, daily bar chart, referrer tracking, contact persistence
- Add per-landing analytics goals (view/click) with admin editor toggle
- Add sticky pay button option for mobile landing pages
- Add daily purchases bar chart (created vs paid) to landing stats
- Replace single purchase count with created/paid split in stats summary
- Add referrer tracking to purchases with hostname display in stats
- Add time display to purchase cards alongside date
- Pass user timezone to stats API for correct daily grouping
- Clamp referrer (500 chars) and subid (255 chars) to backend limits
- Persist contact value per-landing-slug in localStorage
- Fire buy_success analytics goal on successful delivery
- Export USER_TIMEZONE from format utils
- Add analytics/stats translations for fa.json and zh.json locales

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 09:17:52 +03:00
Fringg
a50bd39df2 fix: validate counterId/conversionId before script injection (XSS prevention) 2026-04-29 09:06:29 +03:00
Fringg
80059681da feat: Yandex Metrika CID tracking, offline conversions UI, sticky pay button
- Pass yandex_cid to all auth endpoints (telegram, email, OIDC, OAuth)
- Add OfflineConvGoal interface and offline_conv_* fields to AnalyticsCounters
- Add storeYandexCid API method for server-side CID persistence
- Add analytics fields to LandingConfig (view/click goals, sticky_pay_button)
- Add yandex_cid/referrer/subid to PurchaseRequest
- Add offline conversions UI block in admin AnalyticsTab
- Add cacheYandexCid, syncYandexCid, fireAnalyticsEvent to analytics hook
- Create yandexCid.ts utility (localStorage get/set helpers)
- Add sticky pay button with portal on mobile in QuickPurchase
- Fire view/click analytics goals on landing pages
- Persist contact value and referrer/subid in session/localStorage
- Add i18n keys for offlineConv and apiKey in all 4 locales
2026-04-29 08:59:19 +03:00
Fringg
6d3010b621 feat: multi-media attachments, linkify URLs, shared MessageMediaGrid
- Add media_items array support to ticket messages (types, API clients)
- Create shared MessageMediaGrid component with photo grid, fullscreen
  viewer, keyboard nav, video/document rendering
- Replace per-page AdminMessageMedia/MessageMedia with MessageMediaGrid
- Add linkifyText util (DOMPurify-sanitized) for auto-linking URLs
- Support multi-file upload (up to 10) in AdminTickets and Support pages
- Remove unused ticketsApi import from AdminUserDetail
2026-04-29 08:45:15 +03:00
Fringg
9b1e26d4ec fix: switch component — replace motion with CSS transition-transform 2026-04-29 08:34:37 +03:00
Fringg
8044b664c3 fix: restore cabinet_last_login in user detail (now shows real data) 2026-04-29 06:46:20 +03:00
Fringg
8fcdbbe53e fix: remove stale cabinet_last_login field from user detail 2026-04-29 06:42:25 +03:00
Fringg
bc37f31350 feat: subscription selector in VPN connection block for multi-tariff
- Show VPN connection block even when panelInfo not yet loaded
- Add subscription dropdown when user has multiple subscriptions
- Show spinner while loading, "no data" when panel returns not found
- Changing subscription in VPN block reloads panel info for that sub
2026-04-29 06:34:41 +03:00
Fringg
853e1c9c84 fix: user detail — separate request history sub selector, split mount effects
- Request history subscription selector no longer mutates shared
  activeSubscriptionId — uses independent requestHistorySubId state
- Request history reloads when subscription selector changes
- Split mount effect: loadPanelInfo in separate effect to avoid
  redundant loadUser calls when activeSubscriptionId changes
2026-04-29 06:22:38 +03:00
Fringg
e1d2f8cee4 feat: show VPN connection info and subscription request history on admin user detail
- Load panelInfo eagerly on page load (not just on subscription tab)
- Add VPN connection card to info tab: last/first connection, online status indicator, last node
- Rename "Last activity" to "Bot activity" to distinguish from VPN connection
- Show cabinet_last_login field that was never rendered
- Add collapsible subscription request history section in subscription tab with paginated table
- Add subscription request history API types and method
- Add i18n keys for all 4 locales (ru, en, zh, fa)
2026-04-29 06:11:12 +03:00
Egor
22aa8be212 Merge pull request #410 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.49.0
2026-04-24 17:12:30 +03:00
github-actions[bot]
83d7305276 chore(main): release 1.49.0 2026-04-24 14:12:14 +00:00
Egor
3f47bc8024 Merge pull request #409 from BEDOLAGA-DEV/dev
Dev
2026-04-24 17:11:14 +03:00
Fringg
5b1892ddbb fix: campaigns/partners filter 422 — limit=200 exceeds backend max (100) 2026-04-24 16:31:05 +03:00
Fringg
8e767443f0 fix: load filters independently — one API failure no longer blocks others
Promise.all was used for tariffs, promo groups, campaigns, and partners.
If any one endpoint failed (e.g., partners not configured), all four
setCampaigns/setPartners/etc calls were skipped. Now each loads independently.
2026-04-24 16:22:20 +03:00
Fringg
161f630fd8 fix: bulk actions — modal touch targets, deleteFromPanel reset, remove dupe spacer
- Modal close button: 28px → 44px touch target
- deleteFromPanel checkbox: 20px → 24px + 44px label row
- Confirm/cancel buttons: add min-h-[44px]
- Reset deleteFromPanel to true when modal reopens
- Remove duplicate bottom spacer (h-20)
2026-04-24 16:16:31 +03:00
Fringg
b01ffe3309 feat: add campaign/partner filters, delete_user action, and fix modal positioning in AdminBulkActions
Add campaign and partner filter dropdowns for user filtering, implement
delete_user bulk action with delete_from_panel checkbox, fix ActionModal
to use createPortal with viewport-fixed positioning and safe area insets.
2026-04-24 16:04:20 +03:00
Fringg
5cfbce0663 fix: regenerate FAQ editor keys on locale switch
- Locale switch now regenerates all stable keys so editors remount fresh
- Fixes same-length locale switch (e.g., ru 3 items → en 3 items) reusing wrong editors
- Move keyCounter increment out of functional updater for StrictMode purity
- Remove void locale — prop is now used for key regeneration
2026-04-24 15:25:53 +03:00
Fringg
a6850c8cbc fix: FAQ answer editor — stable keys, safe setContent, drop handler
- Use emitUpdate: false instead of fragile suppressUpdate ref
- Stable React keys for FAQ items — survive reorder/delete without editor desync
- Fix onDrop to check file type before preventDefault (non-media drops were swallowed)
2026-04-24 15:19:20 +03:00
Fringg
0adbfa50eb feat: FAQ answer editor — replace textarea with TipTap rich editor
- Full WYSIWYG editor for FAQ answers with toolbar (bold, italic, underline,
  strike, headings, lists, blockquote, highlight, link, media upload)
- Image/video upload via paste, drag-drop, and file picker
- Upload progress indicator and drag overlay
- Syncs with parent state on reorder and locale switch
2026-04-24 15:10:41 +03:00
Fringg
d6918ee438 fix: info page — slug collision guard, error resilience, overflow, loyalty responsive
- Guard extraPages against slugs colliding with built-in tab IDs
- Handle tabReplacements API failure gracefully (proceed with built-in content)
- Fix overflow: use overflow-x-auto on inner divs instead of fighting bento-card
- Loyalty stat cards: responsive font size + truncate for 320px screens
- Clamp negative "remaining to next tier" amount to zero
- Fix toggleFaq stale closure with functional updater
2026-04-24 15:07:11 +03:00
Fringg
656946952a feat: info pages — tab replacement, custom pages on /info, responsive fixes
- Add replaces_tab field to admin editor with conflict detection
- Show custom InfoPages as extra tabs on /info page
- Replace built-in tab content when replacement is configured
- Rich DOMPurify sanitizer for TipTap content (images, video, iframe)
- Fix query race: built-in queries wait for tab-replacements to load
- Horizontal scroll for tabs on mobile, 44px touch targets
- Responsive prose: scrollable tables, h-auto on img/video, light theme borders
- Loyalty tier names truncation, progress bar labels stack on mobile
2026-04-24 15:01:11 +03:00
Fringg
c16593aeee fix: mobile/responsive issues in FAQ and info pages
- FAQ builder: touch targets 36px → 44px (move up/down/delete buttons)
- Filter tabs: add flex-wrap to prevent overflow on narrow screens
- Accordion: add ResizeObserver for dynamic content height (images
  loading, viewport rotation won't clip content anymore)
- Accordion: use stable key (index+question) instead of filtered array
  index — search+toggle no longer opens wrong item
2026-04-24 14:10:28 +03:00
Fringg
1ee0f18343 feat: FAQ pages — Q&A builder in admin, accordion view for users
Admin editor:
- page_type selector: "Страница" / "FAQ" radio buttons
- When FAQ: FaqBuilder component replaces TipTap editor
  - Question input + answer textarea per Q&A item
  - Add/remove items, up/down reorder buttons
  - Per-locale Q&A (stored as JSON array in content JSONB)
- "Создать FAQ" button in list alongside "Создать страницу"
- Filter tabs: Все / Страницы / FAQ
- Page type badge on each row (accent for pages, amber for FAQ)

Public view (InfoPageView):
- Auto-detects page_type='faq' and renders FaqView component
- Accordion with smooth height animation (300ms ease-in-out)
- Search filter appears when >3 questions
- DOMPurify sanitization on FAQ answers
- Single-item expand (click to open/close)

i18n: full FAQ keys for all 4 locales (questions, answers,
search, counts, empty states, builder labels)
2026-04-24 14:02:03 +03:00
Fringg
596f638cdd fix: prose content overflow on mobile — add overflow-x-auto 2026-04-24 13:51:08 +03:00
Fringg
3ef54adb3e fix: info page editor — locale switch no longer resets user edits
Split the form population effect into two:
1. Form fields (slug, icon, active, titles, contents) — populated
   once when pageData loads, never re-run on locale switch
2. Editor content — set once when editor instance is ready

Previously activeLocale was in the deps array, causing every tab
switch to overwrite all in-memory edits with original server data.
2026-04-24 08:22:16 +03:00
Fringg
7d6d0ba344 feat: information pages — admin editor with TipTap, public viewer
Admin panel:
- New section "Информационные страницы" in admin nav
- Admin list: slug, title, active toggle, edit/delete, sort order
- Admin editor: full TipTap (bold, italic, headings, lists, links,
  image/video upload, alignment, highlight, code blocks)
  with locale tabs (RU/EN/ZH/FA) for title and content
- Create/edit via URL params, slug auto-generation

Public:
- /info/:slug route with DOMPurify sanitized content
- Locale fallback, Telegram safe area, loading skeleton, 404

i18n: all 4 locales
2026-04-24 08:11:20 +03:00
Fringg
d43638b34e fix: floating action bar covering pagination — add bottom spacer when selection active 2026-04-24 07:36:33 +03:00
Fringg
cb148d181a fix: persist checkbox selection across page changes and filter switches
Selection (both user and subscription checkboxes) now persists when:
- Switching pages (prev/next)
- Changing filters (status, tariff, promo group, trial)
- Changing per-page limit
- Searching
- Refreshing data

Selection is only cleared after a successful bulk action execution
(modal close with result).
2026-04-24 07:29:02 +03:00
Fringg
e2706c7c26 fix: select-all subscriptions + per-page selector
- Fix allVisibleSubscriptionIds: include ALL users' filtered subs
  (was only users with >1 subs — single-sub users were excluded)
- Add per-page selector (25/50/100/200) in pagination bar
- Make limit a state variable instead of constant
- perPage i18n keys (ru + en)
2026-04-24 07:23:58 +03:00
Fringg
98871af656 fix: multi-tariff filter now works server-side + trial-only checkbox
- Send comma-separated tariff_ids to backend (was only single ID)
  — server now filters with IN() operator, pagination correct
- Remove client-side tariff filtering (server handles it)
- Add "Только триал" checkbox filter: amber checkbox, filters users
  with trial subscriptions client-side
- Remove "trial" from status dropdown (was not working via
  subscription_status server filter)
- i18n: trialOnly key (ru + en)
2026-04-24 07:16:53 +03:00
Fringg
efca40d9c8 fix: multi-tariff filter shows all users when >1 tariffs selected
Server only supports single tariff_id filter. When multiple tariffs
are selected, apply client-side filtering to hide users who have no
subscriptions matching any of the selected tariffs.
2026-04-24 07:08:40 +03:00
Fringg
c32bcfeb9e fix: floating action bar hidden behind mobile bottom nav — raise z-index + bottom padding 2026-04-24 07:04:44 +03:00
Fringg
eeda567622 feat: second header checkbox for bulk subscription selection
Add green checkbox in table header next to the user checkbox for
mass-selecting all visible subscriptions. Shows filled/partial/empty
states matching user checkbox pattern. Only visible in multi-tariff
mode. Wider select column (56px) to fit both checkboxes.
2026-04-24 07:03:53 +03:00
Fringg
3cb15177cc fix: show sub-rows for single-subscription users + fix floating bar position
- Auto-expand ALL users with subscriptions (was only > 1), so users
  with single subscription also show their sub-row for selection
- FloatingActionBar: render via createPortal to document.body to
  ensure fixed positioning works correctly regardless of parent
  overflow/transform contexts (was trapped inside scrollable area)
2026-04-24 06:59:55 +03:00