From 450ad1ea1f1a949108462b48eb9ae265873be658 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Sun, 19 Jul 2026 02:31:52 +0300 Subject: [PATCH] Enhance user management and billing integration - Updated the `UserSummaryDto` to include `BillingEnabled` and `BillingPaidUntil` properties, allowing for better tracking of user billing status. - Refactored the `IdentityService` to populate the new billing fields when retrieving user summaries. - Modified the dashboard and admin user management components to display billing information, including a link to the billing page and a badge for billing status. - Added internationalization support for new billing-related labels in both English and Russian. - Ensured frontend components reflect the updated user data structure, enhancing user experience with billing visibility. --- .../Common/Interfaces/IIdentityService.cs | 4 ++- .../Identity/IdentityService.cs | 8 +++-- .../src/features/billing/PaidUntilBadge.tsx | 32 +++++++++++++++++++ frontend/src/routes/admin/users.tsx | 9 ++++++ frontend/src/routes/dashboard.tsx | 11 ++++++- frontend/src/shared/api/types.ts | 2 ++ frontend/src/shared/lib/i18n.ts | 10 ++++++ 7 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 frontend/src/features/billing/PaidUntilBadge.tsx diff --git a/backend/src/PnvPanel.Application/Common/Interfaces/IIdentityService.cs b/backend/src/PnvPanel.Application/Common/Interfaces/IIdentityService.cs index a571406..2c7c068 100644 --- a/backend/src/PnvPanel.Application/Common/Interfaces/IIdentityService.cs +++ b/backend/src/PnvPanel.Application/Common/Interfaces/IIdentityService.cs @@ -34,7 +34,9 @@ public sealed record UserSummaryDto( string Role, bool IsActivated, bool IsBlocked, - DateTimeOffset? ActivatedAt + DateTimeOffset? ActivatedAt, + bool BillingEnabled, + DateTimeOffset? BillingPaidUntil ); public sealed record UserStatsDto(int Total, int Activated); diff --git a/backend/src/PnvPanel.Infrastructure/Identity/IdentityService.cs b/backend/src/PnvPanel.Infrastructure/Identity/IdentityService.cs index 3cec77e..abfbdfe 100644 --- a/backend/src/PnvPanel.Infrastructure/Identity/IdentityService.cs +++ b/backend/src/PnvPanel.Infrastructure/Identity/IdentityService.cs @@ -269,15 +269,17 @@ internal sealed class IdentityService( var items = new List(users.Count); foreach (var user in users) { - var roleName = await GetPrimaryRoleNameAsync(user); + var role = await GetPrimaryRoleAsync(user); items.Add( new UserSummaryDto( user.Id, user.UserName!, - roleName, + role.Name!, user.IsActivated, user.IsBlocked, - user.ActivatedAt + user.ActivatedAt, + role.BillingEnabled, + user.BillingPaidUntil ) ); } diff --git a/frontend/src/features/billing/PaidUntilBadge.tsx b/frontend/src/features/billing/PaidUntilBadge.tsx new file mode 100644 index 0000000..87a0a53 --- /dev/null +++ b/frontend/src/features/billing/PaidUntilBadge.tsx @@ -0,0 +1,32 @@ +import { useTranslation } from 'react-i18next' +import { Badge } from '@/shared/ui/badge' + +const RED_THRESHOLD_DAYS = 3 +const YELLOW_THRESHOLD_DAYS = 7 + +/** Дней до paidUntil, округление вверх — «меньше суток» всё равно считается как 1 день, а не 0. */ +function daysRemaining(paidUntil: string): number { + const diffMs = new Date(paidUntil).getTime() - Date.now() + return Math.ceil(diffMs / (24 * 60 * 60 * 1000)) +} + +/** Цветовая индикация оплаченного периода: зелёный — обычный запас, жёлтый — ≤7 дней, красный — + * ≤3 дней или уже истекло. Общий компонент для дашборда пользователя и списка пользователей в админке. */ +export function PaidUntilBadge({ paidUntil }: { paidUntil: string | null }) { + const { t } = useTranslation() + + if (!paidUntil) return {t('billing.neverPaidShort')} + + const days = daysRemaining(paidUntil) + const variant = days <= RED_THRESHOLD_DAYS ? 'destructive' : days <= YELLOW_THRESHOLD_DAYS ? 'warning' : 'success' + const label = + days <= 0 + ? t('billing.expiredShort') + : t('billing.daysRemaining', { count: days }) + + return ( + + {label} + + ) +} diff --git a/frontend/src/routes/admin/users.tsx b/frontend/src/routes/admin/users.tsx index 9041dee..0cc02b7 100644 --- a/frontend/src/routes/admin/users.tsx +++ b/frontend/src/routes/admin/users.tsx @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next' import { Input } from '@/shared/ui/input' import { Button } from '@/shared/ui/button' import { Badge } from '@/shared/ui/badge' +import { PaidUntilBadge } from '@/features/billing/PaidUntilBadge' import { listUsers } from '@/features/admin/users/api' import { UserManageDialog } from '@/features/admin/users/UserManageDialog' import type { UserSummaryDto } from '@/shared/api/types' @@ -56,6 +57,7 @@ function AdminUsersPage() { {t('admin.users.userName')} {t('admin.users.role')} {t('admin.users.statusLabel')} + {t('admin.users.billingLabel')} @@ -73,6 +75,13 @@ function AdminUsersPage() { : t('admin.users.status.pending')} + + {user.billingEnabled ? ( + + ) : ( + + )} +