Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🍱 Consultive V2 Blocks – Related Technologies #3425

Merged
merged 7 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion components/blocks-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,15 @@ const ImageTextBlock = dynamic(() =>
);

const CardCarousel = dynamic(() =>
import("./blocks/cardCarousel/cardCarousel").then((mod) => mod.CardCarousel)
import("./blocks/cardCarousel/cardCarousel/cardCarousel").then(
(mod) => mod.CardCarousel
)
);

const TechnologyCardCarousel = dynamic(() =>
import("./blocks/cardCarousel/technologyCards/technologyCardCarousel").then(
(mod) => mod.TechnologyCardCarousel
)
);

const componentMap = {
Expand Down Expand Up @@ -174,6 +182,7 @@ const componentMap = {
ImageTextBlock,
AccordionBlock,
CardCarousel,
TechnologyCardCarousel,
};

export const Blocks = ({ prefix, blocks }) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
"use client";
import { ListItem } from "@/components/blocksSubtemplates/listItem";
import { PillGroup } from "@/components/blocksSubtemplates/pillGroup";

import { Button } from "@/components/button/templateButton";
import { Container } from "@/components/util/container";
import {
Consultingv2BlocksCardCarousel as CardCarouselData,
Consultingv2BlocksCardCarouselCards,
} from "@/tina/types";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";
import { tinaField } from "tinacms/dist/react";
import { cardOptions } from "../../blocksSubtemplates/tinaFormElements/colourOptions/cardOptions";
import { Icon } from "../../blocksSubtemplates/tinaFormElements/icon";
import V2ComponentWrapper from "../../layout/v2ComponentWrapper";
import { CardList } from "./cardCarouseSlideshow";
import { Tabs, useTabCarousel } from "./cardCarouselTabs";
import V2ComponentWrapper from "../../../layout/v2ComponentWrapper";
import { Card } from "../layout/card";
import { CardList } from "../layout/cardCarouseSlideshow";
import { Tabs, useTabCarousel } from "../layout/cardCarouselTabs";

type CardData = Consultingv2BlocksCardCarouselCards;
export const CardCarousel = ({ data }: { data: CardCarouselData }) => {
export const CardCarousel = ({ data }) => {
//Check if any images are used in cards (adds a placeholder to the other cards)
const [hasImages, setHasImages] = useState(false);
const { tabsData, activeCategory, categoryGroup } = useTabCarousel({
Expand Down Expand Up @@ -98,7 +90,7 @@ export const CardCarousel = ({ data }: { data: CardCarouselData }) => {
<Card
key={`card-${index}`}
placeholder={hasImages}
data={{ ...cardData, cardStyle: data.cardStyle }}
data={{ ...cardData, cardStyle: data.cardStyle ?? 0 }}
/>
);
})}
Expand All @@ -110,7 +102,7 @@ export const CardCarousel = ({ data }: { data: CardCarouselData }) => {
<Container size="custom" padding="sm:px-8" className="py-4">
<CardList
activeCategory={activeCategory}
data={{ cards: cardSet, cardStyle: data.cardStyle }}
data={{ cards: cardSet, cardStyle: data.cardStyle ?? 0 }}
hasImages={hasImages}
/>
</Container>
Expand All @@ -119,76 +111,3 @@ export const CardCarousel = ({ data }: { data: CardCarouselData }) => {
</V2ComponentWrapper>
);
};
type CardProps = {
data: CardData & { cardStyle: number };
placeholder: boolean;
};
const Card = ({ data, placeholder }: CardProps) => {
//If image fails to load, use placeholder (Piers)
const [usePlaceholder, setUsePlaceholder] = useState(false);
const placeholderImage = "/images/videoPlaceholder.png";

return (
<div
className={`flex w-90 shrink flex-col rounded-md text-start ${
cardOptions.find((value) => {
return value.reference === data.cardStyle;
})?.classes
}`}
>
{(data.image || placeholder) && (
<div
className="relative mb-2 min-h-36 w-full overflow-hidden rounded-md"
data-tina-field={tinaField(data, "image")}
>
<Image
src={
usePlaceholder
? placeholderImage
: (data.image ?? placeholderImage)
}
onError={() => setUsePlaceholder(true)}
alt={data.altText ?? "Card Image"}
fill={true}
className="object-cover"
/>
</div>
)}
<Icon data={{ name: data.icon }} className="size-6 text-sswRed" />
{data.chips && <PillGroup data={data.chips} />}
<h3
className="pb-2 text-xl font-semibold leading-6 dark:text-gray-200"
data-tina-field={tinaField(data, "heading")}
>
{data.heading}
</h3>
{data.description && (
<p
className="text-sm font-light dark:text-gray-300"
data-tina-field={tinaField(data, "description")}
>
{data.description}
</p>
)}
{data.featureList?.features?.map((item, index) => {
return <ListItem key={index} data={item} />;
})}
{data.embeddedButton && (
<div className="flex h-full flex-col-reverse justify-between">
<a
href={data.embeddedButton.buttonLink}
className="pt-2 font-semibold text-white !decoration-gray-400 !decoration-1 hover:!decoration-sswRed"
>
{data.embeddedButton.buttonText}
<Icon
data={{ name: data.embeddedButton.icon }}
className="inline size-4"
/>
</a>
</div>
)}
</div>
);
};

export { Card };
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { default as React, useEffect, useState } from "react";
import { Template, wrapFieldsWithMeta } from "tinacms";
import { listItemSchema } from "../../blocksSubtemplates/listItem.schema";
import { pillGroupSchema } from "../../blocksSubtemplates/pillGroup";
import { cardOptions } from "../../blocksSubtemplates/tinaFormElements/colourOptions/cardOptions";
import { ColorPickerInput } from "../../blocksSubtemplates/tinaFormElements/colourSelector";
import { IconPickerInput } from "../../blocksSubtemplates/tinaFormElements/iconSelector";
import { buttonSchema } from "../../button/templateButton.schema";
import { backgroundSchema } from "../../layout/v2ComponentWrapper";
import { Checkbox } from "../../ui/checkbox";
import { listItemSchema } from "../../../blocksSubtemplates/listItem.schema";
import { pillGroupSchema } from "../../../blocksSubtemplates/pillGroup";
import { cardOptions } from "../../../blocksSubtemplates/tinaFormElements/colourOptions/cardOptions";
import { ColorPickerInput } from "../../../blocksSubtemplates/tinaFormElements/colourSelector";
import { IconPickerInput } from "../../../blocksSubtemplates/tinaFormElements/iconSelector";
import { buttonSchema } from "../../../button/templateButton.schema";
import { backgroundSchema } from "../../../layout/v2ComponentWrapper";
import { Checkbox } from "../../../ui/checkbox";

const GUIDFunction = () => Math.random().toString(36).substring(7);

Expand Down
82 changes: 82 additions & 0 deletions components/blocks/cardCarousel/layout/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { ListItem } from "@/components/blocksSubtemplates/listItem";
import { PillGroup } from "@/components/blocksSubtemplates/pillGroup";
import Image from "next/image";
import { useState } from "react";
import { tinaField } from "tinacms/dist/react";
import { cardOptions } from "../../../blocksSubtemplates/tinaFormElements/colourOptions/cardOptions";
import { Icon } from "../../../blocksSubtemplates/tinaFormElements/icon";

type CardProps = {
data;
placeholder: boolean;
};

const Card = ({ data, placeholder }: CardProps) => {
//If image fails to load, use placeholder (Piers)
const [usePlaceholder, setUsePlaceholder] = useState(false);
const placeholderImage = "/images/videoPlaceholder.png";

return (
<div
className={`flex w-90 shrink flex-col rounded-md text-start ${
cardOptions.find((value) => {
return value.reference === data.cardStyle;
})?.classes
}`}
>
{(data.image || placeholder) && (
<div
className="relative mb-2 min-h-36 w-full overflow-hidden rounded-md"
data-tina-field={tinaField(data, "image")}
>
<Image
src={
usePlaceholder
? placeholderImage
: (data.image ?? placeholderImage)
}
onError={() => setUsePlaceholder(true)}
alt={data.altText ?? "Card Image"}
fill={true}
className={data.contain ? "object-contain" : "object-cover"}
/>
</div>
)}
<Icon data={{ name: data.icon }} className="size-6 text-sswRed" />
{data.chips && <PillGroup data={data.chips} />}
<h3
className="pb-2 text-xl font-semibold leading-6 dark:text-gray-200"
data-tina-field={tinaField(data, "heading")}
>
{data.heading}
</h3>
{data.description && (
<p
className="text-sm font-light dark:text-gray-300"
data-tina-field={tinaField(data, "description")}
>
{data.description}
</p>
)}
{data.featureList?.features?.map((item, index) => {
return <ListItem key={index} data={item} />;
})}
{data.embeddedButton && (
<div className="flex h-full flex-col-reverse justify-between">
<a
href={data.embeddedButton.buttonLink}
className="pt-2 font-semibold text-white !decoration-gray-400 !decoration-1 hover:!decoration-sswRed"
>
{data.embeddedButton.buttonText}
<Icon
data={{ name: data.embeddedButton.icon }}
className="inline size-4"
/>
</a>
</div>
)}
</div>
);
};

export { Card };
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
Consultingv2BlocksCardCarouselCategoryGroup,
} from "@/tina/types";
import { useEffect, useState } from "react";
import { Card } from "./cardCarousel";
import { Card } from "./card";

type CardSlideshowProps = {
data: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import client from "@/tina/client";
import { useEffect, useState } from "react";
import { CardCarousel } from "../cardCarousel/cardCarousel";

export const TechnologyCardCarousel = ({ data }) => {
const [cardList, setCardList] = useState([]);

useEffect(() => {
async function fetchData() {
const response = await client.queries.technologiesv2Connection({
filter: {
associatedGroup: {
technologyGroupsv2: {
name: {
in: data.technologyGroups?.map(
(group) => group.technologyGroup?.name
),
},
},
},
},
});
const cards = response.data.technologiesv2Connection.edges.map((card) => {
return {
guid: card.node.associatedGroup?.name,
image: card.node.thumbnail,
title: card.node.name,
altText: card.node.name,
description: card.node.body,
embeddedButton: {
buttonText: "Read More",
buttonLink: card.node.readMoreSlug,
icon: "BiChevronRight",
},
icon: card.node.icon,
contain: true,
};
});
setCardList(cards);
}
fetchData();
}, [data]);

//This data is a limited version of the data that is passed to the CardCarousel component via its schema
const cardCarouselData = {
isStacked: data.isStacked,
categoryGroup:
data.technologyGroups?.length > 1
? data.technologyGroups?.map((group) => {
return {
categoryName: group.technologyGroup?.name,
cardGuidList: {
guid: group.technologyGroup?.name,
cardGuidList: [group.technologyGroup?.name],
},
};
})
: [],
cardStyle: data.techCardStyle,
cards: cardList,
isH1: false,
heading: "Related Technologies",
body: "",
background: data.background,
};

return <CardCarousel data={cardCarouselData} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Template } from "tinacms";
import { backgroundSchema } from "../../../../components/layout/v2ComponentWrapper";
import { cardOptions } from "../../../blocksSubtemplates/tinaFormElements/colourOptions/cardOptions";
import { ColorPickerInput } from "../../../blocksSubtemplates/tinaFormElements/colourSelector";

export const TechnologyCardCarouselSchema: Template = {
name: "technologyCardCarousel",
label: "<V2> Card Carousel (Technology)",
ui: {
previewSrc: "/images/thumbs/tina/card-carousel.jpg",
},
fields: [
{
type: "object",
label: "Technology Groups",
name: "technologyGroups",
list: true,
ui: {
itemProps: (item) => {
const name = item.technologyGroup?.split("/");
return {
label: name[name.length - 1].split(".")[0] ?? "Technology Group",
};
},
},
fields: [
{
type: "reference",
label: "Technology Group",
name: "technologyGroup",
collections: ["technologyGroupsv2"],
ui: {
optionComponent: (props: { name: string }, _internalSys) => {
return props.name ?? _internalSys.path;
},
},
},
],
},
{
type: "boolean",
label: "Stacked Mode",
name: "isStacked",
description: "Remove the carousel effect and stack card entries.",
},
{
type: "number",
label: "Card Style",
name: "techCardStyle",
ui: {
// @ts-expect-error – component is not being recognized
component: ColorPickerInput(cardOptions),
},
},
//@ts-expect-error – fields are not being recognized
backgroundSchema,
],
};
Loading
Loading