fixed some bugs

This commit is contained in:
Jelaletdin12
2025-12-18 23:19:45 +05:00
parent 6d0064b106
commit 0fb4e2765c
36 changed files with 1430 additions and 1485 deletions

View File

@@ -1,6 +1,10 @@
// lib/hooks/useAuth.ts
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useState, useEffect } from "react";
import { apiClient, setAuthToken, clearAuthToken, setGuestToken } from "@/lib/api";
import { apiClient } from "@/lib/api";
import TokenStorage from "@/lib/tokenStorage";
import { AxiosError } from "axios";
// ==================== TYPES ====================
interface LoginCredentials {
@@ -30,59 +34,131 @@ interface AuthResponse {
};
}
// ==================== AUTH STATUS ====================
const getTokenFromCookie = (name: string): string | null => {
if (typeof document === "undefined") return null;
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop()?.split(";").shift() || null;
return null;
};
interface AuthError {
message: string;
code?: string;
statusCode?: number;
}
// ==================== UTILITIES ====================
function extractToken(data: AuthResponse): string {
// Enforce consistent token extraction
const token = data.token || data.data;
if (!token) {
throw new Error("No token received from server");
}
return token;
}
function handleAuthError(error: unknown): AuthError {
if (error instanceof AxiosError) {
if (error.code === 'ECONNABORTED') {
return {
message: "Request timeout - server not responding",
code: "TIMEOUT",
statusCode: 408
};
}
if (error.response) {
return {
message: error.response.data?.message || "Authentication failed",
code: error.response.data?.code || "AUTH_ERROR",
statusCode: error.response.status
};
}
if (error.request) {
return {
message: "Network error - cannot reach server",
code: "NETWORK_ERROR",
statusCode: 0
};
}
}
return {
message: error instanceof Error ? error.message : "Unknown error occurred",
code: "UNKNOWN_ERROR"
};
}
// ==================== AUTH STATUS ====================
export function useAuthStatus() {
const [isLoading, setIsLoading] = useState(true);
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
const authToken = getTokenFromCookie("authToken");
setIsAuthenticated(!!authToken);
setIsAuthenticated(TokenStorage.hasAuthToken());
setIsLoading(false);
}, []);
return {
isAuthenticated,
isLoading,
};
return { isAuthenticated, isLoading };
}
// ==================== GUEST TOKEN ====================
export function useGetGuestToken() {
return useMutation({
mutationFn: async (): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>("/auth/guest-token", {});
return response.data;
},
onSuccess: (data) => {
const token = data?.token || data?.data;
if (token) {
setGuestToken(token);
mutationFn: async (): Promise<string> => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
try {
const response = await apiClient.post<AuthResponse>(
"/auth/guest-token",
{},
{
signal: controller.signal,
timeout: 10000
}
);
clearTimeout(timeoutId);
return extractToken(response.data);
} catch (error) {
clearTimeout(timeoutId);
throw handleAuthError(error);
}
},
onError: (error) => {
console.error("Guest token hatası:", error);
onSuccess: (token) => {
TokenStorage.setGuestToken(token);
},
onError: (error: AuthError) => {
console.error("[Guest Token] Failed:", {
message: error.message,
code: error.code,
statusCode: error.statusCode
});
},
retry: (failureCount, error) => {
const authError = error as AuthError;
// Retry on network errors, not on auth errors
if (authError.code === "NETWORK_ERROR" || authError.code === "TIMEOUT") {
return failureCount < 2;
}
return false;
},
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 5000),
});
}
// ==================== LOGIN ====================
export function useLogin() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (credentials: LoginCredentials): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>("/auth/login", credentials);
return response.data;
mutationFn: async (credentials: LoginCredentials): Promise<string> => {
const response = await apiClient.post<AuthResponse>(
"/auth/login",
credentials,
{ timeout: 15000 }
);
return extractToken(response.data);
},
onSuccess: (token) => {
TokenStorage.setAuthToken(token);
queryClient.invalidateQueries({ queryKey: ["auth-status"] });
queryClient.invalidateQueries({ queryKey: ["user-profile"] });
},
onError: (error) => {
console.error("Login hatası:", error);
const authError = handleAuthError(error);
console.error("[Login] Failed:", authError);
},
});
}
@@ -92,19 +168,22 @@ export function useRegister() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (userData: RegisterData): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>("/auth/register", userData);
return response.data;
mutationFn: async (userData: RegisterData): Promise<string> => {
const response = await apiClient.post<AuthResponse>(
"/auth/register",
userData,
{ timeout: 15000 }
);
return extractToken(response.data);
},
onSuccess: (data) => {
const token = data?.token || data?.data;
if (token) {
setAuthToken(token);
queryClient.invalidateQueries({ queryKey: ["auth-status"] });
}
onSuccess: (token) => {
TokenStorage.setAuthToken(token);
queryClient.invalidateQueries({ queryKey: ["auth-status"] });
queryClient.invalidateQueries({ queryKey: ["user-profile"] });
},
onError: (error) => {
console.error("Register hatası:", error);
const authError = handleAuthError(error);
console.error("[Register] Failed:", authError);
},
});
}
@@ -114,19 +193,22 @@ export function useVerifyToken() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (verifyData: VerifyTokenData): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>("/auth/verify", verifyData);
return response.data;
mutationFn: async (verifyData: VerifyTokenData): Promise<string> => {
const response = await apiClient.post<AuthResponse>(
"/auth/verify",
verifyData,
{ timeout: 15000 }
);
return extractToken(response.data);
},
onSuccess: (data) => {
const token = data?.data || data?.token;
if (token) {
setAuthToken(token);
queryClient.invalidateQueries({ queryKey: ["auth-status"] });
}
onSuccess: (token) => {
TokenStorage.setAuthToken(token);
queryClient.invalidateQueries({ queryKey: ["auth-status"] });
queryClient.invalidateQueries({ queryKey: ["user-profile"] });
},
onError: (error) => {
console.error("Verify hatası:", error);
const authError = handleAuthError(error);
console.error("[Verify] Failed:", authError);
},
});
}
@@ -138,23 +220,28 @@ export function useLogout() {
return useMutation({
mutationFn: async (): Promise<void> => {
try {
await apiClient.post("/auth/logout");
await apiClient.post("/auth/logout", {}, { timeout: 5000 });
} catch (error) {
console.warn("Logout endpoint çalışmadı:", error);
// Logout should succeed even if server call fails
console.warn("[Logout] Server call failed, clearing local state anyway");
}
},
onSuccess: () => {
clearAuthToken();
TokenStorage.clearTokens();
queryClient.clear();
if (typeof window !== "undefined") {
window.location.href = "/login";
window.location.href = "/";
}
},
onError: (error) => {
console.error("Logout hatası:", error);
clearAuthToken();
onError: () => {
// Always clear local state on logout
TokenStorage.clearTokens();
queryClient.clear();
if (typeof window !== "undefined") {
window.location.href = "/";
}
},
});
}