Deploy
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
|
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 }>
|
||||||
|
}
|
||||||
|
|
||||||
|
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<MedusaProduct[]>([])
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const [error, setError] = useState<string | null>(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 }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user