151 lines
4.0 KiB
TypeScript
151 lines
4.0 KiB
TypeScript
/**
|
|
* useConstructorData Hook
|
|
*
|
|
* Orchestrates all data fetching for the constructor page using React Query.
|
|
* Replaces the manual loadData function with cached, deduplicated queries.
|
|
*/
|
|
|
|
import { useMemo } from 'react';
|
|
import { useProjectQuery } from './queries/useProjectQuery';
|
|
import { usePagesQuery } from './queries/usePagesQuery';
|
|
import { useAssetsQuery } from './queries/useAssetsQuery';
|
|
import { useElementDefaultsQuery } from './queries/useElementDefaultsQuery';
|
|
import { extractPageLinksAndElements } from '../lib/extractPageLinks';
|
|
import type { TourPage, Asset } from '../types/entities';
|
|
import type { CanvasElementType, CanvasElement } from '../types/constructor';
|
|
import type { PreloadPageLink, PreloadElement } from '../types/preload';
|
|
|
|
interface UseConstructorDataParams {
|
|
projectId: string | undefined;
|
|
isAuthReady: boolean;
|
|
}
|
|
|
|
// Stable empty references to prevent infinite loops from identity changes
|
|
const EMPTY_ELEMENT_DEFAULTS: Partial<
|
|
Record<CanvasElementType, Partial<CanvasElement>>
|
|
> = {};
|
|
const EMPTY_PAGES: TourPage[] = [];
|
|
const EMPTY_ASSETS: Asset[] = [];
|
|
|
|
interface UseConstructorDataResult {
|
|
// Project
|
|
project: { name: string } | null;
|
|
projectName: string;
|
|
|
|
// Pages
|
|
pages: TourPage[];
|
|
pageLinks: PreloadPageLink[];
|
|
allPagesPreloadElements: PreloadElement[];
|
|
|
|
// Assets
|
|
assets: Asset[];
|
|
|
|
// Element Defaults
|
|
uiElementDefaultsByType: Partial<
|
|
Record<CanvasElementType, Partial<CanvasElement>>
|
|
>;
|
|
|
|
// Loading state
|
|
isLoading: boolean;
|
|
isError: boolean;
|
|
error: Error | null;
|
|
|
|
// Refetch function
|
|
refetch: () => Promise<void>;
|
|
}
|
|
|
|
export function useConstructorData({
|
|
projectId,
|
|
isAuthReady,
|
|
}: UseConstructorDataParams): UseConstructorDataResult {
|
|
// Enable queries only when we have projectId and auth is ready
|
|
const enabled = Boolean(projectId) && isAuthReady;
|
|
|
|
// Fetch project
|
|
const projectQuery = useProjectQuery(enabled ? projectId : undefined);
|
|
|
|
// Fetch pages (dev environment for constructor)
|
|
const pagesQuery = usePagesQuery(enabled ? projectId : undefined, 'dev');
|
|
|
|
// Fetch assets
|
|
const assetsQuery = useAssetsQuery(enabled ? projectId : undefined, {
|
|
limit: 500,
|
|
});
|
|
|
|
// Fetch element defaults
|
|
const elementDefaultsQuery = useElementDefaultsQuery(
|
|
enabled ? projectId : undefined,
|
|
);
|
|
|
|
// Extract page links and preload elements from pages
|
|
const { pageLinks, allPagesPreloadElements } = useMemo(() => {
|
|
if (!pagesQuery.data || pagesQuery.data.length === 0) {
|
|
return {
|
|
pageLinks: [] as PreloadPageLink[],
|
|
allPagesPreloadElements: [] as PreloadElement[],
|
|
};
|
|
}
|
|
const { pageLinks: links, preloadElements: elements } =
|
|
extractPageLinksAndElements(pagesQuery.data as TourPage[]);
|
|
return { pageLinks: links, allPagesPreloadElements: elements };
|
|
}, [pagesQuery.data]);
|
|
|
|
// Combine loading states
|
|
const isLoading =
|
|
projectQuery.isLoading ||
|
|
pagesQuery.isLoading ||
|
|
assetsQuery.isLoading ||
|
|
elementDefaultsQuery.isLoading;
|
|
|
|
// Combine error states
|
|
const isError =
|
|
projectQuery.isError ||
|
|
pagesQuery.isError ||
|
|
assetsQuery.isError ||
|
|
elementDefaultsQuery.isError;
|
|
|
|
const error =
|
|
projectQuery.error ||
|
|
pagesQuery.error ||
|
|
assetsQuery.error ||
|
|
elementDefaultsQuery.error;
|
|
|
|
// Refetch all queries
|
|
const refetch = async () => {
|
|
await Promise.all([
|
|
projectQuery.refetch(),
|
|
pagesQuery.refetch(),
|
|
assetsQuery.refetch(),
|
|
elementDefaultsQuery.refetch(),
|
|
]);
|
|
};
|
|
|
|
return {
|
|
// Project
|
|
project: projectQuery.data || null,
|
|
projectName: projectQuery.data?.name || '',
|
|
|
|
// Pages
|
|
pages: (pagesQuery.data as TourPage[]) || EMPTY_PAGES,
|
|
pageLinks,
|
|
allPagesPreloadElements,
|
|
|
|
// Assets
|
|
assets: (assetsQuery.data as Asset[]) || EMPTY_ASSETS,
|
|
|
|
// Element Defaults
|
|
uiElementDefaultsByType:
|
|
elementDefaultsQuery.data || EMPTY_ELEMENT_DEFAULTS,
|
|
|
|
// Loading state
|
|
isLoading,
|
|
isError,
|
|
error: error instanceof Error ? error : null,
|
|
|
|
// Refetch
|
|
refetch,
|
|
};
|
|
}
|
|
|
|
export default useConstructorData;
|