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>
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { projectsApi } from '@/lib/api/projects';
|
|
import type { Project, CreateProjectDto, UpdateProjectDto } from '@/types/project';
|
|
|
|
export function useProjects(page = 1, pageSize = 20) {
|
|
return useQuery<Project[]>({
|
|
queryKey: ['projects', 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
|
|
retry: 1, // Only retry once to fail faster
|
|
});
|
|
}
|
|
|
|
export function useProject(id: string) {
|
|
return useQuery<Project>({
|
|
queryKey: ['projects', id],
|
|
queryFn: () => projectsApi.getById(id),
|
|
enabled: !!id,
|
|
});
|
|
}
|
|
|
|
export function useCreateProject() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: CreateProjectDto) => projectsApi.create(data),
|
|
onSuccess: (newProject) => {
|
|
// Invalidate and refetch projects list
|
|
queryClient.invalidateQueries({ queryKey: ['projects'] });
|
|
|
|
// Optimistically update cache
|
|
queryClient.setQueryData<Project[]>(['projects'], (old) =>
|
|
old ? [...old, newProject] : [newProject]
|
|
);
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateProject(id: string) {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: UpdateProjectDto) => projectsApi.update(id, data),
|
|
onMutate: async (updatedData) => {
|
|
// Optimistic update
|
|
await queryClient.cancelQueries({ queryKey: ['projects', id] });
|
|
|
|
const previousProject = queryClient.getQueryData<Project>(['projects', id]);
|
|
|
|
queryClient.setQueryData<Project>(['projects', id], (old) => ({
|
|
...old!,
|
|
...updatedData,
|
|
}));
|
|
|
|
return { previousProject };
|
|
},
|
|
onError: (err, variables, context) => {
|
|
// Rollback on error
|
|
if (context?.previousProject) {
|
|
queryClient.setQueryData(['projects', id], context.previousProject);
|
|
}
|
|
},
|
|
onSettled: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['projects', id] });
|
|
queryClient.invalidateQueries({ queryKey: ['projects'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteProject() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (id: string) => projectsApi.delete(id),
|
|
onSuccess: (_, id) => {
|
|
queryClient.invalidateQueries({ queryKey: ['projects'] });
|
|
queryClient.removeQueries({ queryKey: ['projects', id] });
|
|
},
|
|
});
|
|
}
|