Enhance PaidUntilBadge component to support pending payment review status
- Updated the PaidUntilBadge component to accept a new `pendingReview` prop, indicating if a payment is awaiting admin confirmation. - Modified the rendering logic to display a warning badge when a payment is under review, providing users with a neutral status instead of a negative one. - Updated relevant components in billing and dashboard routes to pass the new `pendingReview` prop based on the active payment request status. - Added internationalization support for new labels related to the pending review status in both English and Russian.
This commit is contained in:
@@ -6,10 +6,27 @@ const RED_THRESHOLD_DAYS = 3
|
|||||||
const YELLOW_THRESHOLD_DAYS = 7
|
const YELLOW_THRESHOLD_DAYS = 7
|
||||||
|
|
||||||
/** Цветовая индикация оплаченного периода: зелёный — обычный запас, жёлтый — ≤7 дней, красный —
|
/** Цветовая индикация оплаченного периода: зелёный — обычный запас, жёлтый — ≤7 дней, красный —
|
||||||
* ≤3 дней или уже истекло. Общий компонент для дашборда пользователя и списка пользователей в админке. */
|
* ≤3 дней или уже истекло. Общий компонент для дашборда пользователя и списка пользователей в админке.
|
||||||
export function PaidUntilBadge({ paidUntil }: { paidUntil: string | null }) {
|
*
|
||||||
|
* `pendingReview` — есть заявка на оплату, ожидающая решения админа (`PaymentRequestStatus.AwaitingConfirmation`):
|
||||||
|
* конфиги не гасятся, пока админ не решит (см. BillingService), поэтому вместо тревожного "Истекло"
|
||||||
|
* показываем нейтральный статус — пользователю незачем переживать за то, что от него не зависит. */
|
||||||
|
export function PaidUntilBadge({
|
||||||
|
paidUntil,
|
||||||
|
pendingReview,
|
||||||
|
}: {
|
||||||
|
paidUntil: string | null
|
||||||
|
pendingReview?: boolean
|
||||||
|
}) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
if (pendingReview)
|
||||||
|
return (
|
||||||
|
<Badge variant="warning" title={t('billing.pendingReviewHint')}>
|
||||||
|
{t('billing.pendingReviewShort')}
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
|
||||||
if (!paidUntil) return <Badge variant="destructive">{t('billing.neverPaidShort')}</Badge>
|
if (!paidUntil) return <Badge variant="destructive">{t('billing.neverPaidShort')}</Badge>
|
||||||
|
|
||||||
const days = getDaysRemaining(paidUntil)
|
const days = getDaysRemaining(paidUntil)
|
||||||
|
|||||||
@@ -63,7 +63,12 @@ function BillingContent() {
|
|||||||
? t('billing.paidUntil', { date: new Date(data.paidUntil).toLocaleDateString() })
|
? t('billing.paidUntil', { date: new Date(data.paidUntil).toLocaleDateString() })
|
||||||
: t('billing.neverPaid')}
|
: t('billing.neverPaid')}
|
||||||
</p>
|
</p>
|
||||||
{data.paidUntil && <PaidUntilBadge paidUntil={data.paidUntil} />}
|
{data.paidUntil && (
|
||||||
|
<PaidUntilBadge
|
||||||
|
paidUntil={data.paidUntil}
|
||||||
|
pendingReview={data.activeRequest?.status === 'AwaitingConfirmation'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,10 @@ function ConfigsList() {
|
|||||||
{billingStatusQuery.data?.billingEnabled && (
|
{billingStatusQuery.data?.billingEnabled && (
|
||||||
<Link to="/billing" className="mt-1 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground">
|
<Link to="/billing" className="mt-1 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground">
|
||||||
{t('billing.paidUntilLabel')}
|
{t('billing.paidUntilLabel')}
|
||||||
<PaidUntilBadge paidUntil={billingStatusQuery.data.paidUntil} />
|
<PaidUntilBadge
|
||||||
|
paidUntil={billingStatusQuery.data.paidUntil}
|
||||||
|
pendingReview={billingStatusQuery.data.activeRequest?.status === 'AwaitingConfirmation'}
|
||||||
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ const resources = {
|
|||||||
daysRemaining: '{{count}} дн.',
|
daysRemaining: '{{count}} дн.',
|
||||||
hoursMinutesRemaining: '{{hours}} ч {{minutes}} мин',
|
hoursMinutesRemaining: '{{hours}} ч {{minutes}} мин',
|
||||||
minutesRemaining: '{{count}} мин',
|
minutesRemaining: '{{count}} мин',
|
||||||
|
pendingReviewShort: 'На проверке',
|
||||||
|
pendingReviewHint: 'Оплата отправлена на проверку администратору — доступ не будет приостановлен, пока заявка не решена.',
|
||||||
newRequest: 'Оформить оплату',
|
newRequest: 'Оформить оплату',
|
||||||
period: 'Период',
|
period: 'Период',
|
||||||
periods: {
|
periods: {
|
||||||
@@ -638,6 +640,8 @@ const resources = {
|
|||||||
daysRemaining: '{{count}}d',
|
daysRemaining: '{{count}}d',
|
||||||
hoursMinutesRemaining: '{{hours}}h {{minutes}}m',
|
hoursMinutesRemaining: '{{hours}}h {{minutes}}m',
|
||||||
minutesRemaining: '{{count}}m',
|
minutesRemaining: '{{count}}m',
|
||||||
|
pendingReviewShort: 'Under review',
|
||||||
|
pendingReviewHint: 'Payment sent for admin review — access will not be suspended until the request is decided.',
|
||||||
newRequest: 'Set up payment',
|
newRequest: 'Set up payment',
|
||||||
period: 'Period',
|
period: 'Period',
|
||||||
periods: {
|
periods: {
|
||||||
|
|||||||
Reference in New Issue
Block a user