fixed some bugs
This commit is contained in:
@@ -1,23 +1,25 @@
|
||||
export * from "../../features/products/hooks/useProducts"
|
||||
export * from "../../features/category/hooks/useCategories"
|
||||
export * from "../../features/cart/hooks/useCart"
|
||||
export * from "../../features/favorites/hooks/useFavorites"
|
||||
export * from "../../features/orders/hooks/useOrders"
|
||||
export * from "../../features/search/hooks/useSearch"
|
||||
export * from "../../features/profile/hooks/useUserProfile"
|
||||
export * from "../../features/openStore/hooks/useOpenStore"
|
||||
export * from "../../features/products/hooks/useProducts";
|
||||
export * from "../../features/category/hooks/useCategories";
|
||||
export * from "../../features/cart/hooks/useCart";
|
||||
export * from "../../features/favorites/hooks/useFavorites";
|
||||
export * from "../../features/orders/hooks/useOrders";
|
||||
export * from "../../features/search/hooks/useSearch";
|
||||
export * from "../../features/profile/hooks/useUserProfile";
|
||||
export * from "../../features/openStore/hooks/useOpenStore";
|
||||
|
||||
export * from "../../features/cart/hooks/useAddresses"
|
||||
export * from "../../features/cart/hooks/usePaymentTypes"
|
||||
export * from "../../features/cart/hooks/useAddresses";
|
||||
export * from "../../features/cart/hooks/usePaymentTypes";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export * from "../../features/home/hooks/useMedia"
|
||||
export * from "../../features/home/hooks/useCollections"
|
||||
export * from "../../features/home/hooks/useMedia";
|
||||
export * from "../../features/home/hooks/useCollections";
|
||||
|
||||
// Export types
|
||||
export type { Product, Category, Cart, CartItem, Order, Favorite, Banner } from "@/lib/types/api"
|
||||
export type {
|
||||
Product,
|
||||
Category,
|
||||
Cart,
|
||||
CartItem,
|
||||
Order,
|
||||
Favorite,
|
||||
Banner,
|
||||
} from "@/lib/types/api";
|
||||
|
||||
@@ -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 = "/";
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user