From 40ce5064d6ca496368c9936bc242c58a75f79642 Mon Sep 17 00:00:00 2001 From: adilallo <39313955+adilallo@users.noreply.github.com> Date: Sun, 17 May 2026 22:40:06 -0600 Subject: [PATCH] Implement how it works page --- .../HowItWorksDecorativeShapes.tsx | 43 ++++++ app/(marketing)/how-it-works/page.tsx | 132 ++++++++++++++++++ app/(marketing)/page.tsx | 1 + .../ContentContainer.container.tsx | 13 +- .../ContentContainer.types.ts | 5 + .../ContentContainer.view.tsx | 3 +- .../CardSteps/CardSteps.container.tsx | 3 +- .../sections/CardSteps/CardSteps.types.ts | 2 + .../sections/CardSteps/CardSteps.view.tsx | 8 +- app/components/sections/ContentBanner.tsx | 84 ----------- .../ContentBanner/ContentBanner.container.tsx | 56 ++++++++ .../ContentBanner/ContentBanner.types.ts | 24 ++++ .../ContentBanner/ContentBanner.view.tsx | 128 +++++++++++++++++ .../sections/ContentBanner/index.tsx | 5 + .../RelatedArticles.container.tsx | 4 + .../RelatedArticles/RelatedArticles.types.ts | 9 ++ .../RelatedArticles/RelatedArticles.view.tsx | 12 +- .../ContentLockup/ContentLockup.container.tsx | 2 + .../type/ContentLockup/ContentLockup.view.tsx | 4 + lib/assetUtils.ts | 19 +++ lib/howItWorksSyntheticPost.ts | 31 ++++ messages/en/components/cardSteps.json | 3 +- messages/en/index.ts | 2 + messages/en/metadata.json | 10 ++ messages/en/pages/home.json | 2 +- messages/en/pages/howItWorks.json | 12 ++ .../assets/shapes/guide-banner-logo-arrow.svg | 3 + public/assets/shapes/how-shape-1.svg | 9 ++ public/assets/shapes/how-shape-2.svg | 9 ++ stories/sections/ContentBanner.stories.js | 40 +++++- tests/components/ContentBanner.test.tsx | 22 +++ tests/e2e/critical-journeys.spec.ts | 10 +- tests/e2e/edge-cases.spec.ts | 50 +++---- tests/pages/home.test.jsx | 4 + tests/pages/how-it-works.test.jsx | 66 +++++++++ 35 files changed, 707 insertions(+), 123 deletions(-) create mode 100644 app/(marketing)/how-it-works/_components/HowItWorksDecorativeShapes.tsx create mode 100644 app/(marketing)/how-it-works/page.tsx delete mode 100644 app/components/sections/ContentBanner.tsx create mode 100644 app/components/sections/ContentBanner/ContentBanner.container.tsx create mode 100644 app/components/sections/ContentBanner/ContentBanner.types.ts create mode 100644 app/components/sections/ContentBanner/ContentBanner.view.tsx create mode 100644 app/components/sections/ContentBanner/index.tsx create mode 100644 lib/howItWorksSyntheticPost.ts create mode 100644 messages/en/pages/howItWorks.json create mode 100644 public/assets/shapes/guide-banner-logo-arrow.svg create mode 100644 public/assets/shapes/how-shape-1.svg create mode 100644 public/assets/shapes/how-shape-2.svg create mode 100644 tests/pages/how-it-works.test.jsx diff --git a/app/(marketing)/how-it-works/_components/HowItWorksDecorativeShapes.tsx b/app/(marketing)/how-it-works/_components/HowItWorksDecorativeShapes.tsx new file mode 100644 index 0000000..be24187 --- /dev/null +++ b/app/(marketing)/how-it-works/_components/HowItWorksDecorativeShapes.tsx @@ -0,0 +1,43 @@ +/** + * Figma: "A Guide to CommunityRule" body ornaments (22078:791901) + * https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22078-791901 + * + * - 19003:23575 — concentric circles, right (`how-shape-2.svg`) + * - 19003:23576 — loop mark, left (`how-shape-1.svg`) + */ +import { + getAssetPath, + howItWorksOrnamentLeftPath, + howItWorksOrnamentRightPath, +} from "../../../../lib/assetUtils"; + +export default function HowItWorksDecorativeShapes() { + return ( + <> +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +
+ + ); +} diff --git a/app/(marketing)/how-it-works/page.tsx b/app/(marketing)/how-it-works/page.tsx new file mode 100644 index 0000000..b565907 --- /dev/null +++ b/app/(marketing)/how-it-works/page.tsx @@ -0,0 +1,132 @@ +/** + * Figma: "How Community Rule works" (22078:806964) + * https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=22078-806964 + */ +import type { Metadata } from "next"; +import dynamic from "next/dynamic"; +import messages from "../../../messages/en/index"; +import { getAllBlogPosts } from "../../../lib/content"; +import { + buildHowItWorksSyntheticPost, + HOW_IT_WORKS_SENTINEL_SLUG, +} from "../../../lib/howItWorksSyntheticPost"; +import ContentBanner from "../../components/sections/ContentBanner"; +import HowItWorksDecorativeShapes from "./_components/HowItWorksDecorativeShapes"; +import AskOrganizer from "../../components/sections/AskOrganizer"; +import "../blog/blog.css"; + +const RelatedArticles = dynamic( + () => import("../../components/sections/RelatedArticles"), + { + loading: () => ( +
+ ), + ssr: true, + }, +); + +export async function generateMetadata(): Promise { + const meta = messages.metadata.howItWorks; + const page = messages.pages.howItWorks; + + return { + title: meta.title, + description: meta.description, + keywords: meta.keywords, + openGraph: { + title: page.banner.title, + description: page.banner.description, + type: "website", + siteName: "CommunityRule", + }, + }; +} + +export default function HowItWorksPage() { + const page = messages.pages.howItWorks; + const syntheticPost = buildHowItWorksSyntheticPost(page); + + const allPosts = getAllBlogPosts(); + const relatedPosts = allPosts.slice(0, 8); + const slugOrder = allPosts.map((post) => post.slug); + + const askOrganizerData = { + title: messages.pages.home.askOrganizer.title, + subtitle: messages.pages.home.askOrganizer.subtitle, + buttonText: messages.pages.home.askOrganizer.buttonText, + }; + + const structuredData = { + "@context": "https://schema.org", + "@type": "WebPage", + name: page.banner.title, + description: page.banner.description, + url: "https://communityrule.com/how-it-works", + publisher: { + "@type": "Organization", + name: "CommunityRule", + url: "https://communityrule.com", + }, + }; + + const breadcrumbData = { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: "https://communityrule.com", + }, + { + "@type": "ListItem", + position: 2, + name: page.banner.title, + item: "https://communityrule.com/how-it-works", + }, + ], + }; + + return ( + <> +