refactor: conditionally render credits-related components based on configuration

This commit is contained in:
javayhu 2025-07-13 00:09:05 +08:00
parent 31116cbf8b
commit 4313e32471
6 changed files with 57 additions and 19 deletions

View File

@ -571,6 +571,7 @@
"createCustomerPortalFailed": "Failed to open Stripe customer portal"
},
"price": "Price:",
"periodStartDate": "Period start date:",
"nextBillingDate": "Next billing date:",
"trialEnds": "Trial ends:",
"freePlanMessage": "You are currently on the free plan with limited features",

View File

@ -571,6 +571,7 @@
"createCustomerPortalFailed": "打开Stripe客户界面失败"
},
"price": "价格:",
"periodStartDate": "周期开始日期:",
"nextBillingDate": "下次账单日期:",
"trialEnds": "试用结束日期:",
"freePlanMessage": "您当前使用的是功能有限的免费方案",

View File

@ -1,12 +1,18 @@
'use client';
import { Button } from '@/components/ui/button';
import { websiteConfig } from '@/config/website';
import { useCredits } from '@/hooks/use-credits';
import { useLocaleRouter } from '@/i18n/navigation';
import { Routes } from '@/routes';
import { CoinsIcon, Loader2Icon } from 'lucide-react';
export function CreditsBalanceButton() {
// If credits are not enabled, return null
if (!websiteConfig.credits.enableCredits) {
return null;
}
const router = useLocaleRouter();
// Use the new useCredits hook

View File

@ -1,5 +1,6 @@
'use client';
import { websiteConfig } from '@/config/website';
import { useCredits } from '@/hooks/use-credits';
import { useLocaleRouter } from '@/i18n/navigation';
import { Routes } from '@/routes';
@ -7,6 +8,11 @@ import { CoinsIcon, Loader2Icon } from 'lucide-react';
import { useTranslations } from 'next-intl';
export function CreditsBalanceMenu() {
// If credits are not enabled, return null
if (!websiteConfig.credits.enableCredits) {
return null;
}
const t = useTranslations('Marketing.avatar');
const router = useLocaleRouter();

View File

@ -20,7 +20,7 @@ import { formatDate, formatPrice } from '@/lib/formatter';
import { cn } from '@/lib/utils';
import { PlanIntervals } from '@/payment/types';
import { Routes } from '@/routes';
import { RefreshCwIcon } from 'lucide-react';
import { CheckCircleIcon, ClockIcon, RefreshCwIcon } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { useSearchParams } from 'next/navigation';
import { useEffect, useRef } from 'react';
@ -63,6 +63,11 @@ export default function BillingCard() {
(price) => price.priceId === subscription?.priceId
);
// Get current period start date
const currentPeriodStart = subscription?.currentPeriodStart
? formatDate(subscription.currentPeriodStart)
: null;
// Format next billing date if subscription is active
const nextBillingDate = subscription?.currentPeriodEnd
? formatDate(subscription.currentPeriodEnd)
@ -178,15 +183,23 @@ export default function BillingCard() {
{/* Plan name and status */}
<div className="flex items-center justify-start space-x-4">
<div className="text-3xl font-medium">{currentPlan?.name}</div>
{subscription && (
<Badge variant="outline">
{subscription?.status === 'trialing'
? t('status.trial')
: subscription?.status === 'active'
? t('status.active')
: ''}
</Badge>
)}
{subscription &&
(subscription.status === 'trialing' ||
subscription.status === 'active') && (
<Badge variant="outline" className="text-xs">
{subscription.status === 'trialing' ? (
<div className="flex items-center space-x-2">
<ClockIcon className="size-3 mr-1 text-amber-600" />
{t('status.trial')}
</div>
) : (
<div className="flex items-center space-x-2">
<CheckCircleIcon className="size-3 mr-1 text-green-600" />
{t('status.active')}
</div>
)}
</Badge>
)}
</div>
{/* Free plan message */}
@ -206,7 +219,7 @@ export default function BillingCard() {
{/* Subscription plan message */}
{subscription && currentPrice && (
<div className="text-sm text-muted-foreground space-y-2">
<div>
{/* <div>
{t('price')}{' '}
{formatPrice(currentPrice.amount, currentPrice.currency)} /{' '}
{currentPrice.interval === PlanIntervals.MONTH
@ -214,10 +227,16 @@ export default function BillingCard() {
: currentPrice.interval === PlanIntervals.YEAR
? t('interval.year')
: t('interval.oneTime')}
</div>
</div> */}
{currentPeriodStart && (
<div className="text-muted-foreground">
{t('periodStartDate')} {currentPeriodStart}
</div>
)}
{nextBillingDate && (
<div className="text-green-600">
<div className="text-muted-foreground">
{t('nextBillingDate')} {nextBillingDate}
</div>
)}

View File

@ -14,6 +14,7 @@ import {
UsersRoundIcon,
} from 'lucide-react';
import { useTranslations } from 'next-intl';
import { websiteConfig } from './website';
/**
* Get sidebar config with translations
@ -67,12 +68,16 @@ export function getSidebarLinks(): NestedMenuItem[] {
href: Routes.SettingsBilling,
external: false,
},
{
title: t('settings.credits.title'),
icon: <CoinsIcon className="size-4 shrink-0" />,
href: Routes.SettingsCredits,
external: false,
},
...(websiteConfig.credits.enableCredits
? [
{
title: t('settings.credits.title'),
icon: <CoinsIcon className="size-4 shrink-0" />,
href: Routes.SettingsCredits,
external: false,
},
]
: []),
{
title: t('settings.security.title'),
icon: <LockKeyholeIcon className="size-4 shrink-0" />,