Skip to content

Commit

Permalink
New consulting page breadcrumbs (#3353)
Browse files Browse the repository at this point in the history
* initial commit to setup shadcn

* added config for shadcn and components.json

* shadcn import setup and breadcrum template code

* breadcrumbs component

* 🎨 moved base case to switch statement

* breadcrumb component integrated with Tina

* adding a consulting v2 collection (WIP)

* 🪓 Split consulting page into 2 separate routes

* starting to create the blocks page

* 💄 Replaced navbar on consultingv2 page with stylistically consistent navbar

* 🐛 Fixed Breadcrumbs not rendering on new consulting pages

* 🏷️ Added explicit typing for Breadcrumbs component

* ♻️ Added variable for initial breadcrumb value

* 💄 Fixed layout for v2 consulting page

* 💄 Updated breadcrumbs to match figma prototype

* 💄offset text underline for breadcrumbs to match figma prototype

* 🎨 Added new background color type for new consulting pages

* 💄Made breadcrumbs thinner to match figma prototype

* ✨ Made breadcrumb default to title of the current page

* ✨ updated consulting schema to automatically fill out first breadcrumb when the user leaves it blank

* 🐛 Fixed consulting page not saving when no blocks are provided

* 🪵 Removed console logging in consultingv2 return

* 💄  Fixed responsive view for breadcrumbs & configured dark mode settings

* 🦺 Added contextual editing for final breadcrumb

* ✨ Added option to configure breadcrumb url segments

* Fixed consulting page layout

* Updated tina info fields to be consistent

* 🦺 Applied tina editor feedback from Betty

* 🦺 Made final breadcrumb clickable when empty

* 💄 Added validation for final breadcrumb

* 💄 Fixed missing bottom side padding for breadcrumb

* 🐛 Fixed consulting page type inference throwing exception

* Update consulting page v2 schema to always populate the last breadcrumb if not fileld out

* 🦙 committing tina lock file

* brought over layout fix from consulting page branch

* 🐛 Fixed new consulting pages not being generated

* 🚨 removed unused screen class

* 🚨 Fixed class name order for hero component

* 🚨 Fixed explicit any on new consulting page

* ♻️ Simplified layout on consulting pages

* 💄 Fixed old consulting page missing open sans font

* 🔎 Added seo props to consulting pages

* 🔥 Removed commented code inside of consulting page server component

* 🚨 Fixed linting errors

* 💄 made section padding for consulting 2 smaller on mobile devices

* 💄 Added padding around breadcrumbs rather than page

* 🚨 Disabled eslint rule about custom tailwind classes

* 🚚 updated breadcrumb file names to match current tina collection naming

* 🔧 Fixed es lint ignore message

* ⬆️ update pnpm lock file

* 🚨 Fixed casing on "stroke-linecap" property

* 🔥 removed duplicated consulting page information

* 🦙 Comitting updated tina lock file

* 🐛 Fixed some consulting pages not being generated

* 🐛 Fixed articlesConnection being initialized for no reason

* 🐛 Fixed some consulting pages not being included in the initial fetch

* ✏️ Renamed consulting page params to remove ambiguity

* 💄 Added a prefix for the breadcrumbs component

* 🦺 Added placeholder value for breadcrumb title

* ✨ Added option to configure home route for breadcrumb component

* 🦙 Updating schema new

* 🔥 removed on save functionality for breadcrumbs

* 🎨 Moved Breadcrumb schema to breadcrumbs folder

* 🐛 Fixed screen flashing white after breadcrumbs are created

* TinaCMS content update

Co-authored-by: Caleb Williams <CalebWilliams@ssw.com.au>

* TinaCMS content update

Co-authored-by: Caleb Williams <CalebWilliams@ssw.com.au>

* TinaCMS content update

Co-authored-by: Caleb Williams <CalebWilliams@ssw.com.au>

* ✏️ Reworded instructions for updating breadcrumbs

* 🔥 Removed commented code

* 🔥 Deleted test data for consulting v2 page

* 🚨 Fixed linting warnings

---------

Co-authored-by: isaaclombardssw <isaaclombard@ssw.com.au>
Co-authored-by: tina-cloud-app[bot] <58178390+tina-cloud-app[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 1, 2024
1 parent 203b63d commit c86f287
Show file tree
Hide file tree
Showing 32 changed files with 1,401 additions and 190 deletions.
2 changes: 1 addition & 1 deletion app/components/page-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type PageLayoutProps = {
};
const PageLayout = ({ children, megaMenu }: PageLayoutProps) => {
return (
<div className="flex min-h-screen flex-col">
<div className="flex h-screen min-h-screen flex-col">
<header className="no-print">{megaMenu}</header>
<main className="grow bg-white">{children}</main>
<Footer />
Expand Down
44 changes: 44 additions & 0 deletions app/consulting/[filename]/consulting2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use client";

import { Blocks } from "@/components/blocks-renderer";
import { PreFooter } from "@/components/layout/footer/pre-footer";
import { SectionColor } from "@/components/util/constants/styles";
import { Container } from "@/components/util/container";
import { Section } from "@/components/util/section";
import { Consultingv2Query } from "@/tina/types";

type ConsultingV2PageProps<T> = {
tinaProps: {
data: Consultingv2Query;
};
props: T;
};

export default function ConsultingV2({
tinaProps,
}: ConsultingV2PageProps<object>) {
const { data } = tinaProps;

return (
<>
{/* eslint-disable-next-line tailwindcss/no-custom-classname*/}
<div className="dark flex h-full flex-col">
<Section color={SectionColor.ToggleLightMode}>
<Container width="custom" size="small" className="w-full sm:py-12">
<div className="w-full">
{data.consultingv2.blocks ? (
<Blocks
prefix={"Consultingv2Blocks"}
blocks={data.consultingv2.blocks}
/>
) : (
<></>
)}
</div>
</Container>
</Section>
<PreFooter />
</div>
</>
);
}
149 changes: 119 additions & 30 deletions app/consulting/[filename]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,102 @@
import { MediaCardProps } from "@/components/consulting/mediaCard/mediaCard";
import { getRandomTestimonialsByCategory } from "@/helpers/getTestimonials";
import { useSEO } from "@/hooks/useSeo";
import client from "@/tina/client";
import "aos/dist/aos.css"; // This is important to keep the animation
import { TODAY } from "hooks/useFetchEvents";
import { useSEO } from "hooks/useSeo";
import { Metadata } from "next";
import { Open_Sans } from "next/font/google";
import { TinaClient } from "../../tina-client";
import ConsultingPage from "./consulting";

import OldConsultingPage from "./consulting";
import ConsultingPage2 from "./consulting2";
const openSans = Open_Sans({
variable: "--open-sans-font",
subsets: ["latin"],
display: "swap",
weight: ["300", "400", "600"],
});
type NewConsultingPage = Awaited<
ReturnType<typeof client.queries.consultingv2>
>;

type OldConsultingPage = Awaited<
ReturnType<typeof client.queries.consultingContentQuery>
>;

type NewConsultingPages = Awaited<
ReturnType<typeof client.queries.consultingv2Connection>
>;
type ConsultingPages = Awaited<
ReturnType<typeof client.queries.consultingConnection>
>;

export const dynamicParams = false;

export async function generateStaticParams() {
let pageListData = await client.queries.consultingConnection();
const allPagesListData = pageListData;
type ConsultingPageParams = {
filename: string;
};

while (pageListData.data.consultingConnection.pageInfo.hasNextPage) {
const lastCursor =
pageListData.data.consultingConnection.pageInfo.endCursor;
pageListData = await client.queries.consultingConnection({
after: lastCursor,
});
async function extractAllPages(query, field: string) {
let consultingFetch = await query();

allPagesListData.data.consultingConnection.edges.push(
...pageListData.data.consultingConnection.edges
const accmulatedPages = consultingFetch;

while (consultingFetch.data[field].pageInfo.hasNextPage) {
const lastCursor = consultingFetch.data[field].pageInfo.endCursor;

consultingFetch = await query({ after: lastCursor });

accmulatedPages.data[field].edges.push(
...consultingFetch.data[field].edges
);
}
return accmulatedPages;
}

export async function generateStaticParams(): Promise<ConsultingPageParams[]> {
const newConsultingPages: NewConsultingPages = await extractAllPages(
client.queries.consultingv2Connection,
"consultingv2Connection"
);

const newConsultingPagesData: ConsultingPageParams[] =
newConsultingPages.data.consultingv2Connection.edges.map((page) => {
return { filename: page.node._sys.filename, isNewConsultingPage: true };
});

const pages = allPagesListData.data.consultingConnection.edges.map(
(page) => ({
filename: page.node._sys.filename,
})
const consultingPagesData: ConsultingPages = await extractAllPages(
client.queries.consultingConnection,
"consultingConnection"
);
const consultingPages: ConsultingPageParams[] =
consultingPagesData.data.consultingConnection.edges.map((page) => {
return { filename: page.node._sys.filename, isNewConsultingPage: false };
});

return pages;
return [...consultingPages, ...newConsultingPagesData];
}

const getData = async (filename: string) => {
const newConsultingPageData = async (filename: string) => {
const tinaProps: NewConsultingPage = await client.queries.consultingv2({
relativePath: `${filename}.json`,
});
const global = await client.queries.global({ relativePath: "index.json" });
const seo = tinaProps.data.consultingv2.seo;
return {
props: {
data: tinaProps.data,
query: tinaProps.query,
variables: tinaProps.variables,
header: {
url: global.data.global.header.url,
},
seo,
...tinaProps,
},
};
};

const consultingPageData = async (filename: string) => {
const tinaProps = await client.queries.consultingContentQuery({
relativePath: `${filename}.mdx`,
date: TODAY.toISOString(),
Expand Down Expand Up @@ -120,13 +173,19 @@ type GenerateMetaDataProps = {
};

export async function generateMetadata({
params,
params: { filename },
}: GenerateMetaDataProps): Promise<Metadata> {
const tinaProps = await getData(params.filename);
const isNewConsultingPage = Boolean(await findConsultingPageType(filename));

const tinaProps = isNewConsultingPage
? await newConsultingPageData(filename)
: await consultingPageData(filename);

const seo = tinaProps.props.seo;
const seo =
tinaProps.props.data[isNewConsultingPage ? "consultingv2" : "consulting"]
.seo;
if (seo && !seo.canonical) {
seo.canonical = `${tinaProps.props.header.url}consulting/${params.filename}`;
seo.canonical = `${tinaProps.props.header.url}consulting/${filename}`;
}

// eslint-disable-next-line react-hooks/rules-of-hooks
Expand All @@ -138,15 +197,45 @@ export async function generateMetadata({
export default async function Consulting({
params,
}: {
params: { filename: string };
params: ConsultingPageParams;
}) {
const { filename } = params;

const { props } = await getData(filename);
const isNewConsultingPage: boolean = Boolean(
await findConsultingPageType(params.filename)
);
let pageData:
| Awaited<ReturnType<typeof consultingPageData>>
| Awaited<ReturnType<typeof newConsultingPageData>>;

if (isNewConsultingPage) {
pageData = await newConsultingPageData(params.filename);
} else {
pageData = await consultingPageData(params.filename);
}
const { props } = pageData;

return (
return isNewConsultingPage ? (
<TinaClient props={props} Component={ConsultingPage2} />
) : (
<div className={openSans.className}>
<TinaClient props={props} Component={ConsultingPage} />
<TinaClient props={props} Component={OldConsultingPage} />
</div>
);
}

const findConsultingPageType = async (
filename: string
): Promise<ConsultingPageType> => {
const v2Pages = await client.queries.consultingv2Connection();

for (const page of v2Pages.data.consultingv2Connection.edges) {
if (page.node._sys.filename === filename) {
return ConsultingPageType.New;
}
}
return ConsultingPageType.Old;
};

enum ConsultingPageType {
New = 1,
Old = 0,
}
2 changes: 1 addition & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const inter = Inter({
variable: "--inter-font",
subsets: ["latin"],
display: "swap",
weight: ["400", "600", "700"],
weight: ["300", "400", "600", "700"],
});

const ChatBaseBot = dynamic(
Expand Down
21 changes: 21 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "styles.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
5 changes: 5 additions & 0 deletions components/blocks-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ const LatestTech = dynamic(() =>

import { EventBooking } from "./training/eventBooking";

const Breadcrumbs = dynamic(() =>
import("./blocks/breadcrumbs/breadcrumbs").then((mod) => mod.Breadcrumbs)
);

const InterestForm = dynamic(
() => import("./events/interestForm").then((mod) => mod.InterestForm),
{ ssr: false }
Expand Down Expand Up @@ -118,6 +122,7 @@ const componentMap = {
AboutUs,
Carousel,
Content,
Breadcrumbs,
ServiceCards,
UpcomingEvents,
BuiltOnAzure,
Expand Down
19 changes: 2 additions & 17 deletions components/blocks/breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import global from "@/content/global/index.json";
import NextBreadcrumbs from "nextjs-breadcrumbs2";
import { FC } from "react";
import { tinaField } from "tinacms/dist/react";

interface BreadcrumbsProps {
path: string;
suffix: string;
Expand All @@ -23,22 +23,7 @@ export const Breadcrumbs: FC<BreadcrumbsProps> = (props) => {
>
<NextBreadcrumbs
replaceCharacterList={[
{ from: "consulting", to: "Services" },
{ from: "products", to: "Products" },
{ from: "offices", to: "Offices" },
{ from: "training", to: "Training" },
{ from: "employment", to: "Employment" },
{ from: "video-production", to: "Video Production" },
{ from: "Training-videos", to: "Training Videos" },
{ from: "industry", to: "Industry" },
{ from: "company", to: "Company" },
{ from: "events", to: "Events" },
{ from: "partners", to: "Partners" },
{ from: "netug", to: ".NET User Group" },
{ from: "clients", to: "Clients" },
{ from: "live", to: "Live" },
{ from: "logo", to: "Logo" },
{ from: "articles", to: "SSW Articles" },
...global.breadcrumbReplacements,
{ from: props.path, to: `${props.title}` },
]}
activeItemClassName={listItemStyling}
Expand Down
Loading

0 comments on commit c86f287

Please sign in to comment.