From 090531fe3a15bb5342c07affc4c8ab7fcb23d9ba Mon Sep 17 00:00:00 2001 From: Vula Builder Date: Tue, 15 Sep 2026 18:02:56 +0000 Subject: [PATCH] Deploy --- src/hooks/useVulaContent.ts | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/hooks/useVulaContent.ts diff --git a/src/hooks/useVulaContent.ts b/src/hooks/useVulaContent.ts new file mode 100644 index 0000000..a04ce32 --- /dev/null +++ b/src/hooks/useVulaContent.ts @@ -0,0 +1,57 @@ +'use client' +import { useState, useEffect } from 'react' + +export interface CmsItem { + id: string + collection: string + title: string | null + data: Record + status: string + sortOrder: number + scheduledAt: string | null + expiresAt: string | null + publishedAt: string | null +} + +export function useVulaContent(collection: string) { + const [items, setItems] = useState([]) + const [loading, setLoading] = useState(true) + + useEffect(() => { + let controller = new AbortController() + + const fetchContent = () => { + controller = new AbortController() + fetch(`/api/content/${collection}`, { signal: controller.signal }) + .then(r => r.json()) + .then((data: { items?: CmsItem[] }) => { + setItems(data.items ?? []) + setLoading(false) + }) + .catch(err => { if (err?.name !== 'AbortError') setLoading(false) }) + } + + fetchContent() + const interval = setInterval(fetchContent, 30000) + const onVisible = () => { if (document.visibilityState === 'visible') fetchContent() } + document.addEventListener('visibilitychange', onVisible) + + return () => { + clearInterval(interval) + controller.abort() + document.removeEventListener('visibilitychange', onVisible) + } + }, [collection]) + + // isLoading is an alias, matching what the product hooks already return + // ({ products, loading, isLoading: loading, error }). Without it this hook was + // the odd one out, and three of our OWN section templates - Specials, Promotions + // and Campaigns - destructure isLoading from it. Every project including any of + // them carried a type error that next dev never reports, because SWC strips + // types without checking them, so it only surfaced when a deploy ran tsc. + // + // Fixing the hook rather than the three call sites: the inconsistency was the + // fault. A generated section that reasonably guesses isLoading now works too, + // instead of being right or wrong depending on which hook it happened to call. + return { items, loading, isLoading: loading } +}