'use client' import { useState, useEffect } from 'react' export interface VulaProductCategory { id: string name: string handle: string } export interface VulaProduct { id: string title: string description: string | null thumbnail: string | null created_at?: string collection?: { id: string; title: string } images?: Array<{ id?: string; url: string; position?: number }> variants: Array<{ id: string title: string prices: Array<{ amount: number; currency_code: string }> }> categories?: VulaProductCategory[] } interface UseProductsResult { products: VulaProduct[] loading: boolean isLoading: boolean // alias for loading — React Query convention, both work error: string | null } type UseProductsOptions = number | { limit?: number; categoryId?: string } // Accepts either a plain number or an options object — both call signatures are valid: // useProducts(4) // useProducts({ limit: 4, categoryId: 'cat_123' }) export function useProducts(options: UseProductsOptions = 12): UseProductsResult { // Extract scalars so useEffect deps are stable primitives, not object references. const limit = typeof options === 'number' ? options : (options.limit ?? 12) const categoryId = typeof options === 'number' ? undefined : options.categoryId const [products, setProducts] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { let controller = new AbortController() const fetchProducts = () => { controller = new AbortController() const params = new URLSearchParams({ limit: String(limit) }) if (categoryId) params.set('categoryId', categoryId) fetch(`/api/products?${params}`, { signal: controller.signal }) .then(res => res.ok ? res.json() : Promise.reject(res.status)) .then(data => { setProducts(data.products ?? []) setLoading(false) }) .catch(err => { if (err?.name !== 'AbortError') { setError(String(err)); setLoading(false) } }) } fetchProducts() // Poll every 30 s so newly published products appear without a manual refresh. const interval = setInterval(fetchProducts, 30000) // Refetch immediately when the user switches back to this tab (e.g. from Business Studio). const onVisible = () => { if (document.visibilityState === 'visible') fetchProducts() } document.addEventListener('visibilitychange', onVisible) return () => { clearInterval(interval) controller.abort() document.removeEventListener('visibilitychange', onVisible) } }, [limit, categoryId]) return { products, loading, isLoading: loading, error } }