Load rule templates from API
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { listRuleTemplatesFromDb } from "../../lib/server/ruleTemplates";
|
||||
import { GOVERNANCE_TEMPLATE_HOME_SLUGS } from "../../lib/templates/governanceTemplateCatalog";
|
||||
import { gridEntriesForSlugOrderWithCatalogFallback } from "../../lib/templates/templateGridPresentation";
|
||||
|
||||
const RuleStack = dynamic(() => import("../components/sections/RuleStack"), {
|
||||
loading: () => (
|
||||
<section className="py-[var(--spacing-scale-032)] min-h-[400px]" />
|
||||
),
|
||||
ssr: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Server-loaded “Popular templates” row so the first paint has card data without a client fetch.
|
||||
*/
|
||||
export async function MarketingRuleStackSection() {
|
||||
const rows = await listRuleTemplatesFromDb();
|
||||
const initialGridEntries = gridEntriesForSlugOrderWithCatalogFallback(
|
||||
rows,
|
||||
GOVERNANCE_TEMPLATE_HOME_SLUGS,
|
||||
);
|
||||
return <RuleStack initialGridEntries={initialGridEntries} />;
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { Suspense } from "react";
|
||||
import messages from "../../messages/en/index";
|
||||
import { getTranslation } from "../../lib/i18n/getTranslation";
|
||||
import HeroBanner from "../components/sections/HeroBanner";
|
||||
import AskOrganizer from "../components/sections/AskOrganizer";
|
||||
import { MarketingRuleStackSection } from "./MarketingRuleStackSection";
|
||||
|
||||
// Code split below-the-fold components to reduce initial bundle size
|
||||
const LogoWall = dynamic(() => import("../components/sections/LogoWall"), {
|
||||
@@ -22,13 +24,6 @@ const NumberedCards = dynamic(
|
||||
},
|
||||
);
|
||||
|
||||
const RuleStack = dynamic(() => import("../components/sections/RuleStack"), {
|
||||
loading: () => (
|
||||
<section className="py-[var(--spacing-scale-032)] min-h-[400px]" />
|
||||
),
|
||||
ssr: true,
|
||||
});
|
||||
|
||||
const FeatureGrid = dynamic(
|
||||
() => import("../components/sections/FeatureGrid"),
|
||||
{
|
||||
@@ -98,7 +93,13 @@ export default function Page() {
|
||||
<HeroBanner {...heroBannerData} />
|
||||
<LogoWall />
|
||||
<NumberedCards {...numberedCardsData} />
|
||||
<RuleStack />
|
||||
<Suspense
|
||||
fallback={
|
||||
<section className="py-[var(--spacing-scale-032)] min-h-[400px]" />
|
||||
}
|
||||
>
|
||||
<MarketingRuleStackSection />
|
||||
</Suspense>
|
||||
<FeatureGrid {...featureGridData} />
|
||||
<QuoteBlock />
|
||||
<AskOrganizer {...askOrganizerData} />
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import HeaderLockup from "../../components/type/HeaderLockup";
|
||||
import { GovernanceTemplateGrid } from "../../components/sections/GovernanceTemplateGrid";
|
||||
import type { TemplateGridCardEntry } from "../../../lib/templates/templateGridPresentation";
|
||||
import { useTranslation } from "../../contexts/MessagesContext";
|
||||
|
||||
export interface TemplatesPageClientProps {
|
||||
initialGridEntries: TemplateGridCardEntry[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Full templates index — Figma 22142-898446 (title, intro, 2-col card grid).
|
||||
* `initialGridEntries` is computed on the server to avoid a client-side loading flash.
|
||||
*/
|
||||
export default function TemplatesPageClient({
|
||||
initialGridEntries,
|
||||
}: TemplatesPageClientProps) {
|
||||
const router = useRouter();
|
||||
const t = useTranslation("pages.templates");
|
||||
|
||||
return (
|
||||
<div className="w-full bg-black text-[var(--color-content-default-primary,white)]">
|
||||
<div
|
||||
className="
|
||||
mx-auto w-full max-w-[1280px]
|
||||
px-[20px] py-[32px]
|
||||
min-[640px]:px-[32px] min-[640px]:py-[40px]
|
||||
min-[1024px]:px-[64px] min-[1024px]:py-[48px]
|
||||
"
|
||||
>
|
||||
<div className="flex w-full flex-col gap-2 py-3">
|
||||
<HeaderLockup
|
||||
title={t("title")}
|
||||
description={t("subtitle")}
|
||||
justification="left"
|
||||
size="L"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6 min-[1024px]:mt-8">
|
||||
<GovernanceTemplateGrid
|
||||
entries={initialGridEntries}
|
||||
onTemplateClick={(slug) => {
|
||||
router.push(
|
||||
`/create/review-template/${encodeURIComponent(slug)}`,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,47 +1,9 @@
|
||||
"use client";
|
||||
import { listRuleTemplatesFromDb } from "../../../lib/server/ruleTemplates";
|
||||
import { gridEntriesForFullCatalogWithFallback } from "../../../lib/templates/templateGridPresentation";
|
||||
import TemplatesPageClient from "./TemplatesPageClient";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import HeaderLockup from "../../components/type/HeaderLockup";
|
||||
import { GovernanceTemplateGrid } from "../../components/sections/GovernanceTemplateGrid";
|
||||
import { GOVERNANCE_TEMPLATE_CATALOG } from "../../../lib/templates/governanceTemplateCatalog";
|
||||
import { useTranslation } from "../../contexts/MessagesContext";
|
||||
|
||||
/**
|
||||
* Full templates index — Figma 22142-898446 (title, intro, 2-col card grid).
|
||||
*/
|
||||
export default function TemplatesPage() {
|
||||
const router = useRouter();
|
||||
const t = useTranslation("pages.templates");
|
||||
|
||||
return (
|
||||
<div className="w-full bg-black text-[var(--color-content-default-primary,white)]">
|
||||
<div
|
||||
className="
|
||||
mx-auto w-full max-w-[1280px]
|
||||
px-[20px] py-[32px]
|
||||
min-[640px]:px-[32px] min-[640px]:py-[40px]
|
||||
min-[1024px]:px-[64px] min-[1024px]:py-[48px]
|
||||
"
|
||||
>
|
||||
<div className="flex w-full flex-col gap-2 py-3">
|
||||
<HeaderLockup
|
||||
title={t("title")}
|
||||
description={t("subtitle")}
|
||||
justification="left"
|
||||
size="L"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6 min-[1024px]:mt-8">
|
||||
<GovernanceTemplateGrid
|
||||
entries={GOVERNANCE_TEMPLATE_CATALOG}
|
||||
onTemplateClick={(slug) => {
|
||||
router.push(
|
||||
`/create/review-template/${encodeURIComponent(slug)}`,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
export default async function TemplatesPage() {
|
||||
const rows = await listRuleTemplatesFromDb();
|
||||
const initialGridEntries = gridEntriesForFullCatalogWithFallback(rows);
|
||||
return <TemplatesPageClient initialGridEntries={initialGridEntries} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user