Files
latosa-escrima/frontend/hooks/use-api.tsx

110 lines
2.5 KiB
TypeScript

"use client";
import { API_URL } from "@/lib/constants";
import { getCookie } from "cookies-next";
import useSWR, { SWRConfiguration } from "swr";
import useSWRMutation, { type SWRMutationConfiguration } from "swr/mutation";
export interface ApiResponse<T> {
status: "Error" | "Success";
message: string;
data?: T;
}
async function request<T>(
url: string,
options: {
method?: "GET" | "POST" | "PATCH" | "DELETE";
body?: any;
requiresAuth?: boolean;
} = {},
): Promise<ApiResponse<T>> {
const { method = "GET", body, requiresAuth = true } = options;
const headers: Record<string, string> = {
"Content-Type": "application/json",
};
if (requiresAuth) {
const authToken = getCookie("auth_token");
if (!authToken) {
throw new Error("User is not authenticated");
}
headers.Authorization = `Bearer ${authToken}`;
}
const response = await fetch(`${API_URL}${url}`, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
});
const apiResponse: ApiResponse<T> = await response.json();
if (apiResponse.status === "Error") {
throw new Error(apiResponse.message || "An unexpected error occurred");
}
return apiResponse;
}
async function fetcher<T>(
url: string,
requiresAuth: boolean = true,
): Promise<ApiResponse<T>> {
return request(url, { requiresAuth });
}
async function mutationHandler<T, A>(
url: string,
{
arg,
method,
requiresAuth,
}: {
arg: A;
method: "GET" | "POST" | "PATCH" | "DELETE";
requiresAuth: boolean;
},
): Promise<ApiResponse<T>> {
return request(url, { method, body: arg, requiresAuth });
}
export function useApi<T>(
url: string,
config?: SWRConfiguration,
requiresAuth: boolean = true,
) {
const swr = useSWR<ApiResponse<T>>(
url,
() => fetcher(url, requiresAuth),
config,
);
return {
...swr,
data: swr.data?.data,
isLoading: swr.isLoading || swr.isValidating,
success: swr.data?.status === "Success",
};
}
export default function useApiMutation<T, A>(
endpoint: string,
config?: SWRMutationConfiguration<ApiResponse<T>, Error, string, A>,
method: "GET" | "POST" | "PATCH" | "DELETE" = "GET",
requiresAuth: boolean = false,
) {
const mutation = useSWRMutation<ApiResponse<T>, Error, string, A>(
endpoint,
(url, { arg }) => mutationHandler(url, { arg, method, requiresAuth }),
config,
);
return {
...mutation,
trigger: mutation.trigger as (
arg: A,
) => Promise<ApiResponse<T> | undefined>,
data: mutation.data?.data,
isSuccess: mutation.data?.status === "Success",
};
}