Spaces:
Paused
Paused
| import { useQuery } from '@tanstack/react-query'; | |
| import { useTranslation } from 'react-i18next'; | |
| import { graphqlRequest } from '@/gql/graphql'; | |
| import { useSelectedProjectId } from '@/stores/projectStore'; | |
| import { useErrorHandler } from '@/hooks/use-error-handler'; | |
| import { useUsageLogPermissions } from '../../../gql/useUsageLogPermissions'; | |
| import { UsageLog, UsageLogConnection, usageLogConnectionSchema, usageLogSchema } from './schema'; | |
| // Dynamic GraphQL query builder | |
| function buildUsageLogsQuery(permissions: { canViewChannels: boolean }) { | |
| const channelFields = permissions.canViewChannels | |
| ? ` | |
| channel { | |
| id | |
| name | |
| type | |
| }` | |
| : ''; | |
| return ` | |
| query GetUsageLogs($first: Int, $after: Cursor, $orderBy: UsageLogOrder, $where: UsageLogWhereInput) { | |
| usageLogs(first: $first, after: $after, orderBy: $orderBy, where: $where) { | |
| edges { | |
| node { | |
| id | |
| createdAt | |
| updatedAt | |
| requestID${channelFields} | |
| modelID | |
| promptTokens | |
| completionTokens | |
| totalTokens | |
| promptAudioTokens | |
| promptCachedTokens | |
| promptWriteCachedTokens | |
| completionAudioTokens | |
| completionReasoningTokens | |
| completionAcceptedPredictionTokens | |
| completionRejectedPredictionTokens | |
| source | |
| format | |
| totalCost | |
| costItems { | |
| itemCode | |
| quantity | |
| subtotal | |
| } | |
| } | |
| cursor | |
| } | |
| pageInfo { | |
| hasNextPage | |
| hasPreviousPage | |
| startCursor | |
| endCursor | |
| } | |
| totalCount | |
| } | |
| } | |
| `; | |
| } | |
| function buildUsageLogDetailQuery(permissions: { canViewChannels: boolean }) { | |
| const channelFields = permissions.canViewChannels | |
| ? ` | |
| channel { | |
| id | |
| name | |
| type | |
| }` | |
| : ''; | |
| return ` | |
| query GetUsageLog($id: ID!) { | |
| node(id: $id) { | |
| ... on UsageLog { | |
| id | |
| createdAt | |
| updatedAt | |
| requestID${channelFields} | |
| modelID | |
| promptTokens | |
| completionTokens | |
| totalTokens | |
| promptAudioTokens | |
| promptCachedTokens | |
| promptWriteCachedTokens | |
| completionAudioTokens | |
| completionReasoningTokens | |
| completionAcceptedPredictionTokens | |
| completionRejectedPredictionTokens | |
| source | |
| format | |
| totalCost | |
| costItems { | |
| itemCode | |
| quantity | |
| subtotal | |
| } | |
| } | |
| } | |
| } | |
| `; | |
| } | |
| // Query hooks | |
| export function useUsageLogs(variables?: { | |
| first?: number; | |
| after?: string; | |
| orderBy?: { field: 'CREATED_AT'; direction: 'ASC' | 'DESC' }; | |
| where?: { | |
| source?: string; | |
| modelID?: string; | |
| channelID?: string; | |
| projectID?: string; | |
| [key: string]: any; | |
| }; | |
| }) { | |
| const { handleError } = useErrorHandler(); | |
| const { t } = useTranslation(); | |
| const permissions = useUsageLogPermissions(); | |
| const selectedProjectId = useSelectedProjectId(); | |
| return useQuery({ | |
| queryKey: ['usageLogs', variables, permissions, selectedProjectId], | |
| queryFn: async () => { | |
| try { | |
| const query = buildUsageLogsQuery(permissions); | |
| const headers = selectedProjectId ? { 'X-Project-ID': selectedProjectId } : undefined; | |
| const data = await graphqlRequest<{ usageLogs: UsageLogConnection }>(query, variables, headers); | |
| return usageLogConnectionSchema.parse(data?.usageLogs); | |
| } catch (error) { | |
| handleError(error, t('usageLogs.errors.loadUsageLogsFailed')); | |
| throw error; | |
| } | |
| }, | |
| enabled: !!selectedProjectId, // Only query when a project is selected | |
| }); | |
| } | |
| export function useUsageLog(id: string) { | |
| const { handleError } = useErrorHandler(); | |
| const { t } = useTranslation(); | |
| const permissions = useUsageLogPermissions(); | |
| const selectedProjectId = useSelectedProjectId(); | |
| return useQuery({ | |
| queryKey: ['usageLog', id, permissions, selectedProjectId], | |
| queryFn: async () => { | |
| try { | |
| const query = buildUsageLogDetailQuery(permissions); | |
| const headers = selectedProjectId ? { 'X-Project-ID': selectedProjectId } : undefined; | |
| const data = await graphqlRequest<{ node: UsageLog }>(query, { id }, headers); | |
| if (!data.node) { | |
| throw new Error('Usage log not found'); | |
| } | |
| return usageLogSchema.parse(data.node); | |
| } catch (error) { | |
| handleError(error, t('usageLogs.errors.loadUsageLogDetailFailed')); | |
| throw error; | |
| } | |
| }, | |
| enabled: !!id, | |
| }); | |
| } | |