Commit Graph

1858 Commits

Author SHA1 Message Date
c0mrade
fe75fa45f0 feat: delete expired subscriptions with confirmation dialog
- API: deleteSubscription() calls DELETE /subscriptions/:id
- Subscription detail: "Удалить подписку" button for expired subs
  in multi-tariff mode
- Radix Dialog confirmation with warning text, cancel/confirm buttons
- Navigates to /subscriptions after successful deletion
2026-03-24 15:31:10 +03:00
c0mrade
2921d8cae6 feat: wheel subscription picker for multi-tariff mode
- API: spin() accepts subscriptionId, WheelConfig has eligible_subscriptions
- Auto-select subscription when only one eligible
- Show subscription picker when multiple eligible (days payment)
- Disable spin button until subscription selected (when >1 eligible)
- Daily tariffs excluded from eligible list
2026-03-24 14:41:20 +03:00
c0mrade
31d0953c23 feat: add WebBackButton to all sub-pages, widen renew page layout
- New WebBackButton component: visible on web, hidden in Telegram
  (native back button handles navigation there)
- Added to: Subscription detail, SubscriptionPurchase, RenewSubscription
- RenewSubscription: removed max-w-lg, grid layout for period cards
2026-03-24 14:01:55 +03:00
c0mrade
f1cb9e5c66 redesign: subscriptions list page — full width, grid layout, accent add button
- Remove max-w-lg constraint to match dashboard width
- Grid layout: 2 columns on desktop, 1 on mobile
- Move "Новый тариф" button to header row as accent-styled button
- Larger empty state with more breathing room
2026-03-24 13:31:25 +03:00
c0mrade
348d654892 fix: send subscription_id as query param in ALL POST/PATCH endpoints
All backend endpoints accept subscription_id via Query(...) parameter,
but frontend was sending it in the request body via bodyWithSubId helper.
This caused multi-tariff operations (pause, autopay, renew, traffic,
devices, servers, tariff switch) to silently fail — backend couldn't
find subscription_id in query params and fell back to first subscription.

Changed bodyWithSubId to return [body, config] tuple with subscription_id
in params, spread into axios calls as separate arguments.
2026-03-24 12:45:47 +03:00
c0mrade
871b4769aa feat: show autopay/auto-charge status on subscription cards, invalidate list on toggle
- SubscriptionListCard: always show autopay status (green check / red cross)
  for regular tariffs, show auto-charge status for daily tariffs
- Hide autopay for trial subscriptions
- Autopay mutation: invalidate subscriptions-list for instant UI update
- Types: added is_daily, is_daily_paused to SubscriptionListItem
2026-03-24 12:28:02 +03:00
c0mrade
b0421b94a6 fix: send subscription_id as query param in autopay PATCH, not in body 2026-03-24 12:05:48 +03:00
c0mrade
6a53221cc1 fix: hide renewal button for daily tariffs in multi-tariff mode, fix hint text
- Daily tariffs renew automatically — no manual renewal CTA needed
- Show "Продление подписки" hint in multi-tariff instead of "Продление и смена тарифа"
2026-03-24 11:10:30 +03:00
c0mrade
10824b7322 fix: show missing balance amount on renew page, no tariff switch in multi-tariff
- RenewSubscription: display actual missing amount instead of {{missing}} placeholder
- SubscriptionPurchase: suppress "switch tariff" title in multi-tariff mode
  (only renewal exists, no tariff switching)
2026-03-24 10:58:37 +03:00
c0mrade
82eb03dec9 feat: separate renewal and purchase flows in multi-tariff mode
Renewal flow (per-subscription):
- New /subscriptions/:id/renew page showing only period options for
  the specific tariff with balance display and renew button
- PurchaseCTAButton links to /renew in multi-tariff mode

