diff --git a/client/package.json b/client/package.json index 50fafb35c..7c5acb441 100644 --- a/client/package.json +++ b/client/package.json @@ -43,7 +43,7 @@ "react-toastify": "^10.0.5", "recharts": "2.15.2", "redux-persist": "6.0.0", - "swr": "2.3.6", + "swr": "^2.3.6", "vite-plugin-svgr": "^4.2.0", "zod": "4.1.11" }, diff --git a/client/src/Hooks/UseApi.ts b/client/src/Hooks/UseApi.ts new file mode 100644 index 000000000..06845d6c1 --- /dev/null +++ b/client/src/Hooks/UseApi.ts @@ -0,0 +1,34 @@ +import useSWR from "swr"; +import type { SWRConfiguration } from "swr"; +import type { AxiosRequestConfig } from "axios"; +import { get } from "@/Utils/ApiClient"; + +interface ApiResponse { + success: boolean; + msg: string; + data: T; +} + +const fetcher = async (url: string, config?: AxiosRequestConfig) => { + const res = await get>(url, config); + return res.data; +}; + +export const useGet = ( + url: string | null, + axiosConfig?: AxiosRequestConfig, + swrConfig?: SWRConfiguration +) => { + const { data, error, isLoading, mutate } = useSWR>( + url, + (url: string) => fetcher(url, axiosConfig), + swrConfig + ); + + return { + data: data?.data ?? null, + isLoading, + error, + refetch: mutate, + }; +}; diff --git a/client/src/Types/Monitor.ts b/client/src/Types/Monitor.ts index 05f7d7d6f..e01c9f844 100644 --- a/client/src/Types/Monitor.ts +++ b/client/src/Types/Monitor.ts @@ -1,7 +1,7 @@ import type { Check } from "@/Types/Check"; export type MonitorStatus = "up" | "down" | "initializing"; -export interface IMonitor { +export interface Monitor { checks: Check[]; createdAt: string; createdBy: string; diff --git a/client/src/Utils/ApiClient.ts b/client/src/Utils/ApiClient.ts new file mode 100644 index 000000000..e375b07e7 --- /dev/null +++ b/client/src/Utils/ApiClient.ts @@ -0,0 +1,59 @@ +import axios from "axios"; +import type { AxiosError } from "axios"; +import type { AxiosRequestConfig, AxiosResponse } from "axios"; +import { store } from "@/store"; +const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; + +const api = axios.create({ + baseURL: BASE_URL, +}); + +api.interceptors.request.use( + (config) => { + const authToken = store.getState().auth?.authToken ?? ""; + + config.headers.set("Authorization", `Bearer ${authToken}`); + if (!config.headers.has("Accept-Language")) { + config.headers.set("Accept-Language", "en"); + } + + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +const onSuccess = (response: AxiosResponse) => response; +const onError = (error: AxiosError) => { + if (error.response?.status === 401) { + window.location.href = "/login"; + } + return Promise.reject(error); +}; + +api.interceptors.response.use(onSuccess, onError); + +export const get = ( + url: string, + config: AxiosRequestConfig = {} +): Promise> => api.get(url, config); + +export const post = ( + url: string, + data: unknown, + config: AxiosRequestConfig = {} +): Promise> => api.post(url, data, config); + +export const patch = ( + url: string, + data: unknown, + config: AxiosRequestConfig = {} +): Promise> => api.patch(url, data, config); + +export const deleteOp = ( + url: string, + config: AxiosRequestConfig = {} +): Promise> => api.delete(url, config); + +export default api;