refactor: remove subscription and lifetime credits logic from credit stats and balance card

This commit is contained in:
javayhu 2025-08-22 00:04:40 +08:00
parent 19120ee7f1
commit 63a5e4f328
4 changed files with 18 additions and 89 deletions

View File

@ -601,8 +601,7 @@
"creditsAdded": "Credits have been added to your account", "creditsAdded": "Credits have been added to your account",
"viewTransactions": "View Credit Transactions", "viewTransactions": "View Credit Transactions",
"retry": "Retry", "retry": "Retry",
"subscriptionCredits": "{credits} credits from subscription this month",
"lifetimeCredits": "{credits} credits from lifetime plan this month",
"expiringCredits": "{credits} credits expiring on {date}" "expiringCredits": "{credits} credits expiring on {date}"
}, },
"packages": { "packages": {

View File

@ -601,8 +601,7 @@
"creditsAdded": "积分已添加到您的账户", "creditsAdded": "积分已添加到您的账户",
"viewTransactions": "查看积分记录", "viewTransactions": "查看积分记录",
"retry": "重试", "retry": "重试",
"subscriptionCredits": "本月订阅获得 {credits} 积分",
"lifetimeCredits": "本月终身会员获得 {credits} 积分",
"expiringCredits": "{credits} 积分将在 {date} 过期" "expiringCredits": "{credits} 积分将在 {date} 过期"
}, },
"packages": { "packages": {

View File

@ -1,6 +1,5 @@
'use server'; 'use server';
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
import { getDb } from '@/db'; import { getDb } from '@/db';
import { creditTransaction } from '@/db/schema'; import { creditTransaction } from '@/db/schema';
import type { User } from '@/lib/auth-types'; import type { User } from '@/lib/auth-types';
@ -9,7 +8,6 @@ import { addDays } from 'date-fns';
import { and, eq, gte, isNotNull, lte, sql, sum } from 'drizzle-orm'; import { and, eq, gte, isNotNull, lte, sql, sum } from 'drizzle-orm';
const CREDITS_EXPIRATION_DAYS = 31; const CREDITS_EXPIRATION_DAYS = 31;
const CREDITS_MONTHLY_DAYS = 31;
/** /**
* Get credit statistics for a user * Get credit statistics for a user
@ -39,38 +37,6 @@ export const getCreditStatsAction = userActionClient.action(async ({ ctx }) => {
) )
); );
// Get credits from subscription renewals (recent CREDITS_MONTHLY_DAYS days)
const monthlyRefreshDaysAgo = addDays(new Date(), -CREDITS_MONTHLY_DAYS);
const subscriptionCredits = await db
.select({
amount: sum(creditTransaction.amount),
})
.from(creditTransaction)
.where(
and(
eq(creditTransaction.userId, userId),
eq(
creditTransaction.type,
CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL
),
gte(creditTransaction.createdAt, monthlyRefreshDaysAgo)
)
);
// Get credits from monthly lifetime distribution (recent CREDITS_MONTHLY_DAYS days)
const lifetimeCredits = await db
.select({
amount: sum(creditTransaction.amount),
})
.from(creditTransaction)
.where(
and(
eq(creditTransaction.userId, userId),
eq(creditTransaction.type, CREDIT_TRANSACTION_TYPE.LIFETIME_MONTHLY),
gte(creditTransaction.createdAt, monthlyRefreshDaysAgo)
)
);
return { return {
success: true, success: true,
data: { data: {
@ -78,12 +44,6 @@ export const getCreditStatsAction = userActionClient.action(async ({ ctx }) => {
amount: Number(expiringCredits[0]?.amount) || 0, amount: Number(expiringCredits[0]?.amount) || 0,
earliestExpiration: expiringCredits[0]?.earliestExpiration || null, earliestExpiration: expiringCredits[0]?.earliestExpiration || null,
}, },
subscriptionCredits: {
amount: Number(subscriptionCredits[0]?.amount) || 0,
},
lifetimeCredits: {
amount: Number(lifetimeCredits[0]?.amount) || 0,
},
}, },
}; };
} catch (error) { } catch (error) {

View File

@ -13,9 +13,7 @@ import { Skeleton } from '@/components/ui/skeleton';
import { websiteConfig } from '@/config/website'; import { websiteConfig } from '@/config/website';
import { useCreditBalance, useCreditStats } from '@/hooks/use-credits'; import { useCreditBalance, useCreditStats } from '@/hooks/use-credits';
import { useMounted } from '@/hooks/use-mounted'; import { useMounted } from '@/hooks/use-mounted';
import { useCurrentPlan } from '@/hooks/use-payment';
import { useLocaleRouter } from '@/i18n/navigation'; import { useLocaleRouter } from '@/i18n/navigation';
import { authClient } from '@/lib/auth-client';
import { formatDate } from '@/lib/formatter'; import { formatDate } from '@/lib/formatter';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { Routes } from '@/routes'; import { Routes } from '@/routes';
@ -48,11 +46,6 @@ export default function CreditsBalanceCard() {
refetch: refetchBalance, refetch: refetchBalance,
} = useCreditBalance(); } = useCreditBalance();
// Get payment info to check plan type
const { data: session } = authClient.useSession();
const { data: paymentData } = useCurrentPlan(session?.user?.id);
const currentPlan = paymentData?.currentPlan;
// TanStack Query hook for credit statistics // TanStack Query hook for credit statistics
const { const {
data: creditStats, data: creditStats,
@ -167,44 +160,22 @@ export default function CreditsBalanceCard() {
{/* Balance information */} {/* Balance information */}
<div className="text-sm text-muted-foreground space-y-2"> <div className="text-sm text-muted-foreground space-y-2">
{/* Plan-based credits info */} {/* Expiring credits warning */}
{!isLoadingStats && creditStats && ( {!isLoadingStats &&
<> creditStats &&
{/* Subscription credits (for paid plans) */} creditStats.expiringCredits.amount > 0 &&
{!currentPlan?.isFree && creditStats.expiringCredits.earliestExpiration && (
(creditStats.subscriptionCredits.amount > 0 || <div className="flex items-center gap-2 text-amber-600">
creditStats.lifetimeCredits.amount > 0) && ( <span>
<div className="flex items-center gap-2 text-muted-foreground"> {t('expiringCredits', {
<span> credits: creditStats.expiringCredits.amount,
{currentPlan?.isLifetime date: formatDate(
? t('lifetimeCredits', { new Date(creditStats.expiringCredits.earliestExpiration)
credits: creditStats.lifetimeCredits.amount, ),
}) })}
: t('subscriptionCredits', { </span>
credits: creditStats.subscriptionCredits.amount, </div>
})} )}
</span>
</div>
)}
{/* Expiring credits warning */}
{creditStats.expiringCredits.amount > 0 &&
creditStats.expiringCredits.earliestExpiration && (
<div className="flex items-center gap-2 text-amber-600">
<span>
{t('expiringCredits', {
credits: creditStats.expiringCredits.amount,
date: formatDate(
new Date(
creditStats.expiringCredits.earliestExpiration
)
),
})}
</span>
</div>
)}
</>
)}
</div> </div>
</CardContent> </CardContent>
<CardFooter className=""> <CardFooter className="">