"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 { status: "Error" | "Success"; message: string; data?: T; } async function request( url: string, options: { method?: "GET" | "POST" | "PATCH" | "DELETE"; body?: any; requiresAuth?: boolean; } = {}, ): Promise> { const { method = "GET", body, requiresAuth = true } = options; const headers: Record = { "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 = await response.json(); if (apiResponse.status === "Error") { throw new Error(apiResponse.message || "An unexpected error occurred"); } return apiResponse; } async function fetcher( url: string, requiresAuth: boolean = true, ): Promise> { return request(url, { requiresAuth }); } async function mutationHandler( url: string, { arg, method, requiresAuth, }: { arg: A; method: "GET" | "POST" | "PATCH" | "DELETE"; requiresAuth: boolean; }, ): Promise> { return request(url, { method, body: arg, requiresAuth }); } export function useApi( url: string, config?: SWRConfiguration, requiresAuth: boolean = true, ) { const swr = useSWR>( 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( endpoint: string, config?: SWRMutationConfiguration, Error, string, A>, method: "GET" | "POST" | "PATCH" | "DELETE" = "GET", requiresAuth: boolean = false, ) { const mutation = useSWRMutation, Error, string, A>( endpoint, (url, { arg }) => mutationHandler(url, { arg, method, requiresAuth }), config, ); return { ...mutation, trigger: mutation.trigger as ( arg: A, ) => Promise | undefined>, data: mutation.data?.data, isSuccess: mutation.data?.status === "Success", }; }