feat: implement consume credits action and get credit balance action, update credits balance references
This commit is contained in:
parent
263440742a
commit
de1ccca27b
@ -624,7 +624,7 @@
|
||||
"remainingAmount": "剩余金额",
|
||||
"paymentId": "支付编号",
|
||||
"expirationDate": "过期日期",
|
||||
"expirationDateProcessedAt": "过期日期处理时间",
|
||||
"expirationDateProcessedAt": "过期处理时间",
|
||||
"createdAt": "创建时间",
|
||||
"updatedAt": "更新时间"
|
||||
},
|
||||
|
43
src/actions/consume-credits.ts
Normal file
43
src/actions/consume-credits.ts
Normal file
@ -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',
|
||||
};
|
||||
}
|
||||
});
|
@ -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 };
|
||||
}
|
||||
});
|
21
src/actions/get-credit-balance.ts
Normal file
21
src/actions/get-credit-balance.ts
Normal file
@ -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 };
|
||||
});
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user