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({ enabled: !!getCookie("auth-token"), retry: false, staleTime: 10 * 60 * 1000, }), ); const customerQuery = useQuery( api.customers.getByUserId.queryOptions({ input: { id: authQuery.data?.id ?? "" }, enabled: !!authQuery.data?.id, retry: false, staleTime: 10 * 60 * 1000, refetchOnWindowFocus: false, }), ); useEffect(() => { console.log({ user: authQuery.data, customer: customerQuery.data, isCustomer: !!customerQuery.data, isUserPending: authQuery.isPending, isCustomerPending: customerQuery.isPending, }); }, [authQuery, customerQuery]); const hasToken = !!getCookie("auth-token"); const isPending = authQuery.isPending && hasToken; const login = async ( payload: LoginPayload, ): Promise> => { 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> => { 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> => { 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> => { 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> => { 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> => { 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(); window.location.href = "/login"; }; return { isPending, user: authQuery.data ?? null, customer: customerQuery.data ?? null, login, signup, setPassword, verifyOTP, sendOTP, generateVerificationCode, logout, authQuery, customerQuery, }; }; export default useAuth;