diff --git a/my-app/app/admin/dashboard/page.tsx b/my-app/app/admin/dashboard/page.tsx index 384822e..6507245 100644 --- a/my-app/app/admin/dashboard/page.tsx +++ b/my-app/app/admin/dashboard/page.tsx @@ -12,11 +12,14 @@ import { NodeResources } from "@/app/admin/dashboard/node-resources" import { DashboardQuickActions } from "@/components/dashboard/dashboard-quick-actions" import { Button } from "@/components/ui/button" import { RefreshCw } from "lucide-react" +import { useAuth } from "@/contexts/auth-context" export default function AdminDashboardPage() { + const { authState } = useAuth() // Fetch unified dashboard data const { data: dashboardData, loading, error, refetch } = useApiState({ fetchFn: getDashboardData, + enabled: authState.authenticated === true && authState.isAdmin === true, deps: [] }) diff --git a/my-app/app/creator/dashboard/page.tsx b/my-app/app/creator/dashboard/page.tsx index 4b195af..b0c80da 100644 --- a/my-app/app/creator/dashboard/page.tsx +++ b/my-app/app/creator/dashboard/page.tsx @@ -10,14 +10,21 @@ import { ErrorDisplay } from "@/components/ui/error-display"; import { Copy, CopyPlusIcon, Edit } from "lucide-react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; +import { useAuth } from "@/contexts/auth-context"; export default function CreatorDashboardPage() { + const { authState } = useAuth(); + const creatorOrAdmin = + authState.authenticated === true && + (authState.isCreator === true || authState.isAdmin === true); + const { data: templates, loading: templatesLoading, error: templatesError, } = useApiState({ fetchFn: getAllPodTemplates, + enabled: creatorOrAdmin, }); const { @@ -26,6 +33,7 @@ export default function CreatorDashboardPage() { error: unpublishedError, } = useApiState({ fetchFn: getUnpublishedTemplates, + enabled: creatorOrAdmin, }); const publishedCount = templates?.length || 0; diff --git a/my-app/app/page.tsx b/my-app/app/page.tsx index dae5e97..d32f3b2 100644 --- a/my-app/app/page.tsx +++ b/my-app/app/page.tsx @@ -42,6 +42,7 @@ export default function Page() { error: dashboardError, } = useApiState({ fetchFn: getUserDashboard, + enabled: authState.authenticated === true, }); // Extract data from the unified response diff --git a/my-app/app/pods/deployed/page.tsx b/my-app/app/pods/deployed/page.tsx index 687354a..d3173af 100644 --- a/my-app/app/pods/deployed/page.tsx +++ b/my-app/app/pods/deployed/page.tsx @@ -10,6 +10,7 @@ import { useApiState } from "@/hooks/use-api-state" import { deletePod, getDeployedPods } from "@/lib/api" import { DeployedPod } from "@/lib/types" import { SectionCards } from "@/app/pods/deployed/deployed-pods-cards" +import { useAuth } from "@/contexts/auth-context" import { AlertDialog, AlertDialogAction, @@ -23,8 +24,10 @@ import { export default function Page() { const [alertOpen, setAlertOpen] = useState(false) const [selectedPod, setSelectedPod] = useState(null) + const { authState } = useAuth() const { data: pods, loading, error } = useApiState({ fetchFn: getDeployedPods, + enabled: authState.authenticated === true, }) const handleDeleteClick = (pod: DeployedPod) => { diff --git a/my-app/app/pods/templates/page.tsx b/my-app/app/pods/templates/page.tsx index 7206a47..9fcd066 100644 --- a/my-app/app/pods/templates/page.tsx +++ b/my-app/app/pods/templates/page.tsx @@ -9,12 +9,15 @@ import { SectionCards } from "@/app/pods/templates/pod-templates-cards" import { getPodTemplates } from "@/lib/api" import { PodDeployDialog } from "@/components/pod-deploy-dialog" import { usePodDeployment } from "@/hooks/use-pod-deployment" +import { useAuth } from "@/contexts/auth-context" export default function Page() { const { isDialogOpen, selectedPod, openDeployDialog, closeDeployDialog } = usePodDeployment() - + const { authState } = useAuth() + const { data: pods, loading, error } = useApiState({ fetchFn: getPodTemplates, + enabled: authState.authenticated === true, }) const pageHeader = ( diff --git a/my-app/contexts/auth-context.tsx b/my-app/contexts/auth-context.tsx index 92c6f0a..ccfb587 100644 --- a/my-app/contexts/auth-context.tsx +++ b/my-app/contexts/auth-context.tsx @@ -8,6 +8,7 @@ import { useEffect, useCallback, } from "react"; +import { clearRequestCache } from "@/lib/api"; interface SessionData { authenticated: boolean; @@ -110,6 +111,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { // Clear cache to force fresh request sessionCache = null; sessionPromise = null; + clearRequestCache(); setAuthState((prev) => ({ ...prev, loading: true })); await checkSession(); }, [checkSession]); @@ -120,6 +122,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { // Clear cache and update state sessionCache = null; sessionPromise = null; + clearRequestCache(); setAuthState({ authenticated: false, loading: false, diff --git a/my-app/hooks/use-api-state.ts b/my-app/hooks/use-api-state.ts index d4a9491..dad6c0c 100644 --- a/my-app/hooks/use-api-state.ts +++ b/my-app/hooks/use-api-state.ts @@ -3,6 +3,7 @@ import { useEffect, useState } from "react" interface UseApiStateOptions { fetchFn: () => Promise deps?: React.DependencyList + enabled?: boolean } interface UseApiStateReturn { @@ -12,7 +13,7 @@ interface UseApiStateReturn { refetch: () => void } -export function useApiState({ fetchFn, deps = [] }: UseApiStateOptions): UseApiStateReturn { +export function useApiState({ fetchFn, deps = [], enabled = true }: UseApiStateOptions): UseApiStateReturn { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) @@ -31,6 +32,10 @@ export function useApiState({ fetchFn, deps = [] }: UseApiStateOptions): U } useEffect(() => { + if (!enabled) { + setLoading(true) + return + } fetchData() }, deps) diff --git a/my-app/lib/api.ts b/my-app/lib/api.ts index 79a8381..5a840f0 100644 --- a/my-app/lib/api.ts +++ b/my-app/lib/api.ts @@ -23,6 +23,11 @@ const requestCache = new Map< >(); const CACHE_DURATION = 5000; // 5 seconds for deduplication +// Clear all cached/in-flight requests +export function clearRequestCache(): void { + requestCache.clear(); +} + // Helper function to handle request deduplication async function deduplicatedFetch( key: string, @@ -49,8 +54,15 @@ async function deduplicatedFetch( // Cache the promise requestCache.set(key, { promise, timestamp: now }); + promise.catch(() => { + const entry = requestCache.get(key); + if (entry && entry.timestamp === now) { + requestCache.delete(key); + } + }); + // Clean up cache after completion - promise.finally(() => { + promise.then(() => { setTimeout(() => { const entry = requestCache.get(key); if (entry && entry.timestamp === now) {