Commit Graph

1709 Commits

Author SHA1 Message Date
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
Fringg
c726d3d74e feat: bulk delete subscription + fix sub-rows showing for filtered single subs
- Add "Удалить подписки" action with red trash icon, destructive
  warning dialog (red border, irreversible action notice)
- Fix canExpand: show sub-rows when isMultiTariff && subs > 0
  (was > 1, hiding single filtered subscription results)
- i18n: deleteSubscription action + warning/hint (ru + en)
2026-04-24 06:51:21 +03:00
Fringg
5969c74f92 feat: devices in subscription rows, set_devices action, table columns
- Remove "Days" column from main table (each subscription shows own)
- Tariff column shows ALL subscription tariffs as comma-separated list
- Subscription sub-rows show device count with phone icon
- New bulk action "Изменить устройства" (set_devices) with input 1-50
- Update UserListItemSubscription type with device_limit field
- i18n: setDevices + deviceLimit keys (ru + en)
2026-04-24 06:36:04 +03:00
Fringg
f13b7239a5 feat: multi-select tariff filter, select-all subscriptions, auto-expand
1. Tariff filter: replace single-select dropdown with MultiSelectDropdown
   component — checkboxes for each tariff, "Select all" / "Deselect all"
   controls, shows selected names or count in button label
2. Client-side subscription filtering: when tariffs selected in filter,
   only show matching subscriptions in expanded sub-rows
3. "Select all subscriptions" button in FloatingActionBar — toggles all
   visible subscription checkboxes and auto-expands relevant rows
4. Auto-expand: all user rows with multiple subscriptions are expanded
   by default when data loads (no need to click chevron)
5. i18n: new keys for tariff multi-select and subscription select-all
2026-04-24 06:20:43 +03:00
Fringg
9673f26469 fix: make subscription checkboxes same size as user checkboxes (h-5 w-5) 2026-04-24 06:11:43 +03:00
Fringg
3801c3626a fix: expand chevron invisible on accent background
ChevronExpandIcon used text-dark-400 (gray) on the accent gradient
circle (green) — completely invisible. Changed to text-white.
2026-04-24 06:08:57 +03:00
Fringg
0844144e23 fix: make checkboxes visible on dark theme in bulk actions
- Increase user checkbox size: h-4.5 → h-5 w-5 with rounded-md border-2
- Increase subscription checkbox: h-3.5 → h-4.5 with rounded-md border-2
- Brighter unselected border: dark-600 → dark-500 with lighter bg
- Hover effect: accent-500/50 border glow on hover
- Selected glow: accent shadow ring for clear visual feedback
- Smooth transition-all duration-150 for all state changes
2026-04-24 06:02:11 +03:00
Fringg
78b41dc338 feat: multi-tariff bulk actions UI — subscription-level selection
- Detect multi-tariff mode when users have multiple subscriptions
- Expandable user rows with chevron: click to show subscription sub-rows
- Each subscription sub-row shows: tariff name, status badge, days
  remaining (color-coded green/amber/red), traffic progress bar
- Independent subscription checkboxes for subscription-level actions
- FloatingActionBar shows dual counters: users (accent) + subscriptions
  (green), actions grouped by target type with disabled state
- Subscription-level actions send subscription_ids, user-level send
  user_ids to the backend
- Backward compatible: single-tariff mode unchanged (no chevrons,
  no sub-rows, user-only selection)
- i18n: subscriptionsSelected, usersSelected, expand/collapse,
  daysUnit, trafficOf, trafficGbUnit (ru + en)
2026-04-24 05:49:38 +03:00
Fringg
161fde4301 fix: bulk actions — add tariff info to user list, fix tariff column display
- Update UserListItem type to include tariff_id, tariff_name,
  traffic_used_gb, traffic_limit_gb, device_limit, days_remaining
  from the backend (now returned in user list API)
- Fix tariff column: was showing subscription_status, now shows
  actual tariff_name from the API response
2026-04-24 05:28:08 +03:00
Fringg
8dd5e4985f fix: bulk progress log shows generic error instead of backend message
The live ProgressView log used entry.error (never sent by backend)
instead of entry.message, falling back to a generic i18n string.
Now checks entry.message first to display the actual error from
the backend (e.g. "No subscription found").
2026-04-24 05:15:13 +03:00
Fringg
fc8170fa1f fix: align frontend bulk action types with backend API contract
- Fix BulkActionType enum: 'extend' → 'extend_subscription',
  'cancel' → 'cancel_subscription', 'activate' → 'activate_subscription'
- Fix BulkActionParams: 'balance_kopeks' → 'amount_kopeks' to match backend
- Fix SSE complete handler: build errors from progress log (backend
  complete event has no errors array)
- Add skipped_count to all BulkActionResult construction paths
- Add dry_run support to BulkActionRequest type
- Transform backend results[] to frontend errors[] in non-streaming path
- Remove unused errors variable in streaming fallback path
2026-04-24 04:52:30 +03:00
Fringg
312e0b4927 feat: bulk actions — live progress, grant subscription, error details
- Real-time progress: SSE streaming with animated progress bar,
  live success/error counters, scrollable log of last 10 results
  with auto-scroll, percentage display
- New action "Выдать подписку": tariff selector + days input,
  warning about users with existing subscriptions being skipped
- Error details: collapsible section with per-user error list,
  colored summary line (green successes / red errors)
