diff --git a/messages/zh.json b/messages/zh.json index b0d2cd9..886a5ea 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -624,7 +624,7 @@ "remainingAmount": "剩余金额", "paymentId": "支付编号", "expirationDate": "过期日期", - "expirationDateProcessedAt": "过期日期处理时间", + "expirationDateProcessedAt": "过期处理时间", "createdAt": "创建时间", "updatedAt": "更新时间" }, diff --git a/src/actions/consume-credits.ts b/src/actions/consume-credits.ts new file mode 100644 index 0000000..b9a7210 --- /dev/null +++ b/src/actions/consume-credits.ts @@ -0,0 +1,43 @@ +'use server'; + +import { consumeCredits } from '@/credits/credits'; +import { getSession } from '@/lib/server'; +import { createSafeActionClient } from 'next-safe-action'; +import { z } from 'zod'; + +const actionClient = createSafeActionClient(); + +// consume credits schema +const consumeSchema = z.object({ + amount: z.number().min(1), + description: z.string().optional(), +}); + +/** + * Consume credits + */ +export const consumeCreditsAction = actionClient + .schema(consumeSchema) + .action(async ({ parsedInput }) => { + const session = await getSession(); + if (!session) { + console.warn('unauthorized request to consume credits'); + return { success: false, error: 'Unauthorized' }; + } + + try { + await consumeCredits({ + userId: session.user.id, + amount: parsedInput.amount, + description: + parsedInput.description || `Consume credits: ${parsedInput.amount}`, + }); + return { success: true }; + } catch (error) { + console.error('consume credits error:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Something went wrong', + }; + } + }); diff --git a/src/actions/credits.action.ts b/src/actions/credits.action.ts deleted file mode 100644 index 6b68cb4..0000000 --- a/src/actions/credits.action.ts +++ /dev/null @@ -1,61 +0,0 @@ -'use server'; - -import { - addMonthlyFreeCredits, - addRegisterGiftCredits, - consumeCredits, - getUserCredits, -} from '@/credits/credits'; -import { getSession } from '@/lib/server'; -import { createSafeActionClient } from 'next-safe-action'; -import { z } from 'zod'; - -const actionClient = createSafeActionClient(); - -// get current user's credits -export const getCreditsAction = actionClient.action(async () => { - const session = await getSession(); - if (!session) return { success: false, error: 'Unauthorized' }; - const credits = await getUserCredits(session.user.id); - return { success: true, credits }; -}); - -// add register gift credits (for testing) -export const addRegisterCreditsAction = actionClient.action(async () => { - const session = await getSession(); - if (!session) return { success: false, error: 'Unauthorized' }; - await addRegisterGiftCredits(session.user.id); - return { success: true }; -}); - -// add monthly free credits (for testing) -export const addMonthlyCreditsAction = actionClient.action(async () => { - const session = await getSession(); - if (!session) return { success: false, error: 'Unauthorized' }; - await addMonthlyFreeCredits(session.user.id); - return { success: true }; -}); - -// consume credits (simulate button) -const consumeSchema = z.object({ - amount: z.number().min(1), - description: z.string().optional(), -}); - -export const consumeCreditsAction = actionClient - .schema(consumeSchema) - .action(async ({ parsedInput }) => { - const session = await getSession(); - if (!session) return { success: false, error: 'Unauthorized' }; - try { - await consumeCredits({ - userId: session.user.id, - amount: parsedInput.amount, - description: - parsedInput.description || `Consume credits: ${parsedInput.amount}`, - }); - return { success: true }; - } catch (e) { - return { success: false, error: (e as Error).message }; - } - }); diff --git a/src/actions/get-credit-balance.ts b/src/actions/get-credit-balance.ts new file mode 100644 index 0000000..1e0b6ba --- /dev/null +++ b/src/actions/get-credit-balance.ts @@ -0,0 +1,21 @@ +'use server'; + +import { getUserCredits } from '@/credits/credits'; +import { getSession } from '@/lib/server'; +import { createSafeActionClient } from 'next-safe-action'; + +const actionClient = createSafeActionClient(); + +/** + * Get current user's credits + */ +export const getCreditBalanceAction = actionClient.action(async () => { + const session = await getSession(); + if (!session) { + console.warn('unauthorized request to get credit balance'); + return { success: false, error: 'Unauthorized' }; + } + + const credits = await getUserCredits(session.user.id); + return { success: true, credits }; +}); diff --git a/src/actions/get-credit-transactions.ts b/src/actions/get-credit-transactions.ts index 65dd504..61d9b82 100644 --- a/src/actions/get-credit-transactions.ts +++ b/src/actions/get-credit-transactions.ts @@ -45,11 +45,13 @@ export const getCreditTransactionsAction = actionClient try { const { pageIndex, pageSize, search, sorting } = parsedInput; + // search by type, amount, paymentId, description const where = search ? or( - ilike(creditTransaction.description, `%${search}%`), ilike(creditTransaction.type, `%${search}%`), - ilike(creditTransaction.paymentId, `%${search}%`) + ilike(creditTransaction.amount, `%${search}%`), + ilike(creditTransaction.paymentId, `%${search}%`), + ilike(creditTransaction.description, `%${search}%`) ) : undefined; diff --git a/src/components/layout/credits-balance-button.tsx b/src/components/layout/credits-balance-button.tsx index 03cb9da..07f6763 100644 --- a/src/components/layout/credits-balance-button.tsx +++ b/src/components/layout/credits-balance-button.tsx @@ -1,6 +1,6 @@ 'use client'; -import { getCreditsAction } from '@/actions/credits.action'; +import { getCreditBalanceAction } from '@/actions/get-credit-balance'; import { Button } from '@/components/ui/button'; import { useLocaleRouter } from '@/i18n/navigation'; import { Routes } from '@/routes'; @@ -17,7 +17,7 @@ export function CreditsBalanceButton() { useEffect(() => { const fetchCredits = async () => { try { - const result = await getCreditsAction(); + const result = await getCreditBalanceAction(); if (result?.data?.success && result.data.credits !== undefined) { setCredits(result.data.credits); } diff --git a/src/components/layout/credits-balance-menu.tsx b/src/components/layout/credits-balance-menu.tsx index 160cd37..ad0c4a1 100644 --- a/src/components/layout/credits-balance-menu.tsx +++ b/src/components/layout/credits-balance-menu.tsx @@ -1,6 +1,6 @@ 'use client'; -import { getCreditsAction } from '@/actions/credits.action'; +import { getCreditBalanceAction } from '@/actions/get-credit-balance'; import { useLocaleRouter } from '@/i18n/navigation'; import { Routes } from '@/routes'; import { useTransactionStore } from '@/stores/transaction-store'; @@ -18,7 +18,7 @@ export function CreditsBalanceMenu() { useEffect(() => { const fetchCredits = async () => { try { - const result = await getCreditsAction(); + const result = await getCreditBalanceAction(); if (result?.data?.success && result.data.credits !== undefined) { setCredits(result.data.credits); } diff --git a/src/components/settings/credits/credit-packages.tsx b/src/components/settings/credits/credit-packages.tsx index e13f733..f7e31c0 100644 --- a/src/components/settings/credits/credit-packages.tsx +++ b/src/components/settings/credits/credit-packages.tsx @@ -1,6 +1,6 @@ 'use client'; -import { getCreditsAction } from '@/actions/credits.action'; +import { getCreditBalanceAction } from '@/actions/get-credit-balance'; import { Badge } from '@/components/ui/badge'; import { Card, @@ -44,7 +44,7 @@ export function CreditPackages() { const fetchCredits = async () => { try { setLoadingCredits(true); - const result = await getCreditsAction(); + const result = await getCreditBalanceAction(); if (result?.data?.success) { console.log('CreditPackages, fetched credits:', result.data.credits); setCredits(result.data.credits || 0); diff --git a/src/payment/provider/stripe.ts b/src/payment/provider/stripe.ts index d364ee7..fb4f490 100644 --- a/src/payment/provider/stripe.ts +++ b/src/payment/provider/stripe.ts @@ -828,7 +828,7 @@ export class StripeProvider implements PaymentProvider { userId, amount: Number.parseInt(credits), type: CREDIT_TRANSACTION_TYPE.PURCHASE, - description: `+${credits} credits for package ${packageId} (${amount})`, + description: `+${credits} credits for package ${packageId} ($${amount.toLocaleString()})`, paymentId: session.id, expireDays: creditPackage.expireDays, });