Purchase flow (new tariffs only):
- Hide already purchased tariffs (is_purchased flag from backend)
- Fallback UI when all tariffs are owned
- Types: added is_purchased, all_tariffs_purchased fields
2026-03-24 10:47:49 +03:00
c0mrade
a709ddbec2 chore: remove unused reactjs-tiptap-editor dependency
This package was not imported anywhere in the codebase but pulled in
@excalidraw/excalidraw and old @radix-ui packages that caused peer
dependency warnings on every npm install (React 19 vs React 16-18).
Tiptap is used directly via @tiptap/* packages.
2026-03-23 21:58:31 +03:00
c0mrade
9d3fb37d60 fix: remove duplicate back buttons, improve multi-subscription UX
- Remove custom back buttons from Subscription detail and SubscriptionPurchase
  pages — native Telegram mini-app back button already handles navigation
- SubscriptionListCard: distinct trial badge with star icon and amber styling,
  trial cards get amber border/background for visual differentiation
- SubscriptionPurchase: change "Купить тариф" to "Новый тариф" when adding
  a new tariff in multi-subscription mode
- Subscription detail: show tariff name as title in multi-tariff mode
2026-03-23 21:38:04 +03:00
c0mrade
376e1bb56d feat: enhance subscription list UX with progress bars, status badges, and glass theme
- SubscriptionListCard: replace status dot with localized status badge,
  add traffic progress bar with color coding, use locale-aware date format
- Subscriptions page: apply glass theme colors, improve empty state styling,
  add SVG plus icon for buy button, skeleton loader with glass theme
- Subscription detail: invalidate subscriptions-list cache on mutations
2026-03-23 18:57:05 +03:00
c0mrade
f4de6d8ad8 fix: multi-subscription UI audit fixes and cache invalidation improvements
- Fix AdminUserDetail multi-subscription display with useMemo optimization
- Update Dashboard subscription cards and purchase entry points
- Fix WebSocket notification handlers for multi-subscription context
- Update SubscriptionPurchase cache invalidation for multi-tariff mode
- Fix Subscriptions list page and navigation patterns
- Update App routing, DeepLinkRedirect, and CommandPalette for multi-sub
- Add SubscriptionListCard component
- Fix TopUpResult and PromoOffersSection navigation
2026-03-23 18:57:05 +03:00
c0mrade
258bfd7654 fix: remove unused multiSubCount variable 2026-03-23 18:57:05 +03:00
c0mrade
09f467bfb3 feat: show per-subscription mini-cards on Dashboard with tariff name, traffic, devices, date 2026-03-23 18:57:05 +03:00
c0mrade
865a78b801 fix: hide legacy subscription card on Dashboard in multi-tariff mode 2026-03-23 18:57:05 +03:00
c0mrade
bcbfa4191e feat: multi-tariff purchase UX - disable switch, show Buy for new tariffs, correct page title 2026-03-23 18:57:05 +03:00
c0mrade
a0c21a11aa fix: navigation links point to /subscriptions (list page) instead of legacy /subscription 2026-03-23 18:57:05 +03:00
c0mrade
f0d520dbaa fix: show subscriptions link on dashboard even with single subscription in multi-tariff mode 2026-03-23 18:57:05 +03:00
c0mrade
44d6069294 fix: correct glass theme and haptic API usage in Subscriptions page 2026-03-23 18:57:05 +03:00
c0mrade
820ba46cc4 feat: multi-subscription frontend support
- Add SubscriptionListItem and SubscriptionsListResponse types
- Add getSubscriptions/getSubscriptionById API methods
- Add optional subscriptionId parameter to all 30+ API methods
- Create /subscriptions page with subscription list cards
- Add /subscription/:subscriptionId route for per-subscription management
- Dashboard: show multi-tariff navigation block when user has 2+ subscriptions
- Subscription page: read subscriptionId from URL params, pass to all queries
- SubscriptionPurchase: accept subscriptionId from query params
- SubscriptionCardExpired: pass subscription.id to API calls
- Full backward compatibility: without subscriptionId, works as before
2026-03-23 18:57:05 +03:00
Fringg
84bded7974 fix: transliterate Cyrillic to Latin in news slug generation 2026-03-23 18:21:24 +03:00
Egor
8299fc15a7 Merge pull request #352 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.42.0
2026-03-23 16:57:47 +03:00
github-actions[bot]
846ea6212d chore(main): release 1.42.0 2026-03-23 13:57:19 +00:00
Egor
e86de809ae Merge pull request #351 from BEDOLAGA-DEV/dev
Dev
2026-03-23 16:56:44 +03:00
Fringg
be7219ec06 feat: add delete buttons for categories and tags in combobox dropdown
- Add onDelete prop to ColoredItemCombobox with X button per item
- Wire up deleteCategory/deleteTag API calls in AdminNewsCreate
- Auto-clear selection if the deleted item was selected
- Spinner on delete, haptic feedback, i18n aria-label
2026-03-23 15:48:27 +03:00
Fringg
13d27a5929 fix: tag color bug, FormData interceptor, falsy id check
- Fix tag using category_color instead of its own color when editing
- Add FormData auto-detection interceptor in client.ts (root cause of 422)
- Remove redundant Content-Type overrides from all 5 upload endpoints
- Fix falsy id check (id: 0 treated as null) with strict comparison
- Await invalidateQueries to prevent stale dropdown data
2026-03-23 15:36:22 +03:00
Fringg
4bcae6ce11 fix: add multipart/form-data header to news media upload request 2026-03-23 15:31:52 +03:00
Fringg
2ae01c95ae feat: add category/tag management UI with ColoredItemCombobox
- ColoredItemCombobox component with search, color swatches, inline creation
- Replace text inputs with combobox dropdowns for category and tag selection
- API methods for categories/tags CRUD
- TypeScript types for NewsCategory, NewsTag
- i18n keys for combobox (ru, en)
2026-03-23 15:30:02 +03:00
Fringg
59d8b66884 fix: disable duplicate link/underline extensions from StarterKit 2026-03-23 15:04:48 +03:00
Fringg
b7ab2cff55 fix: news section — remove duplicate title, add newspaper icon, hide views from users, fix cache invalidation 2026-03-23 15:00:11 +03:00
Fringg
de5414f42e fix: remove duplicate news title and replace N icon with newspaper SVG 2026-03-23 14:52:17 +03:00
Fringg
5c0eb129f4 fix: register DOMPurify hooks once, abort featured upload, fix double drop
- Register DOMPurify hooks at module init (not per sanitizeHtml call)
- Always set iframe allow attribute (not conditional on existing)
- Add AbortController to featured image upload for unmount cleanup
- Check defaultPrevented in React onDrop to prevent double upload with TipTap
- Remove explicit Content-Type header on upload (axios auto-sets boundary)
2026-03-23 12:43:47 +03:00
Fringg
f788f1034c fix: isolated DOMPurify instance and correct video controls attribute
- Use DOMPurify(window) to avoid global hook pollution
- Fix controls default from boolean to empty string (HTML attribute semantics)
- Remove redundant non-null assertion on featured_image_url
2026-03-23 12:32:04 +03:00
Fringg
25f3602aea fix: video not rendering — add TipTap Video extension, allow HTTP src
TipTap didn't recognize <video> tags without a custom node extension,
serializing them as escaped text. Also revert video src to allow HTTP
since request.base_url returns http:// behind reverse proxy.
2026-03-23 12:11:51 +03:00
Fringg
74080004e8 fix: media upload security hardening from 6-agent review
- uploadCount: always decrement in finally (prevent permanent uploading state)
- AbortSignal: pass to actual HTTP request (cancel network, not just UI)
- Concurrent uploads: use Set<AbortController> instead of single ref
- DOMPurify hooks: scope inside sanitizeHtml() to avoid global pollution
- Video src: restrict to HTTPS only (was allowing HTTP)
- GIF: remove from accept attributes (backend rejects GIF)
- Ref mutation: move handleMediaUploadRef update to useEffect
2026-03-23 12:05:55 +03:00
Fringg
723591e5c3 feat: add media upload to news editor with drag-drop, paste, and file picker
Upload images/videos directly to server from editor. DOMPurify video
sanitization, XSS protection, upload cancellation on unmount.
2026-03-23 11:58:18 +03:00
Fringg
8d994f75d9 fix: remove animated background from news section, fix mobile borders
- Remove GridBackground and ScanLine animations
- Use simple transparent blur background instead
- Remove negative margins that broke rounded corners on mobile
2026-03-23 11:23:44 +03:00
Fringg
38b0f4be9a fix: add news link to admin panel, prevent empty news section flash
- Add News item to marketing group in AdminPanel with NewspaperIcon
- Add news nav/panel translations for all 4 locales (ru, en, zh, fa)
- Don't render NewsSection until query confirms articles exist
- Remove skeleton that caused brief flash when news list is empty
2026-03-23 11:21:25 +03:00
Fringg
74e6d52fee fix: news feature security, accessibility, performance improvements
- DOMPurify strict allowlist with sandbox on iframes
- safeColor() CSS injection prevention for category_color
- URL validation (http/https) for images and links
- encodeURIComponent for slug in API calls
- Keyboard navigation on news cards (Enter/Space)
- aria-label, aria-pressed, type=button on all buttons
- 44px touch targets on remaining buttons
- memo() wrappers + stable callbacks (fewer re-renders)
- Canvas draw call batching (~75% reduction)
- TipTap extensions useMemo deps fix ([t] -> [])
- Featured image loading=eager fetchPriority=high (LCP)
- Unsafe Number(id) NaN guard
2026-03-23 11:09:52 +03:00
Fringg
99fc33625e feat: add news section with admin editor and public article view
- NewsSection with animated grid background, category filters, featured cards
- AdminNews list page with toggle publish/featured, pagination
- AdminNewsCreate with TipTap rich text editor, URL validation
- NewsArticle detail page with DOMPurify sanitization, Telegram back button
- Toggle component with WCAG 44px touch targets, role=switch
- Prose styles for highlight marks and responsive iframes
- i18n translations (en, ru, zh, fa)
2026-03-23 10:49:46 +03:00
Egor
eea3b6c269 Merge pull request #343 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.41.0
2026-03-22 10:56:31 +03:00
github-actions[bot]
be9c28cd14 chore(main): release 1.41.0 2026-03-22 07:56:07 +00:00
Egor
39c0d11962 Merge pull request #342 from BEDOLAGA-DEV/dev
Dev
2026-03-22 10:55:40 +03:00
Fringg
5b12784ab8 feat: show subscription revenue and referral earnings in network stats
Add subscription revenue (total from subscription payments) to the
stats panel alongside referral earnings. Layout updated to 2-column
grid with subscription revenue highlighted in accent color.
2026-03-22 10:31:29 +03:00
Fringg
ebe2c3af7e fix: use dark label color on hover (white bg), light on normal (dark bg)
Switch labelColor to attribute-based mode so hovered/highlighted nodes
get dark text (#111827) readable on the white hover background, while
normal labels stay light (#e5e7eb) readable on the dark canvas.
2026-03-22 10:26:16 +03:00
Fringg
0cc1cd5871 fix: use light label color for graph nodes on dark background 2026-03-22 10:18:34 +03:00
Fringg
2229eeecb0 fix: remove campaignUser fill color — campaign membership shown via edges
Campaign users no longer get a separate amber fill color. Their campaign
association is already visible through the edge connecting them to the
campaign node. Users from campaigns now show their subscription status
color (or regular gray if no subscription), reducing visual noise.
2026-03-22 10:13:56 +03:00
Fringg
2436060b5a fix: use white campaign edges to avoid blending with trial expired nodes 2026-03-22 10:08:42 +03:00