import { useQuery, useInfiniteQuery } from "@tanstack/react-query"; import { useAuthToken } from "../hooks/use-root-data"; import { createHomepageApi } from "~/utils/api-client-factory"; // Home query keys export const homeKeys = { all: ["home"] as const, banners: () => [...homeKeys.all, "banners"] as const, categories: () => [...homeKeys.all, "categories"] as const, discounts: () => [...homeKeys.all, "discounts"] as const, forYou: () => [...homeKeys.all, "forYou"] as const, topSellers: () => [...homeKeys.all, "topSellers"] as const, sellerTiles: () => [...homeKeys.all, "sellerTiles"] as const, sellerTilesAll: () => [...homeKeys.all, "sellerTilesAll"] as const, }; /** * Hook for fetching home page banners * @returns Query result with home page banners */ export function useGetHomeBanners() { const token = useAuthToken(); return useQuery({ queryKey: homeKeys.banners(), queryFn: async () => { try { console.log("[Home Hooks] Fetching banners - Token:", !!token); const homeApi = createHomepageApi(token); console.log("[Home Hooks] HomepageApi created, making API call..."); const result = await homeApi.apiHomeV1BannersList(); console.log("[Home Hooks] Banners fetched successfully:", result); return result; } catch (error) { console.error("Error fetching home banners:", error); throw error; } }, staleTime: 5 * 60 * 1000, // 5 minutes cache refetchOnWindowFocus: false, }); } /** * Hook for fetching home page discounts with cursor pagination * @returns Infinite query result with home page discounts */ export function useGetHomeDiscounts() { const token = useAuthToken(); return useInfiniteQuery({ queryKey: homeKeys.discounts(), queryFn: async ({ pageParam }) => { try { const homeApi = createHomepageApi(token); // eslint-disable-next-line @typescript-eslint/no-explicit-any const result = await homeApi.apiHomeV1DiscountsList({ cursor: pageParam, pageSize: 20, }); // API returns { next, previous, results } but type says Array // Return the whole response to access 'next' in getNextPageParam return result; } catch (error) { console.error("Error fetching home discounts:", error); throw error; } }, initialPageParam: undefined as string | undefined, getNextPageParam: (lastPage) => { // Extract cursor from next URL if (lastPage?.next) { const url = new URL(lastPage.next); return url.searchParams.get("cursor"); } return undefined; }, staleTime: 60 * 1000, // 60s — prices/discounts must stay reasonably fresh refetchOnWindowFocus: false, }); } /** * Hook for fetching home page "For You" products with infinite scroll * @returns Infinite query result with personalized products */ export function useGetHomeForYou() { const token = useAuthToken(); return useInfiniteQuery({ queryKey: homeKeys.forYou(), queryFn: async ({ pageParam }) => { try { const homeApi = createHomepageApi(token); // eslint-disable-next-line @typescript-eslint/no-explicit-any const result = await homeApi.apiHomeV1ForYouList({ cursor: pageParam, pageSize: 20, }); // API returns { next, previous, results } but type says Array // Return the whole response to access 'next' in getNextPageParam return result; } catch (error) { console.error("Error fetching home 'For You' products:", error); throw error; } }, initialPageParam: undefined as string | undefined, getNextPageParam: (lastPage) => { // Extract cursor from next URL if (lastPage?.next) { const url = new URL(lastPage.next); return url.searchParams.get("cursor"); } return undefined; }, staleTime: 60 * 1000, // 60s — prices/discounts must stay reasonably fresh refetchOnWindowFocus: false, }); } /** * Hook for fetching home page top sellers with cursor pagination * @returns Infinite query result with top selling products */ export function useGetHomeTopSellers() { const token = useAuthToken(); return useInfiniteQuery({ queryKey: homeKeys.topSellers(), queryFn: async ({ pageParam }) => { try { const homeApi = createHomepageApi(token); // eslint-disable-next-line @typescript-eslint/no-explicit-any const result = await homeApi.apiHomeV1TopSellersList({ cursor: pageParam, pageSize: 20, }); // API returns { next, previous, results } but type says Array // Return the whole response to access 'next' in getNextPageParam return result; } catch (error) { console.error("Error fetching home top sellers:", error); throw error; } }, initialPageParam: undefined as string | undefined, getNextPageParam: (lastPage) => { // Extract cursor from next URL if (lastPage?.next) { const url = new URL(lastPage.next); return url.searchParams.get("cursor"); } return undefined; }, staleTime: 60 * 1000, // 60s — prices/discounts must stay reasonably fresh refetchOnWindowFocus: false, }); } /** * Hook for fetching home page categories * @returns Query result with home page categories */ export function useGetHomeCategories() { const token = useAuthToken(); return useQuery({ queryKey: homeKeys.categories(), queryFn: async () => { try { const homeApi = createHomepageApi(token); return await homeApi.apiHomeV1CategoriesList(); } catch (error) { console.error("Error fetching home categories:", error); throw error; } }, staleTime: 20 * 60 * 1000, // 5 minutes cache refetchOnWindowFocus: false, }); } /** * Hook for fetching top 4 seller tiles for homepage * @returns Query result with seller tiles */ export function useGetHomeSellerTiles() { const token = useAuthToken(); return useQuery({ queryKey: homeKeys.sellerTiles(), queryFn: async () => { try { const homeApi = createHomepageApi(token); return await homeApi.apiHomeV1SellerTilesList(); } catch (error) { console.error("Error fetching home seller tiles:", error); throw error; } }, staleTime: 5 * 60 * 1000, refetchOnWindowFocus: false, }); } /** * Hook for fetching all seller tiles for 'See more' page * @returns Query result with all seller tiles */ export function useGetAllSellerTiles() { const token = useAuthToken(); return useQuery({ queryKey: homeKeys.sellerTilesAll(), queryFn: async () => { try { const homeApi = createHomepageApi(token); return await homeApi.apiHomeV1SellerTilesAllList(); } catch (error) { console.error("Error fetching all seller tiles:", error); throw error; } }, staleTime: 5 * 60 * 1000, refetchOnWindowFocus: false, }); }