fix(templates): fetch templates data from router (#321)

This commit is contained in:
Guy Ben-Aharon
2024-11-04 18:01:04 +02:00
committed by GitHub
parent ebce8827ea
commit d8a20ebbd9
3 changed files with 71 additions and 35 deletions

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React from 'react';
import ChartDBLogo from '@/assets/logo-light.png';
import ChartDBDarkLogo from '@/assets/logo-dark.png';
import { useTheme } from '@/hooks/use-theme';
@@ -7,49 +7,27 @@ import { ThemeProvider } from '@/context/theme-context/theme-provider';
import { Component, Star } from 'lucide-react';
import { ListMenu } from '@/components/list-menu/list-menu';
import { TemplateCard } from './template-card/template-card';
import { useMatches, useParams } from 'react-router-dom';
import { useLoaderData, useMatches, useParams } from 'react-router-dom';
import type { Template } from '@/templates-data/templates-data';
import { Spinner } from '@/components/spinner/spinner';
import { removeDups } from '@/lib/utils';
import { Helmet } from 'react-helmet-async';
export interface TemplatesPageLoaderData {
templates: Template[] | undefined;
allTags: string[] | undefined;
}
const TemplatesPageComponent: React.FC = () => {
const { effectiveTheme } = useTheme();
const data = useLoaderData() as TemplatesPageLoaderData;
const { templates, allTags } = data ?? {};
const { tag } = useParams<{ tag: string }>();
const matches = useMatches();
const [templates, setTemplates] = React.useState<Template[]>();
const [tags, setTags] = React.useState<string[]>();
const isFeatured = matches.some(
(match) => match.id === 'templates_featured'
);
const isAllTemplates = matches.some((match) => match.id === 'templates');
const isTags = matches.some((match) => match.id === 'templates_tags');
useEffect(() => {
const loadTemplates = async () => {
const { templates: loadedTemplates } = await import(
'@/templates-data/templates-data'
);
let templatesToLoad = loadedTemplates;
if (isFeatured) {
templatesToLoad = loadedTemplates.filter((t) => t.featured);
}
if (isTags && tag) {
templatesToLoad = loadedTemplates.filter((t) =>
t.tags.includes(tag)
);
}
setTemplates(templatesToLoad);
setTags(removeDups(loadedTemplates?.flatMap((t) => t.tags) ?? []));
};
loadTemplates();
}, [isFeatured, isTags, tag]);
return (
<>
@@ -125,10 +103,10 @@ const TemplatesPageComponent: React.FC = () => {
<h4 className="mt-4 text-left text-sm font-semibold">
Tags
</h4>
{tags ? (
{allTags ? (
<ListMenu
className="mt-1 w-44 shrink-0"
items={tags.map((currentTag) => ({
items={allTags.map((currentTag) => ({
title: currentTag,
href: `/templates/tags/${currentTag}`,
selected: tag === currentTag,

View File

@@ -2,6 +2,8 @@ import React from 'react';
import type { RouteObject } from 'react-router-dom';
import { createBrowserRouter } from 'react-router-dom';
import type { TemplatePageLoaderData } from './pages/template-page/template-page';
import type { TemplatesPageLoaderData } from './pages/templates-page/templates-page';
import { getTemplatesAndAllTags } from './templates-data/template-utils';
const routes: RouteObject[] = [
...['', 'diagrams/:diagramId'].map((path) => ({
@@ -38,6 +40,15 @@ const routes: RouteObject[] = [
element: <TemplatesPage />,
};
},
loader: async (): Promise<TemplatesPageLoaderData> => {
const { tags, templates } = await getTemplatesAndAllTags();
return {
allTags: tags,
templates,
};
},
},
{
id: 'templates_featured',
@@ -50,6 +61,16 @@ const routes: RouteObject[] = [
element: <TemplatesPage />,
};
},
loader: async (): Promise<TemplatesPageLoaderData> => {
const { tags, templates } = await getTemplatesAndAllTags({
featured: true,
});
return {
allTags: tags,
templates,
};
},
},
{
id: 'templates_tags',
@@ -62,6 +83,16 @@ const routes: RouteObject[] = [
element: <TemplatesPage />,
};
},
loader: async ({ params }): Promise<TemplatesPageLoaderData> => {
const { tags, templates } = await getTemplatesAndAllTags({
tag: params.tag,
});
return {
allTags: tags,
templates,
};
},
},
{
id: 'templates_templateSlug',

View File

@@ -1,6 +1,6 @@
import type { Diagram } from '@/lib/domain/diagram';
import type { Template } from './templates-data';
import { generateId } from '@/lib/utils';
import { generateId, removeDups } from '@/lib/utils';
import type { DBTable } from '@/lib/domain/db-table';
import type { DBField } from '@/lib/domain/db-field';
import type { DBIndex } from '@/lib/domain/db-index';
@@ -87,3 +87,30 @@ export const convertTemplateToNewDiagram = (template: Template): Diagram => {
tables,
};
};
export const getTemplatesAndAllTags = async ({
featured,
tag,
}: {
featured?: boolean;
tag?: string;
} = {}): Promise<{ templates: Template[]; tags: string[] }> => {
const { templates } = await import('@/templates-data/templates-data');
const allTags = removeDups(templates?.flatMap((t) => t.tags) ?? []);
if (featured) {
return {
templates: templates.filter((t) => t.featured),
tags: allTags,
};
}
if (tag) {
return {
templates: templates.filter((t) => t.tags.includes(tag)),
tags: allTags,
};
}
return { templates, tags: allTags };
};