Commit Graph

1832 Commits

Author SHA1 Message Date
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
Dmitry Lunin
d75440bfe4 fix: wrap server display names with Twemoji for cross-platform emoji rendering 2026-04-21 23:03:20 +03:00
Egor
bfa5f7ae7f Merge pull request #401 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.47.0
2026-04-18 04:00:36 +03:00
github-actions[bot]
2fcec89bbf chore(main): release 1.47.0 2026-04-18 00:58:29 +00:00
Egor
52c02d5e39 Merge pull request #400 from BEDOLAGA-DEV/dev
Dev
2026-04-18 03:58:03 +03:00
Fringg
996840f627 fix: change aurapay icon to pink gradient to avoid kassa_ai color collision 2026-04-18 00:12:15 +03:00
Fringg
48827e430d feat: add AuraPay payment provider to cabinet frontend
- Payment method label and icon (violet gradient, AP)
- Admin settings tree entry for AURAPAY category
- Locale strings and descriptions for ru, en, zh, fa
2026-04-18 00:05:56 +03:00
Egor
73bea1a28a Merge pull request #399 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.46.0
2026-04-16 06:11:25 +03:00
github-actions[bot]
7d819c6826 chore(main): release 1.46.0 2026-04-16 03:10:37 +00:00
Egor
2fd0961c03 Merge pull request #398 from BEDOLAGA-DEV/dev
Dev
2026-04-16 06:10:11 +03:00
Fringg
4eed0f358e fix: differentiate rollypay icon from riopay (teal gradient, RY text) 2026-04-16 05:58:58 +03:00
Fringg
770a5803d6 feat: add RollyPay payment provider to cabinet frontend
- Payment method label and icon (green gradient, RP)
- Admin settings tree entry for ROLLYPAY category
- Locale strings and descriptions for ru, en, zh, fa
2026-04-16 05:55:21 +03:00
Fringg
5cbf29a1e8 fix: add paypear payment method description to ru/en locales 2026-04-16 05:38:34 +03:00
Fringg
31ac511a09 feat: add PayPear payment provider to cabinet frontend
- Payment method label and icon (amber gradient)
- Admin settings tree entry for PAYPEAR category
- Locale strings for ru, en, zh, fa
2026-04-16 05:26:09 +03:00
github-actions[bot]
e0ed311614 chore(main): release 1.45.1 (#396)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-15 14:16:04 +03:00
Egor
e6cf3af846 fix: period discounts clearing, SBP default, happ cryptolink flow
* Make SBP default and first top-up option (#389)

* fix(connection): happ cryptolink flow + ui fixes (#385)

* fix(connection): respect happ_cryptolink mode

- read connect_mode from connection-link endpoint
- auto-redirect to happ cryptolink flow when mode is HAPP_CRYPTOLINK
- keep installation guide behavior for other modes

* docs(readme): fix source build step 2

- use compose service name for build/create commands
- copy static files from created compose container
- remove compose container via docker compose rm

* fix(connection): handle mode and ws path

- treat any non-guide connect mode as direct happ redirect
- wait for connection-link response before rendering installation guide
- build websocket URL from VITE_API_URL (supports /api and absolute URLs)

* docs(readme): fix docker cp static path

- copy /usr/share/nginx/html contents via html/.
- prevent nested /srv/cabinet/html deployment and 404 on root

* fix(connection): keep guide, use happ links

- restore guide page behavior for /connection (no auto redirect)
- use happ cryptolink URL in /connection/qr when happ crypt mode is active
- replace subscription page connection URL with happ cryptolink from connection-link API

* fix(connection): avoid wrong redirect flow

- force happ scheme deeplink in HAPP_CRYPTOLINK mode for guide connect buttons
- use cabinet redirect page only inside Telegram Mini App
- open deeplink directly in regular browsers

* fix(connection): enforce happ cryptolink

- prioritize backend crypt deeplink fields in HAPP_CRYPTOLINK mode
- fallback to local crypt4/crypt3 generation from subscription URL when backend returns plain happ://sub...
- apply same resolution for guide open action, qr page source and subscription page link display/copy

* fix(subscription): truncate long connect link

- render connection URL in a single line with ellipsis on /subscriptions
- preserve full URL in tooltip for easier manual copy
- keep copy button behavior unchanged

* fix(connection): build cryptolink from happ sub

- allow cryptolink fallback generation from happ://sub... URLs in addition to http(s)
- prevent plain happ://sub links from leaking into UI in HAPP_CRYPTOLINK mode

* fix: allow saving 0% period discount in promo groups

Changed condition from percent > 0 to percent >= 0 so that
admins can explicitly set 0% discount for a period. Previously
0% entries were silently dropped and not sent to the backend.

* fix: always send period_discounts in promo group updates

When all period discounts were removed, the frontend sent undefined
(field absent from JSON), so the backend never cleared them.
Now always sends the field - empty object {} to clear, or populated
object to update.

---------

Co-authored-by: zavul0nn <34007368+zavul0nn@users.noreply.github.com>
Co-authored-by: Dxnil <62987903+D4nilKO@users.noreply.github.com>
2026-04-15 14:13:24 +03:00
Egor
ac89343cc1 Dev (#394)
* Make SBP default and first top-up option (#389)

* fix(connection): happ cryptolink flow + ui fixes (#385)

* fix(connection): respect happ_cryptolink mode

- read connect_mode from connection-link endpoint
- auto-redirect to happ cryptolink flow when mode is HAPP_CRYPTOLINK
- keep installation guide behavior for other modes

* docs(readme): fix source build step 2

- use compose service name for build/create commands
- copy static files from created compose container
- remove compose container via docker compose rm

* fix(connection): handle mode and ws path

- treat any non-guide connect mode as direct happ redirect
- wait for connection-link response before rendering installation guide
- build websocket URL from VITE_API_URL (supports /api and absolute URLs)

* docs(readme): fix docker cp static path

- copy /usr/share/nginx/html contents via html/.
- prevent nested /srv/cabinet/html deployment and 404 on root

* fix(connection): keep guide, use happ links

- restore guide page behavior for /connection (no auto redirect)
- use happ cryptolink URL in /connection/qr when happ crypt mode is active
- replace subscription page connection URL with happ cryptolink from connection-link API

* fix(connection): avoid wrong redirect flow

- force happ scheme deeplink in HAPP_CRYPTOLINK mode for guide connect buttons
- use cabinet redirect page only inside Telegram Mini App
- open deeplink directly in regular browsers

* fix(connection): enforce happ cryptolink

- prioritize backend crypt deeplink fields in HAPP_CRYPTOLINK mode
- fallback to local crypt4/crypt3 generation from subscription URL when backend returns plain happ://sub...
- apply same resolution for guide open action, qr page source and subscription page link display/copy

* fix(subscription): truncate long connect link

- render connection URL in a single line with ellipsis on /subscriptions
- preserve full URL in tooltip for easier manual copy
- keep copy button behavior unchanged

* fix(connection): build cryptolink from happ sub

- allow cryptolink fallback generation from happ://sub... URLs in addition to http(s)
- prevent plain happ://sub links from leaking into UI in HAPP_CRYPTOLINK mode

* fix: allow saving 0% period discount in promo groups

Changed condition from percent > 0 to percent >= 0 so that
admins can explicitly set 0% discount for a period. Previously
0% entries were silently dropped and not sent to the backend.

* fix: always send period_discounts in promo group updates

When all period discounts were removed, the frontend sent undefined
(field absent from JSON), so the backend never cleared them.
Now always sends the field - empty object {} to clear, or populated
object to update.

---------

Co-authored-by: zavul0nn <34007368+zavul0nn@users.noreply.github.com>
Co-authored-by: Dxnil <62987903+D4nilKO@users.noreply.github.com>
2026-04-15 14:04:39 +03:00
Fringg
d15c2408df fix: always send period_discounts in promo group updates
When all period discounts were removed, the frontend sent undefined
(field absent from JSON), so the backend never cleared them.
Now always sends the field - empty object {} to clear, or populated
object to update.
2026-04-15 04:13:53 +03:00
Fringg
3a865a472b fix: allow saving 0% period discount in promo groups
Changed condition from percent > 0 to percent >= 0 so that
admins can explicitly set 0% discount for a period. Previously
0% entries were silently dropped and not sent to the backend.
2026-04-15 03:40:09 +03:00
Dxnil
c80e1aff75 fix(connection): happ cryptolink flow + ui fixes (#385)
* fix(connection): respect happ_cryptolink mode

- read connect_mode from connection-link endpoint
- auto-redirect to happ cryptolink flow when mode is HAPP_CRYPTOLINK
- keep installation guide behavior for other modes

* docs(readme): fix source build step 2

- use compose service name for build/create commands
- copy static files from created compose container
- remove compose container via docker compose rm

* fix(connection): handle mode and ws path

- treat any non-guide connect mode as direct happ redirect
- wait for connection-link response before rendering installation guide
- build websocket URL from VITE_API_URL (supports /api and absolute URLs)

* docs(readme): fix docker cp static path

- copy /usr/share/nginx/html contents via html/.
- prevent nested /srv/cabinet/html deployment and 404 on root

* fix(connection): keep guide, use happ links

- restore guide page behavior for /connection (no auto redirect)
- use happ cryptolink URL in /connection/qr when happ crypt mode is active
- replace subscription page connection URL with happ cryptolink from connection-link API

* fix(connection): avoid wrong redirect flow

- force happ scheme deeplink in HAPP_CRYPTOLINK mode for guide connect buttons
- use cabinet redirect page only inside Telegram Mini App
- open deeplink directly in regular browsers

* fix(connection): enforce happ cryptolink

- prioritize backend crypt deeplink fields in HAPP_CRYPTOLINK mode
- fallback to local crypt4/crypt3 generation from subscription URL when backend returns plain happ://sub...
- apply same resolution for guide open action, qr page source and subscription page link display/copy

* fix(subscription): truncate long connect link

- render connection URL in a single line with ellipsis on /subscriptions
- preserve full URL in tooltip for easier manual copy
- keep copy button behavior unchanged

* fix(connection): build cryptolink from happ sub

- allow cryptolink fallback generation from happ://sub... URLs in addition to http(s)
- prevent plain happ://sub links from leaking into UI in HAPP_CRYPTOLINK mode
2026-04-15 03:29:54 +03:00
zavul0nn
32dba93f1a Make SBP default and first top-up option (#389) 2026-04-15 03:27:47 +03:00
Egor
c331e5db88 Merge pull request #393 from BEDOLAGA-DEV/main
w
2026-04-15 03:25:20 +03:00
c0mrade
1f833dbdd5 Merge pull request #391 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.45.0
2026-04-13 19:47:47 +03:00
github-actions[bot]
06a83a01ae chore(main): release 1.45.0 2026-04-13 16:37:55 +00:00
c0mrade
dc20d3e087 Merge pull request #390 from BEDOLAGA-DEV/dev
Bugfixes: polyfill, UI fixes, campaign tracking, menu editor
2026-04-13 19:37:21 +03:00
c0mrade
30d8d28475 fix: show API error details in menu editor save + allow tg:// URLs
Save mutation was showing generic error instead of backend validation
detail, making it impossible to diagnose 422 errors. Also added tg://
to frontend URL validation for Telegram deep link support.
2026-04-13 17:07:29 +03:00
c0mrade
a46c89e45e feat: send campaign_slug during standalone email registration
Frontend now reads campaign slug from localStorage and includes it
in the registration API call, ensuring campaign attribution works
even if email verification happens in a different browser.
2026-04-13 14:43:39 +03:00
c0mrade
3d0fc76ecd fix: subscription status badge overflow + inline password validation
- Status badge (e.g. 'ПРИОСТАНОВЛЕНА (НЕДОСТАТОЧНО СРЕДСТВ)') now
  constrained with max-w-[55%] to prevent overlapping tariff name
- Password too short error shown inline under password field during
  registration instead of at the top of the page (invisible on mobile)
2026-04-13 14:43:29 +03:00