Files
edr-platform/apps/edr-freight-web/portal/src/hooks/useAuth.ts
2026-06-06 09:11:30 +03:00

196 lines
5.4 KiB
TypeScript

import { useQuery, useQueryClient } from "@tanstack/react-query";
import { api } from "@/services/api";
import type {
LoginPayload,
LoginResponse,
SignupPayload,
SignupResponse,
OtpResponse,
} from "@/types/auth";
import type { Result } from "@/utils/result";
import { extractApiError } from "@/utils/result";
import { useEffect } from "react";
function setCookie(name: string, value: string, days: number) {
const expires = new Date();
expires.setDate(expires.getDate() + days);
document.cookie = `${name}=${value}; path=/; expires=${expires.toUTCString()}; SameSite=Lax`;
}
function getCookie(name: string): string | undefined {
return document.cookie
.split("; ")
.find((row) => row.startsWith(`${name}=`))
?.split("=")[1];
}
const useAuth = () => {
const queryClient = useQueryClient();
const authQuery = useQuery(
api.auth.getMyInfo.queryOptions({
retry: false,
staleTime: 10 * 60 * 1000,
}),
);
const companyQuery = useQuery(
api.companies.getInfo.queryOptions({
enabled: !!authQuery.data?.id,
retry: false,
staleTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
}),
);
useEffect(() => {
console.log({
user: authQuery.data,
company: companyQuery.data,
isCompany: !!companyQuery.data,
isUserPending: authQuery.isPending,
isCompanyPending: companyQuery.isPending,
});
}, [authQuery, companyQuery]);
const hasToken = !!getCookie("auth-token");
const isPending = authQuery.isPending && hasToken;
const login = async (
payload: LoginPayload,
): Promise<Result<LoginResponse>> => {
try {
const res = await api.auth.login.call(payload);
setCookie("auth-token", res.token, 7);
setCookie("refresh-token", res.refreshToken, 7);
await authQuery.refetch();
return { success: true, data: res };
} catch (err) {
return { success: false, error: extractApiError(err) };
}
};
const signup = async (
payload: SignupPayload,
): Promise<Result<SignupResponse>> => {
try {
const res = await api.auth.createUser.call(payload);
setCookie("auth-token", res.token, 7);
setCookie("refresh-token", res.refreshToken, 7);
await authQuery.refetch();
const otpCode = res.otp?.split(" ")?.[6] ?? "";
localStorage.setItem("otp", otpCode);
localStorage.setItem("otp-phone", payload.phoneNumber);
localStorage.setItem("otp-email", payload.email);
api.auth.sendOTP
.call({ phone: payload.phoneNumber, otp: otpCode })
.catch(() => { });
return { success: true, data: res };
} catch (err) {
return { success: false, error: extractApiError(err) };
}
};
const setPassword = async (data: {
newPassword: string;
confirmPassword: string;
}): Promise<Result<void>> => {
try {
const userId = authQuery.data?.id ?? "";
const email = localStorage.getItem("otp-email") ?? "";
const verificationCode = localStorage.getItem("otp") ?? "";
await api.auth.setPassword.call({
newPassword: data.newPassword,
confirmPassword: data.confirmPassword,
userId,
email,
verificationCode,
});
["userId", "otp", "otp-phone", "otp-email"].forEach((k) =>
localStorage.removeItem(k),
);
await queryClient.invalidateQueries({
queryKey: api.auth.getMyInfo.queryKey(),
});
return { success: true, data: undefined };
} catch (err) {
return { success: false, error: extractApiError(err) };
}
};
const verifyOTP = async (otp: string): Promise<Result<OtpResponse>> => {
try {
const phone = localStorage.getItem("otp-phone") ?? "";
const res = await api.auth.verifyOTP.call({ phone, otp });
return { success: true, data: res };
} catch (err) {
return { success: false, error: extractApiError(err) };
}
};
const sendOTP = async (otp: string): Promise<Result<OtpResponse>> => {
try {
const phone = localStorage.getItem("otp-phone") ?? "";
const res = await api.auth.sendOTP.call({ phone, otp });
return { success: true, data: res };
} catch (err) {
return { success: false, error: extractApiError(err) };
}
};
const generateVerificationCode = async (
type: string,
): Promise<Result<string>> => {
try {
const email = localStorage.getItem("otp-email") ?? "";
const phoneNumber = localStorage.getItem("otp-phone") ?? "";
const res = await api.auth.generateVerificationCode.call({
email,
phoneNumber,
type,
});
return { success: true, data: res };
} catch (err) {
return { success: false, error: extractApiError(err) };
}
};
const logout = async () => {
try {
await api.auth.logout.call();
} catch {
// proceed with client-side cleanup even if server call fails
}
[
"auth-token",
"refresh-token",
"auth-user",
"current-position-id",
"selected-position-id",
].forEach((name) => {
document.cookie = `${name}=; Max-Age=0; path=/`;
});
localStorage.clear();
queryClient.clear();
};
return {
isPending,
user: authQuery.data ?? null,
company: companyQuery.data ?? null,
customer: companyQuery.data ?? null,
login,
signup,
setPassword,
verifyOTP,
sendOTP,
generateVerificationCode,
logout,
authQuery,
companyQuery,
customerQuery: companyQuery,
};
};
export default useAuth;