fix(frontend): Add comprehensive debugging for API connection issues
Enhanced error handling and debugging to diagnose API connection problems. Changes: - Added detailed console logging in API client (client.ts) - Enhanced error display in projects page with troubleshooting steps - Added logging in useProjects hook for better debugging - Display API URL and error details on error screen - Added retry button for easy error recovery This will help diagnose why the backend API (localhost:5167) is not connecting. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,14 @@ export default function ProjectsPage() {
|
|||||||
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
|
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
|
||||||
const { data: projects, isLoading, error } = useProjects();
|
const { data: projects, isLoading, error } = useProjects();
|
||||||
|
|
||||||
|
// Log state for debugging
|
||||||
|
console.log('[ProjectsPage] State:', {
|
||||||
|
isLoading,
|
||||||
|
error,
|
||||||
|
projects,
|
||||||
|
apiUrl: process.env.NEXT_PUBLIC_API_URL,
|
||||||
|
});
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[50vh] items-center justify-center">
|
<div className="flex h-[50vh] items-center justify-center">
|
||||||
@@ -21,11 +29,44 @@ export default function ProjectsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api/v1';
|
||||||
|
|
||||||
|
console.error('[ProjectsPage] Error loading projects:', error);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[50vh] items-center justify-center">
|
<div className="flex h-[50vh] items-center justify-center">
|
||||||
<p className="text-sm text-muted-foreground">
|
<Card className="w-full max-w-md">
|
||||||
Failed to load projects. Please try again later.
|
<CardHeader>
|
||||||
</p>
|
<CardTitle className="text-red-600">Failed to Load Projects</CardTitle>
|
||||||
|
<CardDescription>Unable to connect to the backend API</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<p className="text-sm font-medium">Error Details:</p>
|
||||||
|
<p className="text-sm text-muted-foreground">{errorMessage}</p>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<p className="text-sm font-medium">API URL:</p>
|
||||||
|
<p className="text-sm font-mono text-muted-foreground">{apiUrl}</p>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<p className="text-sm font-medium">Troubleshooting Steps:</p>
|
||||||
|
<ul className="list-disc list-inside text-sm text-muted-foreground space-y-1">
|
||||||
|
<li>Check if the backend server is running</li>
|
||||||
|
<li>Verify the API URL in .env.local</li>
|
||||||
|
<li>Check browser console (F12) for detailed errors</li>
|
||||||
|
<li>Check network tab (F12) for failed requests</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
Retry
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api/v1';
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api/v1';
|
||||||
|
|
||||||
|
// Log API URL for debugging
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
console.log('[API Client] API_URL:', API_URL);
|
||||||
|
console.log('[API Client] NEXT_PUBLIC_API_URL:', process.env.NEXT_PUBLIC_API_URL);
|
||||||
|
}
|
||||||
|
|
||||||
export class ApiError extends Error {
|
export class ApiError extends Error {
|
||||||
constructor(
|
constructor(
|
||||||
public status: number,
|
public status: number,
|
||||||
@@ -14,11 +20,18 @@ export class ApiError extends Error {
|
|||||||
async function handleResponse<T>(response: Response): Promise<T> {
|
async function handleResponse<T>(response: Response): Promise<T> {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json().catch(() => ({}));
|
const errorData = await response.json().catch(() => ({}));
|
||||||
throw new ApiError(
|
const error = new ApiError(
|
||||||
response.status,
|
response.status,
|
||||||
errorData.message || response.statusText,
|
errorData.message || response.statusText,
|
||||||
errorData
|
errorData
|
||||||
);
|
);
|
||||||
|
console.error('[API Client] Request failed:', {
|
||||||
|
url: response.url,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
errorData,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
@@ -34,6 +47,12 @@ export async function apiRequest<T>(
|
|||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const url = `${API_URL}${endpoint}`;
|
const url = `${API_URL}${endpoint}`;
|
||||||
|
|
||||||
|
console.log('[API Client] Request:', {
|
||||||
|
method: options.method || 'GET',
|
||||||
|
url,
|
||||||
|
endpoint,
|
||||||
|
});
|
||||||
|
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
};
|
};
|
||||||
@@ -56,8 +75,23 @@ export async function apiRequest<T>(
|
|||||||
headers,
|
headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(url, config);
|
try {
|
||||||
return handleResponse<T>(response);
|
const response = await fetch(url, config);
|
||||||
|
const result = await handleResponse<T>(response);
|
||||||
|
console.log('[API Client] Response:', {
|
||||||
|
url,
|
||||||
|
status: response.status,
|
||||||
|
data: result,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[API Client] Network error:', {
|
||||||
|
url,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
errorObject: error,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
|
|||||||
@@ -5,8 +5,19 @@ import type { Project, CreateProjectDto, UpdateProjectDto } from '@/types/projec
|
|||||||
export function useProjects(page = 1, pageSize = 20) {
|
export function useProjects(page = 1, pageSize = 20) {
|
||||||
return useQuery<Project[]>({
|
return useQuery<Project[]>({
|
||||||
queryKey: ['projects', page, pageSize],
|
queryKey: ['projects', page, pageSize],
|
||||||
queryFn: () => projectsApi.getAll(page, pageSize),
|
queryFn: async () => {
|
||||||
|
console.log('[useProjects] Fetching projects...', { page, pageSize });
|
||||||
|
try {
|
||||||
|
const result = await projectsApi.getAll(page, pageSize);
|
||||||
|
console.log('[useProjects] Fetch successful:', result);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[useProjects] Fetch failed:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
},
|
||||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||||
|
retry: 1, // Only retry once to fail faster
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user