Skip to content

Commit

Permalink
feat: solutions showcase
Browse files Browse the repository at this point in the history
  • Loading branch information
juliankoehn committed Dec 30, 2024
1 parent 560f8ed commit c38ca66
Show file tree
Hide file tree
Showing 13 changed files with 10,388 additions and 155 deletions.
6 changes: 0 additions & 6 deletions src/app/(frontend)/local/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import { HomeHero } from "@/components/hero/home";
import CTASection from "@/components/sections/cta";
import { ProblemStatement } from "@/components/sections/problem-statement";
import { UseCases } from "@/components/sections/use-cases";
import { Separator } from "@/components/ui/separator";

export default function Home() {
return (
<>
<HomeHero />
<ProblemStatement />
<div className="layout">
<Separator className="col-span-full my-8 lg:my-12" />
</div>

<UseCases />
<CTASection />
Expand Down
4 changes: 4 additions & 0 deletions src/blocks/render-blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MetricsBlock } from "./metrics/metrics-block";
import { ContentBlock } from "./content/content-block";
import { CardGridBlock } from "./card-grid/card-grid-block";
import { FeatureGridBlock } from "./feature-grid/feature-grid-block";
import { SolutionShowcaseBlock } from "./solution-showcase/solution-showcase-block";

type Block = Page["layout"][0];

Expand Down Expand Up @@ -43,6 +44,9 @@ export const RenderBlocks = ({ blocks }: RenderBlocksProps) => {
case "featureGrid": {
return <FeatureGridBlock key={`${block.id}`} {...block} />;
}
case "solutionShowcase": {
return <SolutionShowcaseBlock key={`${block.id}`} {...block} />;
}
default: {
return null;
}
Expand Down
107 changes: 107 additions & 0 deletions src/blocks/solution-showcase/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { themeField } from "@/fields/theme";
import type { Block } from "payload";

export const SolutionShowcase: Block = {
slug: "solutionShowcase",
interfaceName: "SolutionShowcaseBlock",
labels: {
singular: "Solution Showcase",
plural: "Solution Showcases",
},
fields: [
themeField(),
{
name: "heading",
type: "group",
fields: [
{
name: "title",
type: "text",
required: true,
},
{
name: "description",
type: "textarea",
},
{
name: "alignment",
type: "select",
defaultValue: "center",
options: [
{ label: "Center", value: "center" },
{ label: "Left", value: "left" },
],
},
],
},
{
name: "solutions",
type: "array",
required: true,
minRows: 1,
admin: {
description: "Add solutions or use cases to display",
},
fields: [
themeField(),
{
name: "title",
type: "text",
required: true,
},
{
name: "description",
type: "textarea",
required: true,
},

{
name: "media",
type: "group",
fields: [
{
name: "mediaType",
type: "radio",
defaultValue: "image",
enumName: "enum_solutionshowcase_media_type",
options: [
{
label: "Image",
value: "image",
},
{
label: "Icon",
value: "icon",
},
],
},
{
name: "image",
type: "upload",
relationTo: "media",
required: true,
admin: {
condition: (_, { mediaType } = {}) => {
return mediaType === "image";
},
},
filterOptions: {
mimeType: { contains: "image" },
},
},
{
name: "icon",
type: "text",
required: true,
label: "Icon Name",
admin: {
condition: (_, { mediaType } = {}) => mediaType === "icon",
description: "Name of the Lucide icon to use",
},
},
],
},
],
},
],
};
92 changes: 92 additions & 0 deletions src/blocks/solution-showcase/solution-showcase-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { ColorMode } from "@/components/cms/color-mode";
import { Media } from "@/components/cms/media";
import { Feature } from "@/components/ui/feature";
import { Icon, type IconName } from "@/components/ui/icon";
import { Heading, Paragraph } from "@/components/ui/typography";
import { cn } from "@/lib/utils";
import type { SolutionShowcaseBlock as SolutionShowcaseBlockProps } from "@/payload-types";

type Props = SolutionShowcaseBlockProps;

export const SolutionShowcaseBlock = ({ theme, heading, solutions }: Props) => {
return (
<ColorMode
as="section"
className="py-16 space-y-8 lg:space-y-12"
theme={theme}
>
{/* Headline Section */}
{heading && (
<div className="layout">
<div
className={cn(
"col-span-full mb-12 space-y-4",
"lg:col-span-8",
heading.alignment === "center" ? "text-center" : "text-left"
)}
>
<h2 className="text-4xl md:text-5xl font-bold text-foreground">
{heading.title}
</h2>
{heading.description && (
<p className="text-lg text-muted-foreground">
{heading.description}
</p>
)}
</div>
</div>
)}

<div className="layout">
{Array.isArray(solutions) &&
solutions.map((solution, index) => (
<ColorMode
key={`${solution.id}`}
theme={solution.theme}
className={cn(
"col-span-full @container h-full",
index % 4 === 0
? "md:col-span-2 lg:col-span-8"
: index % 4 === 1
? "md:col-span-1 lg:col-span-4"
: "md:col-span-1 lg:col-span-6"
)}
>
<Feature.Root className="h-full">
<Feature.TextWrapper className="space-y-2">
<Heading as="h4" level={5}>
{solution.title}
</Heading>

<Paragraph color="muted">{solution.description}</Paragraph>
</Feature.TextWrapper>
{/* Media handling */}
{solution.media &&
solution.media.mediaType === "image" &&
solution.media?.image && (
<Feature.Media>
<Media
resource={solution.media.image}
className="w-full h-full object-cover rounded-2xl"
imgClassName="rounded-2xl"
/>
</Feature.Media>
)}

{solution.media &&
solution.media.mediaType === "icon" &&
solution.media?.icon && (
<div className="relative w-12 h-12 my-4">
<Icon
name={solution.media.icon as IconName}
className="w-full h-full object-contain"
/>
</div>
)}
</Feature.Root>
</ColorMode>
))}
</div>
</ColorMode>
);
};
2 changes: 2 additions & 0 deletions src/collections/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Metrics } from "@/blocks/metrics/config";
import { Content } from "@/blocks/content/config";
import { CardGrid } from "@/blocks/card-grid/config";
import { FeatureGrid } from "@/blocks/feature-grid/config";
import { SolutionShowcase } from "@/blocks/solution-showcase/config";

export const Pages: CollectionConfig<"pages"> = {
slug: "pages",
Expand Down Expand Up @@ -86,6 +87,7 @@ export const Pages: CollectionConfig<"pages"> = {
Content,
CardGrid,
FeatureGrid,
SolutionShowcase,
],
required: true,
admin: {
Expand Down
10 changes: 8 additions & 2 deletions src/components/cms/color-mode.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { forwardRef } from "react";
import { Box, type BoxProps } from "../ui/box";
import type { ThemeField } from "@/payload-types";
import { cn } from "@/lib/utils";

export type ColorModeProps = BoxProps<"div" | "section"> & {
theme: ThemeField;
};

export const ColorMode = forwardRef<HTMLDivElement, ColorModeProps>(
(props, ref) => {
const { children, theme, ...restProps } = props;
const { children, theme, className, ...restProps } = props;
const { colorMode } = theme ?? {};

return (
<Box {...restProps} ref={ref} data-theme={colorMode ?? "light"}>
<Box
{...restProps}
className={cn("text-foreground", className)}
ref={ref}
data-theme={colorMode ?? "light"}
>
{children}
</Box>
);
Expand Down
Loading

0 comments on commit c38ca66

Please sign in to comment.