diff --git a/web/src/api/hooks/useStoreHooks.ts b/web/src/api/hooks/useStoreHooks.ts index 4ef8232..a43c75e 100644 --- a/web/src/api/hooks/useStoreHooks.ts +++ b/web/src/api/hooks/useStoreHooks.ts @@ -1,16 +1,18 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useApiClients } from "../apiClient"; import { cacheKeys, cacheSettings, CACHE_TIMES } from "../utils/cache"; -import { +import type { + // Use type-only import for Error ApiKeyCreate, StoreUpdate, StoreBasicInfo, Error, SearchStoresParams, - GetApiKeyUsagePayload, // <-- Import payload type for usage stats - GetApiUsageLogParams, // <-- Import params type for usage log - ApiUsageLogEntry, // <-- Import log entry type - PaginationInfo, // <-- Import pagination info type + GetApiKeyUsagePayload, + GetApiUsageLogParams, + ApiUsageLogEntry, + PaginationInfo, + ApiKeyUsage, // <-- Add ApiKeyUsage import } from "../types/data-contracts"; import { useAuth } from "../../hooks/useAuth"; import { useState, useEffect } from "react"; @@ -90,24 +92,45 @@ export function useRevokeApiKey() { // Update useApiKeyUsage to accept payload export function useApiKeyUsage( - keyId: string, - payload?: GetApiKeyUsagePayload, // Accept payload + keyId: string | undefined, // Allow undefined here + payload?: GetApiKeyUsagePayload, ) { const { apiClients, clientsReady } = useApiClients(); const { isAuthenticated, isLoading: authLoading } = useAuth(); - // Include payload in the query key if present - // This object now matches the expected parameter type for the updated cache key - const queryKeyParams = { keyId, ...payload }; - - return useQuery({ - // This call should now be valid - queryKey: cacheKeys.stores.apiKeyUsage(queryKeyParams), - queryFn: () => - // Pass payload to the API call - apiClients.stores.getApiKeyUsage(keyId, payload).then((res) => res.data), - enabled: !!keyId && isAuthenticated && !authLoading && clientsReady, - ...cacheSettings.apiKeys, // Consider specific cache settings for usage + // Determine if the query should be enabled + // It should only run if a specific keyId is provided (not undefined, null, or "all") + const isEnabled = + isAuthenticated && + !authLoading && + clientsReady && + !!keyId && // Ensure keyId is truthy (not undefined, null, or empty string) + keyId !== "all"; // Explicitly disable if it's "all" + + return useQuery({ + // Use a more specific query key that includes the keyId and payload + queryKey: cacheKeys.stores.apiKeyUsage({ + // Pass a single object argument + keyId: keyId || "all", + startDate: payload?.startDate, + endDate: payload?.endDate, + }), + queryFn: () => { + // Add a check here just in case, although 'enabled' should prevent it + if (!keyId || keyId === "all") { + // Should not happen if 'enabled' works correctly, but good failsafe + return Promise.reject( + new Error("No specific API key ID provided for usage stats."), + ); + } + return apiClients.stores + .getApiKeyUsage(keyId, payload) // Pass keyId and payload + .then((res) => res.data); + }, + enabled: isEnabled, // Use the calculated enabled state + // Optional: Add placeholderData or staleTime if desired + // placeholderData: (previousData) => previousData, + // staleTime: 5 * 60 * 1000, // 5 minutes }); } diff --git a/web/src/index.css b/web/src/index.css index 88aad27..340d90c 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -2,4 +2,10 @@ @plugin "flowbite-react/plugin/tailwindcss"; @source "../.flowbite-react/class-list.json"; +@layer base { + body { + @apply bg-gray-50 dark:bg-gray-900; + } +} + @custom-variant dark (&:where(.dark, .dark *)); diff --git a/web/src/pages/StoreDashboard/ApiKeyManagement.tsx b/web/src/pages/StoreDashboard/ApiKeyManagement.tsx index 80240b2..7700535 100644 --- a/web/src/pages/StoreDashboard/ApiKeyManagement.tsx +++ b/web/src/pages/StoreDashboard/ApiKeyManagement.tsx @@ -215,11 +215,13 @@ export function ApiKeyManagement() {
- Name - Prefix - Status - Created At - Actions + + Name + Prefix + Status + Created At + Actions + {apiKeysData.map((key) => ( diff --git a/web/src/pages/StoreDashboard/ApiUsageDashboard.tsx b/web/src/pages/StoreDashboard/ApiUsageDashboard.tsx index c512178..03d5409 100644 --- a/web/src/pages/StoreDashboard/ApiUsageDashboard.tsx +++ b/web/src/pages/StoreDashboard/ApiUsageDashboard.tsx @@ -86,7 +86,8 @@ export function ApiUsageDashboard() { data: usageStats, isLoading: usageStatsLoading, error: usageStatsError, - } = useApiKeyUsage(usageFilters.keyId || "all", { + } = useApiKeyUsage(usageFilters.keyId, { + // Pass usageFilters.keyId directly (can be undefined) startDate: usageFilters.startDate, endDate: usageFilters.endDate, }); @@ -167,8 +168,12 @@ export function ApiUsageDashboard() { + value={ + usageFilters.startDate + ? new Date(usageFilters.startDate) + : undefined + } + onChange={(date: Date | null) => handleFilterChange("startDate", date) } maxDate={ @@ -183,8 +188,13 @@ export function ApiUsageDashboard() { + // Convert string back to Date for the component's value prop + value={ + usageFilters.endDate + ? new Date(usageFilters.endDate) + : undefined + } + onChange={(date: Date | null) => handleFilterChange("endDate", date) } minDate={ @@ -202,19 +212,28 @@ export function ApiUsageDashboard() {

Usage Statistics

+ {/* Show loading spinner ONLY if the query is actually running */} {usageStatsLoading ? (
- ) : usageStatsError ? ( + ) : usageStatsError ? ( // Show error if the query failed Failed to load usage statistics: {usageStatsError.message} - ) : !usageStats || usageStats.totalRequests === 0 ? ( + ) : // Add a specific check for when no key is selected (stats are undefined but not loading/error) + !usageFilters.keyId ? ( +

+ Select an API key from the filter above to view its usage + statistics. +

+ ) : // Original check for no data *after* a key was selected and the query ran + !usageStats || usageStats.totalRequests === 0 ? (

- No usage data found for the selected filters. + No usage data found for the selected key and date range.

) : ( + // Render the stats and charts only when data is available

Total Requests:{" "} @@ -272,7 +291,7 @@ export function ApiUsageDashboard() { } > {Object.entries(usageStats.methodBreakdown).map( - (entry, index) => ( + (_, index) => ( - {/* Detailed Log Section */} + {/* Detailed Log Section (Should be okay as is) */}

Detailed Request Log @@ -314,11 +333,13 @@ export function ApiUsageDashboard() { >

- Timestamp - Method - Endpoint - Key Prefix - User Agent + + Timestamp + Method + Endpoint + Key Prefix + User Agent + {usageLogData.logs.map((log) => (