Skip to content

Commit e3bf333

Browse files
authored
Merge pull request #163 from Zindiks/claude/create-axios-instance-01BFGrTbNNDa6GWTCRngqfvG
Create centralized Axios instance for API requests
2 parents af36953 + a160582 commit e3bf333

21 files changed

+266
-445
lines changed

client/.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# API Configuration
2+
# The base URL for API requests will be: {VITE_API_HOST}:{VITE_API_PORT}{VITE_API_VERSION}
3+
# Example: http://localhost:4000/api/v1
4+
15
VITE_API_HOST=http://localhost
26
VITE_API_PORT=4000
37
VITE_API_VERSION=/api/v1

client/src/hooks/useActivities.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { useQuery } from "@tanstack/react-query";
2-
import axios from "axios";
2+
import apiClient from "@/lib/axios";
33
import type { Activity, ActivityActionType } from "@/types/types";
44

5-
const API_HOST = import.meta.env.VITE_API_HOST;
6-
const API_PORT = import.meta.env.VITE_API_PORT;
7-
const API_VERSION = import.meta.env.VITE_API_VERSION;
8-
9-
const API_URL = `${API_HOST}:${API_PORT}${API_VERSION}`;
10-
115
export interface ActivityFilters {
126
action_type?: ActivityActionType;
137
user_id?: string;
@@ -39,9 +33,9 @@ export const useActivities = (cardId?: string, filters?: ActivityFilters) => {
3933
if (filters?.offset) params.append("offset", filters.offset.toString());
4034

4135
const queryString = params.toString();
42-
const url = `${API_URL}/activities/card/${cardId}${queryString ? `?${queryString}` : ""}`;
36+
const url = `/activities/card/${cardId}${queryString ? `?${queryString}` : ""}`;
4337

44-
const response = await axios.get(url);
38+
const response = await apiClient.get(url);
4539
return response.data;
4640
},
4741
enabled: !!cardId,

client/src/hooks/useAnalytics.ts

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
import { useQuery } from "@tanstack/react-query";
2-
import axios from "axios";
2+
import apiClient from "@/lib/axios";
33
import {
44
ProductivityTrend,
55
BoardOverview,
66
WeeklyMetrics,
77
MonthlyMetrics,
88
} from "../types/types";
99

10-
const API_HOST = import.meta.env.VITE_API_HOST;
11-
const API_PORT = import.meta.env.VITE_API_PORT;
12-
const API_VERSION = import.meta.env.VITE_API_VERSION;
13-
14-
const API_URL = `${API_HOST}:${API_PORT}${API_VERSION}`;
15-
1610
export interface PersonalStats {
1711
assignedCards: number;
1812
completedCards: number;
@@ -133,11 +127,10 @@ export const usePersonalDashboard = (organizationId: string | null) => {
133127
return useQuery<PersonalDashboard>({
134128
queryKey: ["dashboard", "personal", organizationId],
135129
queryFn: async () => {
136-
const { data } = await axios.get(
137-
`${API_URL}/api/v1/analytics/dashboard/personal`,
130+
const { data } = await apiClient.get(
131+
`/analytics/dashboard/personal`,
138132
{
139133
params: { organizationId },
140-
withCredentials: true,
141134
}
142135
);
143136
return data;
@@ -151,9 +144,8 @@ export const useBoardAnalytics = (boardId: string | null) => {
151144
return useQuery<BoardAnalytics>({
152145
queryKey: ["analytics", "board", boardId],
153146
queryFn: async () => {
154-
const { data } = await axios.get(
155-
`${API_URL}/api/v1/analytics/board/${boardId}`,
156-
{ withCredentials: true }
147+
const { data } = await apiClient.get(
148+
`/analytics/board/${boardId}`
157149
);
158150
return data;
159151
},
@@ -166,9 +158,8 @@ export const useSprintBurndown = (sprintId: string | null) => {
166158
return useQuery<SprintBurndown>({
167159
queryKey: ["analytics", "sprint", sprintId, "burndown"],
168160
queryFn: async () => {
169-
const { data } = await axios.get(
170-
`${API_URL}/api/v1/analytics/sprint/${sprintId}/burndown`,
171-
{ withCredentials: true }
161+
const { data } = await apiClient.get(
162+
`/analytics/sprint/${sprintId}/burndown`
172163
);
173164
return data;
174165
},
@@ -181,9 +172,8 @@ export const useBoardVelocity = (boardId: string | null) => {
181172
return useQuery<VelocityMetric[]>({
182173
queryKey: ["analytics", "board", boardId, "velocity"],
183174
queryFn: async () => {
184-
const { data } = await axios.get(
185-
`${API_URL}/api/v1/analytics/board/${boardId}/velocity`,
186-
{ withCredentials: true }
175+
const { data } = await apiClient.get(
176+
`/analytics/board/${boardId}/velocity`
187177
);
188178
return data;
189179
},
@@ -196,11 +186,10 @@ export const useAssignedTasks = (organizationId: string | null) => {
196186
return useQuery<AssignedTask[]>({
197187
queryKey: ["analytics", "tasks", "assigned", organizationId],
198188
queryFn: async () => {
199-
const { data } = await axios.get(
200-
`${API_URL}/api/v1/analytics/tasks/assigned`,
189+
const { data } = await apiClient.get(
190+
`/analytics/tasks/assigned`,
201191
{
202192
params: { organizationId },
203-
withCredentials: true,
204193
}
205194
);
206195
return data;
@@ -214,9 +203,8 @@ export const useDueDateAnalytics = (boardId: string | null) => {
214203
return useQuery<DueDateAnalytics>({
215204
queryKey: ["analytics", "board", boardId, "due-dates"],
216205
queryFn: async () => {
217-
const { data } = await axios.get(
218-
`${API_URL}/api/v1/analytics/board/${boardId}/due-dates`,
219-
{ withCredentials: true }
206+
const { data } = await apiClient.get(
207+
`/analytics/board/${boardId}/due-dates`
220208
);
221209
return data;
222210
},
@@ -233,11 +221,10 @@ export const useProductivityTrends = (
233221
return useQuery<ProductivityTrend>({
234222
queryKey: ["analytics", "trends", "personal", organizationId, period, daysBack],
235223
queryFn: async () => {
236-
const { data } = await axios.get(
237-
`${API_URL}/api/v1/analytics/trends/personal`,
224+
const { data } = await apiClient.get(
225+
`/analytics/trends/personal`,
238226
{
239227
params: { organizationId, period, daysBack },
240-
withCredentials: true,
241228
}
242229
);
243230
return data;
@@ -251,11 +238,10 @@ export const useBoardsOverview = (organizationId: string | null) => {
251238
return useQuery<BoardOverview[]>({
252239
queryKey: ["analytics", "boards", "overview", organizationId],
253240
queryFn: async () => {
254-
const { data } = await axios.get(
255-
`${API_URL}/api/v1/analytics/boards/overview`,
241+
const { data } = await apiClient.get(
242+
`/analytics/boards/overview`,
256243
{
257244
params: { organizationId },
258-
withCredentials: true,
259245
}
260246
);
261247
return data;
@@ -272,11 +258,10 @@ export const useWeeklyMetrics = (
272258
return useQuery<WeeklyMetrics[]>({
273259
queryKey: ["analytics", "metrics", "weekly", organizationId, weeksBack],
274260
queryFn: async () => {
275-
const { data } = await axios.get(
276-
`${API_URL}/api/v1/analytics/metrics/weekly`,
261+
const { data } = await apiClient.get(
262+
`/analytics/metrics/weekly`,
277263
{
278264
params: { organizationId, weeksBack },
279-
withCredentials: true,
280265
}
281266
);
282267
return data;
@@ -293,11 +278,10 @@ export const useMonthlyMetrics = (
293278
return useQuery<MonthlyMetrics[]>({
294279
queryKey: ["analytics", "metrics", "monthly", organizationId, monthsBack],
295280
queryFn: async () => {
296-
const { data } = await axios.get(
297-
`${API_URL}/api/v1/analytics/metrics/monthly`,
281+
const { data } = await apiClient.get(
282+
`/analytics/metrics/monthly`,
298283
{
299284
params: { organizationId, monthsBack },
300-
withCredentials: true,
301285
}
302286
);
303287
return data;

client/src/hooks/useAssignees.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
2-
import axios, { AxiosResponse } from "axios";
2+
import { AxiosResponse } from "axios";
3+
import apiClient from "@/lib/axios";
34
import { useToast } from "@/hooks/use-toast";
45
import type { Assignee } from "@/types/types";
56

6-
const API_HOST = import.meta.env.VITE_API_HOST;
7-
const API_PORT = import.meta.env.VITE_API_PORT;
8-
const API_VERSION = import.meta.env.VITE_API_VERSION;
9-
10-
const API_URL = `${API_HOST}:${API_PORT}${API_VERSION}`;
11-
127
export interface AddAssigneeParams {
138
card_id: string;
149
user_id: string;
@@ -37,7 +32,7 @@ export const useAssignees = (cardId?: string) => {
3732
queryKey: ["assignees", cardId],
3833
queryFn: async () => {
3934
if (!cardId) throw new Error("Card ID is required");
40-
const response = await axios.get(`${API_URL}/assignees/card/${cardId}`);
35+
const response = await apiClient.get(`/assignees/card/${cardId}`);
4136
return response.data;
4237
},
4338
enabled: !!cardId,
@@ -46,14 +41,9 @@ export const useAssignees = (cardId?: string) => {
4641
// Add assignee to card
4742
const addAssignee = useMutation<AxiosResponse, FetchError, AddAssigneeParams>({
4843
mutationFn: (params) => {
49-
return axios.post(
50-
`${API_URL}/assignees/`,
51-
JSON.stringify(params),
52-
{
53-
headers: {
54-
"Content-Type": "application/json",
55-
},
56-
}
44+
return apiClient.post(
45+
`/assignees/`,
46+
params
5747
);
5848
},
5949
onMutate: async (params) => {
@@ -90,7 +80,7 @@ export const useAssignees = (cardId?: string) => {
9080
// Remove assignee from card
9181
const removeAssignee = useMutation<AxiosResponse, FetchError, RemoveAssigneeParams>({
9282
mutationFn: ({ card_id, user_id }) => {
93-
return axios.delete(`${API_URL}/assignees/${card_id}/user/${user_id}`);
83+
return apiClient.delete(`/assignees/${card_id}/user/${user_id}`);
9484
},
9585
onMutate: async (params) => {
9686
// Cancel outgoing refetches

client/src/hooks/useAttachments.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
2-
import axios, { AxiosResponse } from "axios";
2+
import { AxiosResponse } from "axios";
3+
import apiClient from "@/lib/axios";
34
import { useToast } from "@/hooks/use-toast";
45
import type { Attachment } from "@/types/types";
56

6-
const API_HOST = import.meta.env.VITE_API_HOST;
7-
const API_PORT = import.meta.env.VITE_API_PORT;
8-
const API_VERSION = import.meta.env.VITE_API_VERSION;
9-
10-
const API_URL = `${API_HOST}:${API_PORT}${API_VERSION}`;
11-
127
export interface UploadAttachmentParams {
138
card_id: string;
149
file: File;
@@ -43,7 +38,7 @@ export const useAttachments = (cardId?: string) => {
4338
queryKey: ["attachments", cardId],
4439
queryFn: async () => {
4540
if (!cardId) throw new Error("Card ID is required");
46-
const response = await axios.get(`${API_URL}/attachments/card/${cardId}`);
41+
const response = await apiClient.get(`/attachments/card/${cardId}`);
4742
return response.data;
4843
},
4944
enabled: !!cardId,
@@ -55,8 +50,8 @@ export const useAttachments = (cardId?: string) => {
5550
const formData = new FormData();
5651
formData.append("file", file);
5752

58-
return axios.post(
59-
`${API_URL}/attachments/card/${card_id}`,
53+
return apiClient.post(
54+
`/attachments/card/${card_id}`,
6055
formData,
6156
{
6257
headers: {
@@ -88,7 +83,7 @@ export const useAttachments = (cardId?: string) => {
8883
// Delete attachment
8984
const deleteAttachment = useMutation<AxiosResponse, FetchError, DeleteAttachmentParams>({
9085
mutationFn: ({ id, card_id }) => {
91-
return axios.delete(`${API_URL}/attachments/${id}/card/${card_id}`);
86+
return apiClient.delete(`/attachments/${id}/card/${card_id}`);
9287
},
9388
onMutate: async (params) => {
9489
// Cancel outgoing refetches
@@ -131,14 +126,9 @@ export const useAttachments = (cardId?: string) => {
131126
// Update attachment (rename)
132127
const updateAttachment = useMutation<AxiosResponse, FetchError, UpdateAttachmentParams>({
133128
mutationFn: ({ id, card_id, filename }) => {
134-
return axios.patch(
135-
`${API_URL}/attachments/`,
136-
JSON.stringify({ id, card_id, filename }),
137-
{
138-
headers: {
139-
"Content-Type": "application/json",
140-
},
141-
}
129+
return apiClient.patch(
130+
`/attachments/`,
131+
{ id, card_id, filename }
142132
);
143133
},
144134
onMutate: async (params) => {
@@ -185,7 +175,7 @@ export const useAttachments = (cardId?: string) => {
185175
const downloadAttachment = (attachmentId: string, filename: string) => {
186176
if (!cardId) return;
187177

188-
const downloadUrl = `${API_URL}/attachments/${attachmentId}/card/${cardId}/download`;
178+
const downloadUrl = `/attachments/${attachmentId}/card/${cardId}/download`;
189179

190180
// Create a temporary link and trigger download
191181
const link = document.createElement("a");

client/src/hooks/useBoards.ts

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
2-
import axios, { AxiosResponse } from "axios";
2+
import { AxiosResponse } from "axios";
3+
import apiClient from "@/lib/axios";
34
import { useToast } from "@/hooks/use-toast";
45
import { Board } from "@/types/types";
56

6-
const API_HOST = import.meta.env.VITE_API_HOST;
7-
const API_PORT = import.meta.env.VITE_API_PORT;
8-
const API_VERSION = import.meta.env.VITE_API_VERSION;
9-
10-
const API_URL = `${API_HOST}:${API_PORT}${API_VERSION}`;
11-
127
export interface CreateBoard {
138
title: string;
149
description: string;
@@ -36,8 +31,8 @@ export const useBoard = (organization_id: string) => {
3631

3732
const fetchBoards = async (organization_id: string) => {
3833
try {
39-
const response = await axios.get(
40-
`${API_URL}/boards/${organization_id}/all`,
34+
const response = await apiClient.get(
35+
`/boards/${organization_id}/all`,
4136
);
4237
return response.data;
4338
} catch (err) {
@@ -47,7 +42,7 @@ export const useBoard = (organization_id: string) => {
4742

4843
const fetchBoard = async (board_id: string) => {
4944
try {
50-
const response = await axios.get(`${API_URL}/boards/${board_id}`);
45+
const response = await apiClient.get(`/boards/${board_id}`);
5146
return response.data;
5247
} catch (error) {
5348
throw new Error(`Error fetching boards: ${error}`);
@@ -72,11 +67,7 @@ export const useBoard = (organization_id: string) => {
7267
mutationFn: (formData) => {
7368
formData.organization_id = organization_id;
7469

75-
return axios.post(`${API_URL}/boards`, JSON.stringify(formData), {
76-
headers: {
77-
"Content-Type": "application/json",
78-
},
79-
});
70+
return apiClient.post(`/boards`, formData);
8071
},
8172

8273
onSuccess: () => {
@@ -96,7 +87,7 @@ export const useBoard = (organization_id: string) => {
9687

9788
const deleteBoard = useMutation<AxiosResponse, FetchError, string>({
9889
mutationFn: (board_id) => {
99-
return axios.delete(`${API_URL}/boards/${board_id}`);
90+
return apiClient.delete(`/boards/${board_id}`);
10091
},
10192

10293
onSuccess: ({ data }) => {
@@ -125,14 +116,9 @@ export const useBoard = (organization_id: string) => {
125116
UpdateBoardTitle
126117
>({
127118
mutationFn: (formData) => {
128-
return axios.put(
129-
`${API_URL}/boards/${formData.id}`,
130-
JSON.stringify(formData),
131-
{
132-
headers: {
133-
"Content-Type": "application/json",
134-
},
135-
},
119+
return apiClient.put(
120+
`/boards/${formData.id}`,
121+
formData,
136122
);
137123
},
138124
onSuccess: () => {

0 commit comments

Comments
 (0)