prmbr-image-mksaas/src/hooks/use-credits.ts

154 lines
4.2 KiB
TypeScript

import { consumeCreditsAction } from '@/actions/consume-credits';
import { getCreditBalanceAction } from '@/actions/get-credit-balance';
import { getCreditStatsAction } from '@/actions/get-credit-stats';
import { getCreditTransactionsAction } from '@/actions/get-credit-transactions';
import { useCreditsStore } from '@/stores/credits-store';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type { SortingState } from '@tanstack/react-table';
import { useEffect } from 'react';
// Query keys
export const creditsKeys = {
all: ['credits'] as const,
balance: () => [...creditsKeys.all, 'balance'] as const,
stats: () => [...creditsKeys.all, 'stats'] as const,
transactions: () => [...creditsKeys.all, 'transactions'] as const,
transactionsList: (filters: {
pageIndex: number;
pageSize: number;
search: string;
sorting: SortingState;
}) => [...creditsKeys.transactions(), filters] as const,
};
// Hook to fetch credit balance
export function useCreditBalance() {
const updateTrigger = useCreditsStore((state) => state.updateTrigger);
const query = useQuery({
queryKey: creditsKeys.balance(),
queryFn: async () => {
console.log('Fetching credit balance...');
const result = await getCreditBalanceAction();
if (!result?.data?.success) {
throw new Error(
result?.data?.error || 'Failed to fetch credit balance'
);
}
console.log('Credit balance fetched:', result.data.credits);
return result.data.credits || 0;
},
});
// Refetch when updateTrigger changes
useEffect(() => {
if (updateTrigger > 0) {
console.log('Credits update triggered, refetching balance...');
query.refetch();
}
}, [updateTrigger, query]);
return query;
}
// Hook to fetch credit statistics
export function useCreditStats() {
const updateTrigger = useCreditsStore((state) => state.updateTrigger);
const query = useQuery({
queryKey: creditsKeys.stats(),
queryFn: async () => {
console.log('Fetching credit stats...');
const result = await getCreditStatsAction();
if (!result?.data?.success) {
throw new Error(result?.data?.error || 'Failed to fetch credit stats');
}
console.log('Credit stats fetched:', result.data.data);
return result.data.data;
},
});
// Refetch when updateTrigger changes
useEffect(() => {
if (updateTrigger > 0) {
console.log('Credits update triggered, refetching stats...');
query.refetch();
}
}, [updateTrigger, query]);
return query;
}
// Hook to consume credits
export function useConsumeCredits() {
const queryClient = useQueryClient();
const triggerUpdate = useCreditsStore((state) => state.triggerUpdate);
return useMutation({
mutationFn: async ({
amount,
description,
}: {
amount: number;
description: string;
}) => {
const result = await consumeCreditsAction({
amount,
description,
});
if (!result?.data?.success) {
throw new Error(result?.data?.error || 'Failed to consume credits');
}
return result.data;
},
onSuccess: () => {
// Trigger credits update in store to notify all components
triggerUpdate();
// Invalidate credit balance and stats after consuming credits
queryClient.invalidateQueries({
queryKey: creditsKeys.balance(),
});
queryClient.invalidateQueries({
queryKey: creditsKeys.stats(),
});
},
});
}
// Hook to fetch credit transactions with pagination, search, and sorting
export function useCreditTransactions(
pageIndex: number,
pageSize: number,
search: string,
sorting: SortingState
) {
return useQuery({
queryKey: creditsKeys.transactionsList({
pageIndex,
pageSize,
search,
sorting,
}),
queryFn: async () => {
const result = await getCreditTransactionsAction({
pageIndex,
pageSize,
search,
sorting,
});
if (!result?.data?.success) {
throw new Error(
result?.data?.error || 'Failed to fetch credit transactions'
);
}
return {
items: result.data.data?.items || [],
total: result.data.data?.total || 0,
};
},
});
}