- Fix: modal cannot be closed during loading (backdrop + Escape)
- Fix: row checkbox aria-labels now user-specific
- i18n: full progress/grant/error translations (ru + en)
2026-04-24 04:40:53 +03:00
Fringg
ebe9d9be48 fix: bulk actions frontend — selectedUserIds mapping, debounce cleanup
- Fix selectedUserIds: was mapping row keys as array indices instead
  of using them directly as user IDs (getRowId returns String(user.id))
- Add useEffect cleanup for search debounce timer on unmount
2026-04-24 04:24:33 +03:00
Fringg
1772d9632e feat: admin bulk actions page with TanStack Table
Full-featured admin page for mass operations on users:

- TanStack Table with checkbox selection (select all / individual)
- Server-side pagination, search, and filters (status, tariff, promo group)
- Columns: user, subscription status, tariff, balance, days left, promo group
- Floating glass-effect action bar with 7 bulk operations:
  extend subscription, deactivate, activate, change tariff,
  add traffic, add balance, assign promo group
- Action modal dialogs with input fields, loading state, result summary
- Responsive design for desktop, mobile, and Telegram Mini App
- Full i18n support (ru, en)
- Dark theme with accent highlights and status color badges
2026-04-24 04:15:28 +03:00
Egor
ae8504d6c3 Merge pull request #407 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.48.0
2026-04-23 05:21:06 +03:00
github-actions[bot]
0d54e4d80b chore(main): release 1.48.0 2026-04-23 02:20:36 +00:00
Egor
d0d6bbc6ad Merge pull request #406 from BEDOLAGA-DEV/dev
Dev
2026-04-23 05:20:09 +03:00
Fringg
33f32648f0 feat: improve squad management UX — rename, swap icons, color gift button
1. Rename "Управление серверами" → "Управление сквадами" across all
   4 locales (ru, en, zh, fa) — title, subtitle, nav, subscription
   options. The page manages RemnaWave squads, not individual servers.

2. Swap toggle button semantics — the button now shows the ACTION
   that will happen on click, not the current state:
   - Active squad: red X icon (click to deactivate)
   - Inactive squad: green checkmark (click to activate)

3. Gift/trial button: amber/orange when functional (clearly clickable),
   gray when disabled. Previously always gray, making it look inactive
   even when it could be clicked.
2026-04-23 05:00:36 +03:00
Fringg
2d6815a88e fix: landing page currency symbol not changing with locale
formatPrice() was hardcoded to ru-RU locale and RUB currency.
Now it reads the current language from i18next and maps it to
the appropriate currency (ru→RUB, en→USD, zh→CNY, fa→IRR).

All consumers (QuickPurchase landing, GiftSubscription, admin)
automatically get locale-aware currency formatting without
any component-level changes.
2026-04-23 04:55:36 +03:00
Fringg
1d5ce2d4ea fix: complete is_limited status handling across all views
- SubscriptionListCard: show traffic progress bar for limited subs
  in multi-tariff list (was hidden because isActive excluded limited)
- SubscriptionListCard: amber border/background for limited status
  cards (was using default neutral style, inconsistent with rest of UI)
- Subscription page: hide delete button for limited subs in
  multi-tariff mode (limited subs still have valid days remaining)
- SubscriptionPurchase: allow tariff switch for limited subs
  (was blocked by is_active-only gate in canSwitch formula)
- AdminUserDetail: include limited status in "already purchased"
  tariff filter to prevent duplicate subscription creation
2026-04-23 04:04:11 +03:00
Fringg
f68b46699c fix: limited (traffic exhausted) subscription shows as expired
- Dashboard card: change date label from "Истекла" to "Активна до"
  for limited subscriptions (traffic exhausted but time remaining)
- Dashboard button: change text from "Трафик исчерпан" (dead-end) to
  "Докупить трафик" (actionable) for limited status
- Subscription page: CountdownTimer shows remaining time for limited
  subs instead of "Истекла" (was passing is_active=false)
- PurchaseCTAButton: don't treat limited as expired — limited subs
  still have time, should show extend CTA not "buy new subscription"
2026-04-23 03:56:07 +03:00
Fringg
e6403eb7d0 fix: gift page shows only 1 tariff when tariffs have different periods
The gift page filtered tariffs by selected period, hiding tariffs
whose single period didn't match. When each tariff has a unique
period (30d, 60d, 180d, 360d), only the first tariff was visible.

- Remove period-first filtering (visibleTariffs/allPeriods)
- Show all tariffs directly from config.tariffs
- Auto-select the chosen tariff's period when switching tariffs
- Show tariff cards when more than 1 tariff exists
2026-04-23 03:29:00 +03:00
Egor
f7587b2524 Merge pull request #405 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.47.1
2026-04-22 06:18:13 +03:00
github-actions[bot]
e371493aab chore(main): release 1.47.1 2026-04-22 03:09:06 +00:00
Egor
88c8dbcb31 Merge pull request #404 from BEDOLAGA-DEV/dev
Dev
2026-04-22 06:08:34 +03:00
Egor
848caba6be Merge pull request #402 from BlackRaincoat/fix/twemoji-server-names
Fix/twemoji server names
2026-04-22 06:07:25 +03:00
Egor
4a9a4948b4 Merge pull request #403 from BEDOLAGA-DEV/main
w
2026-04-22 06:06:40 +03:00