'use client' import { useState, useEffect } from 'react' export interface MedusaProductCategory { id: string name: string handle: string } export interface MedusaProduct { id: string title: string description?: string thumbnail?: string // variants is optional — Medusa API may omit it when fields param is not set variants?: Array<{ id: string; prices: Array<{ amount: number; currency_code: string }> }> images?: Array<{ url: string }> tags?: Array<{ value: string }> created_at?: string collection?: { id: string; title: string; handle: string } | null categories?: MedusaProductCategory[] } interface UseMedusaProductsResult { products: MedusaProduct[] loading: boolean isLoading: boolean // alias for loading — both work error: string | null } type UseMedusaProductsOptions = number | { limit?: number; categoryId?: string } // Accepts either a plain number or an options object — both call signatures are valid: // useMedusaProducts(4) // useMedusaProducts({ limit: 4, categoryId: 'cat_123' }) export function useMedusaProducts(options: UseMedusaProductsOptions = 12): UseMedusaProductsResult { // 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/medusa/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() const interval = setInterval(fetchProducts, 30000) return () => { clearInterval(interval); controller.abort() } }, [limit, categoryId]) return { products, loading, isLoading: loading, error } }