Added /users/me route, and handling auth in frontend
This commit is contained in:
109
frontend/hooks/use-api.tsx
Normal file
109
frontend/hooks/use-api.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
"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",
|
||||
};
|
||||
}
|
||||
31
frontend/hooks/use-login.tsx
Normal file
31
frontend/hooks/use-login.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import { setCookie } from "cookies-next";
|
||||
import useApiMutation from "./use-api";
|
||||
|
||||
export interface LoginArgs {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export default function useLogin() {
|
||||
const {
|
||||
trigger,
|
||||
isMutating: loading,
|
||||
isSuccess,
|
||||
} = useApiMutation<string, LoginArgs>("/users/login", undefined, "POST");
|
||||
|
||||
const login = async (inputs: LoginArgs) => {
|
||||
try {
|
||||
const res = await trigger(inputs);
|
||||
if (!res) throw new Error("The server hasn't responded.");
|
||||
if (res.status === "Error") throw new Error(res.message);
|
||||
if (res.data) setCookie("auth_token", res.data);
|
||||
return res;
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
return { login, loading, isSuccess };
|
||||
}
|
||||
16
frontend/hooks/use-me.tsx
Normal file
16
frontend/hooks/use-me.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import IUser from "@/interfaces/IUser";
|
||||
import { useApi } from "./use-api";
|
||||
|
||||
export default function useMe() {
|
||||
const {
|
||||
data: user,
|
||||
isLoading,
|
||||
mutate,
|
||||
error,
|
||||
success,
|
||||
} = useApi<IUser>("/users/me", undefined, true);
|
||||
|
||||
return { user, isLoading, success, error, mutate };
|
||||
}
|
||||
Reference in New Issue
Block a user