diff --git a/apps/climatemappedafrica/src/components/ExplorePage/index.js b/apps/climatemappedafrica/src/components/ExplorePage/index.js index 051dcee4b..4296a53b3 100644 --- a/apps/climatemappedafrica/src/components/ExplorePage/index.js +++ b/apps/climatemappedafrica/src/components/ExplorePage/index.js @@ -11,17 +11,37 @@ import useStyles from "./useStyles"; import Panel from "@/climatemappedafrica/components/HURUmap/Panel"; -function initialState(profiles, onClick) { +function initialState( + profiles, + onClick, + explorePagePath, + initialLocationCode, + pinInitialLocation, +) { return { profiles: Array.isArray(profiles) ? profiles : [profiles], options: [ { color: "primary", onClick }, { color: "secondary", onClick }, ], + explorePagePath, + initialLocationCode, + pinInitialLocation, }; } -function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { +function ExplorePage({ + initialLocation, + explorePagePath, + panel: PanelProps = {}, + profile: profileProp, + ...props +}) { + const { + center, + name: initialLocationCode, + pinInitialLocation, + } = initialLocation; const theme = useTheme(); const classes = useStyles(props); // NOTE: This setState and the corresponding useEffect are "hacks" since at @@ -32,23 +52,43 @@ function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { setGeoCode(code); }; const [state, dispatch] = useExplore( - initialState(profileProp, handleClickTag), + initialState( + profileProp, + handleClickTag, + explorePagePath, + initialLocationCode, + pinInitialLocation, + ), ); useEffect(() => { dispatch({ type: "reset", - payload: initialState(profileProp, handleClickTag), + payload: initialState( + profileProp, + handleClickTag, + explorePagePath, + initialLocationCode, + pinInitialLocation, + ), }); - }, [dispatch, profileProp]); + }, [ + dispatch, + profileProp, + explorePagePath, + initialLocationCode, + pinInitialLocation, + ]); useEffect(() => { if (geoCode) { dispatch({ type: "fetch", payload: { code: geoCode } }); } }, [dispatch, geoCode]); + const router = useRouter(); const shouldFetch = () => (state.primary.shouldFetch && state.primary.code) || (state.secondary?.shouldFetch && state.secondary?.code); + const { data, error } = useProfileGeography(shouldFetch); useEffect(() => { if (data) { @@ -59,13 +99,23 @@ function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { } }, [dispatch, data]); + // Update URL when state.slug changes + useEffect(() => { + if (state.slug) { + const href = `/${explorePagePath}/${state.slug}`; + router.push(href, href, { shallow: true }); + } + // router shouldn't part of useEffect dependencies: https://nextjs.org/docs/api-reference/next/router#userouter + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [state.slug]); + const handleSelectLocation = (payload) => { const { code } = payload; const newPath = state.isPinning || state.isCompare ? `${state.primary.geography.code}-vs-${code}` : `${code}`; - const href = `/explore/${newPath.toLowerCase()}`; + const href = `/${explorePagePath}/${newPath.toLowerCase()}`; router.push(href, href, { shallow: true }); const type = state.isPinning && state.isCompare ? "compare" : "fetch"; dispatch({ type, payload }); @@ -86,14 +136,6 @@ function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { } dispatch({ type: "unpin", payload }); }; - useEffect(() => { - if (state.slug) { - const href = `/explore/${state.slug}`; - router.push(href, href, { shallow: true }); - } - // router shouldn't part of useEffect dependencies: https://nextjs.org/docs/api-reference/next/router#userouter - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [state.slug]); const isLoading = shouldFetch() && !(data || error); const { @@ -119,7 +161,7 @@ function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { >
); } ExplorePage.propTypes = { - apiUri: PropTypes.string, - panelProps: PropTypes.shape({}), + center: PropTypes.arrayOf(PropTypes.number), + initialLocation: PropTypes.shape({ + center: PropTypes.arrayOf(PropTypes.number), + name: PropTypes.string, + pinInitialLocation: PropTypes.bool, + }), + explorePagePath: PropTypes.string, + panel: PropTypes.shape({}), profile: PropTypes.oneOfType([ PropTypes.shape({ geography: PropTypes.shape({}), diff --git a/apps/climatemappedafrica/src/components/ExplorePage/useExplore.js b/apps/climatemappedafrica/src/components/ExplorePage/useExplore.js index f82569823..c621b93f5 100644 --- a/apps/climatemappedafrica/src/components/ExplorePage/useExplore.js +++ b/apps/climatemappedafrica/src/components/ExplorePage/useExplore.js @@ -2,7 +2,7 @@ import { useReducer } from "react"; import Link from "@/climatemappedafrica/components/Link"; -function extendProfileTags(profile, options) { +function extendProfileTags(profile, options, explorePagePath) { const { tags: originalTags, ...other } = profile || {}; if (!originalTags) { return profile; @@ -12,7 +12,7 @@ function extendProfileTags(profile, options) { ...otherTags, code, component: Link, - href: `/explore/${code.toLowerCase()}`, + href: `/${explorePagePath}/${code.toLowerCase()}`, shallow: true, underline: "none", ...options, @@ -20,19 +20,29 @@ function extendProfileTags(profile, options) { return { ...other, tags }; } -function initializer({ profiles, options }) { +function initializer({ + explorePagePath, + initialLocationCode, + profiles, + pinInitialLocation, + options, +}) { const [primary, secondary] = profiles; const [primaryOptions, secondaryOptions] = options; return { isPinning: false, isCompare: !!(primary && secondary), - primary: extendProfileTags(primary, primaryOptions), - secondary: extendProfileTags(secondary, secondaryOptions), + primary: extendProfileTags(primary, primaryOptions, explorePagePath), + secondary: extendProfileTags(secondary, secondaryOptions, explorePagePath), + explorePagePath, + initialLocationCode, + pinInitialLocation, }; } function reducer(state, action) { + const { explorePagePath, initialLocationCode, pinInitialLocation } = state; switch (action.type) { case "fetch": { const code = action.payload?.code; @@ -67,10 +77,14 @@ function reducer(state, action) { ); if (profileType) { const newState = { ...state }; - newState[profileType] = extendProfileTags(profile, { - ...others, - color: profileType, - }); + newState[profileType] = extendProfileTags( + profile, + { + ...others, + color: profileType, + }, + explorePagePath, + ); return newState; } } @@ -78,10 +92,10 @@ function reducer(state, action) { return state; } case "pin": - if (state.primary.geography.code.toLowerCase() !== "af") { + if (state.primary.geography.code.toLowerCase() !== initialLocationCode) { return { ...state, isPinning: true }; } - return { ...state, isPinning: false }; + return { ...state, isPinning: pinInitialLocation }; case "compare": { const code = action.payload?.code; if (code) { @@ -101,9 +115,13 @@ function reducer(state, action) { newState.secondary = undefined; } else if (state.primary?.geography?.code === code && state.secondary) { // NOTE: need to reset color from secondary back to primary as well - newState.primary = extendProfileTags(state.secondary, { - color: "primary", - }); + newState.primary = extendProfileTags( + state.secondary, + { + color: "primary", + }, + explorePagePath, + ); newState.secondary = undefined; } newState.secondary = undefined; diff --git a/apps/climatemappedafrica/src/components/Hero/Hero.js b/apps/climatemappedafrica/src/components/Hero/Hero.js index 7f375673c..8c687dbc8 100644 --- a/apps/climatemappedafrica/src/components/Hero/Hero.js +++ b/apps/climatemappedafrica/src/components/Hero/Hero.js @@ -13,6 +13,7 @@ import Section from "@/climatemappedafrica/components/Section"; const Map = dynamic(() => import("./Map"), { ssr: false }); function Hero({ + center, comment, title, subtitle, @@ -20,7 +21,6 @@ function Hero({ featuredLocations, searchPlaceholder, properties, - location: { center }, level, ...props }) { @@ -151,6 +151,7 @@ function Hero({ } Hero.propTypes = { + center: PropTypes.arrayOf(PropTypes.number), comment: PropTypes.string, subtitle: PropTypes.arrayOf(PropTypes.shape({})), searchLabel: PropTypes.string, diff --git a/apps/climatemappedafrica/src/components/Hero/Hero.snap.js b/apps/climatemappedafrica/src/components/Hero/Hero.snap.js index ec7dfe4c5..237b5e9d0 100644 --- a/apps/climatemappedafrica/src/components/Hero/Hero.snap.js +++ b/apps/climatemappedafrica/src/components/Hero/Hero.snap.js @@ -64,6 +64,7 @@ exports[` renders unchanged 1`] = ` blocktype="hero" boundary="[object Object]" class="MuiInputBase-root makeStyles-inputRoot-8 MuiInputBase-colorPrimary MuiInputBase-adornedEnd css-1illudf-MuiInputBase-root" + location="[object Object]" slug="hero" > ({ }, })); -function ExploreNavigation({ logo, variant }) { +function ExploreNavigation({ explorePagePath, logo, variant }) { const classes = useStyles(); const { setIsOpen } = useTour(); @@ -71,6 +71,7 @@ function ExploreNavigation({ logo, variant }) { > ; }); -function MobileNavigation({ drawerLogo, logo, menus, socialLinks, ...props }) { +function MobileNavigation({ + drawerLogo, + explorePagePath, + logo, + menus, + socialLinks, + ...props +}) { const classes = useStyles(props); const [open, setOpen] = useState(false); const router = useRouter(); @@ -277,6 +284,7 @@ function MobileNavigation({ drawerLogo, logo, menus, socialLinks, ...props }) { }} > locationCode); + const geoCodes = code + .split("-vs-") + .map((c) => c.trim()) + .filter((c) => c); + if (!geoCodes.every((gC) => locationCodes.includes(gC))) { + return { + notFound: true, + }; + } + + const [primaryCode, secondaryCode] = geoCodes; + const primaryProfile = await fetchProfileGeography(primaryCode); + const profile = [primaryProfile]; + if (secondaryCode) { + const secondaryProfile = await fetchProfileGeography(secondaryCode); + profile.push(secondaryProfile); + } + + // TODO: Move this to a PayloadCMS + const panel = { + panelItems: [ + { + value: "rich-data", + icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", + iconProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", + width: 44, + height: 44, + type: "svg", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGElEQVR4nGNgQAP/T///f/o/jHMWiQMHACIVCyeABSwfAAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + value: "pin", + icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", + pin: true, + iconProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", + width: 44, + height: 44, + type: "svg", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAH0lEQVR4nGNgQAP/L/z/f/r//4P/wZzT//+fBbOQAQBvnQ3r6iVM4QAAAABJRU5ErkJggg==", + placeholder: "blur", + }, + }, + ], + scrollToTopLabel: "Back To Top", + dataNotAvailable: "— DATA NOT AVAILABLE", + lazyblock: { + slug: "lazyblock/panel", + }, + align: "", + anchor: "", + blockId: "20amuc", + blockUniqueClass: "lazyblock-panel-20amuc", + ghostkitSpacings: "", + ghostkitSR: "", + }; + const res = { + id: "explore-page", + blockType: "explore-page", + choropleth, + initialLocation, + explorePagePath: value.slug, + locations, + mapType, + panel, + profile, + variant: "explore", + preferredChildren, + }; + + return res; +} + +export default explorePage; diff --git a/apps/climatemappedafrica/src/lib/data/blockify/hero.js b/apps/climatemappedafrica/src/lib/data/blockify/hero.js index 69eaccaf0..f6c7cefbc 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/hero.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/hero.js @@ -3,10 +3,11 @@ import { fetchProfileGeography, } from "@/climatemappedafrica/lib/hurumap"; -export default async function hero(block) { - const { geometries } = await fetchProfileGeography( - block.location?.name?.toLowerCase(), - ); +export default async function hero({ block, hurumap }) { + const { + initialLocation: { center, name }, + } = hurumap; + const { geometries } = await fetchProfileGeography(name.toLowerCase()); const { level } = geometries.boundary?.properties ?? {}; const childLevelMaps = { continent: "country", @@ -24,6 +25,7 @@ export default async function hero(block) { const boundary = children[preferredLevel]; return { ...block, + center, slug: "hero", boundary, featuredLocations, diff --git a/apps/climatemappedafrica/src/lib/data/blockify/index.js b/apps/climatemappedafrica/src/lib/data/blockify/index.js index 3aed58b79..d8a83f9fe 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/index.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/index.js @@ -1,20 +1,24 @@ +import explorePage from "./explore-page"; import hero from "./hero"; import pageHero from "./page-hero"; import team from "./team"; +import tutorial from "./tutorial"; const propsifyBlockBySlug = { + "explore-page": explorePage, hero, "page-hero": pageHero, team, + tutorial, }; -export const blockify = async (blocks, api, context) => { +export const blockify = async (blocks, api, context, hurumap) => { const promises = blocks?.map(async (block) => { const slug = block.blockType; const propsifyBlock = propsifyBlockBySlug[slug]; if (propsifyBlock) { - return propsifyBlock(block, api, context); + return propsifyBlock({ block, api, context, hurumap }); } return { ...block, diff --git a/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js b/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js index 0a732a785..1be4c04a4 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js @@ -1,6 +1,6 @@ import { imageFromMedia } from "@/climatemappedafrica/lib/data/utils"; -async function pageHero(block) { +async function pageHero({ block }) { const { background: media, ...others } = block; let background = null; if (media) { diff --git a/apps/climatemappedafrica/src/lib/data/blockify/team.js b/apps/climatemappedafrica/src/lib/data/blockify/team.js index ccc51693e..74c51abf6 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/team.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/team.js @@ -8,7 +8,7 @@ import { equalsIgnoreCase } from "@/climatemappedafrica/utils"; const getCountryFromCode = (alpha3) => countries.find((c) => equalsIgnoreCase(c.alpha3, alpha3)) ?? null; -async function team(block, api, context) { +async function team({ block, api, context }) { const { query } = context; const data = await getMembers(api, query); let members = null; diff --git a/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js b/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js new file mode 100644 index 000000000..781934ccc --- /dev/null +++ b/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js @@ -0,0 +1,88 @@ +async function tutorial() { + // TODO: Move this to Payload CMS + return { + blockType: "tutorial", + id: "tutorial", + items: [ + { + title: "SELECT LOCATION", + description: + "Select the County or Municipality you want to explore, by clicking on the search field and the dropdown menu.

Once you have made your selection, explore the visualisations, change location or pin to compare it to a second location.", + selector: "#location-search", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", + width: 694, + height: 572, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGOoqW09f/7Shw8fzp07x8AuoC4qqdXf311YWMTAL6YVE5ve2tpcV18PAHqlETRE6fa/AAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + description: + "Explore the map to confirm or change your selection. You can also pin your location if you want to compare two places.

Once a location is confirmed, click on the “Rich Data” button (on the left hand-side) to display the data visualisations.", + title: "EXPLORE THE MAP", + selector: "#none", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", + width: 751, + height: 589, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGP49u3rxEnTDxw4sn//fobCggJeYVU+YaWCvByGzMxMPmElWwfPgvw8AH1vD9GRbZHGAAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + title: "BROWSE THE CHARTS", + description: + "Continue to open the Rich Data dashboard, using the button on the left.

Browse the charts by scrolling the data dashboard. You can share and download the data using the buttons on the side of each chart.", + selector: "#rich-data", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", + width: 670, + height: 439, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/ANbW1s3NyVtbWrKyswDOztFdY38JCxe5ubcA3t7ffIKf4uPq////vgcX8ZIA2dgAAAAASUVORK5CYII=", + placeholder: "blur", + }, + }, + { + title: "PIN AND COMPARE", + description: + "There are two ways to pin and compare a second location:

1) From the data dashboard: look for the “pin” icon and select a second location from the dropdown menu.

2) From the map: pin your selected location by clicking on the ”pin” icon, then select a second location, which will appear in a different colour.", + selector: "#pin", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", + width: 675, + height: 491, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/APj491lWYA8QI+zs6wC/wMHXzMmLi5uztLYAu7u7w8XF39/eu7u7x7oYwYnBuWcAAAAASUVORK5CYII=", + placeholder: "blur", + }, + }, + ], + lazyblock: { + slug: "lazyblock/tutorial", + }, + align: "", + anchor: "", + blockId: "Z1npKaH", + blockUniqueClass: "lazyblock-tutorial-Z1npKaH", + ghostkitSpacings: "", + ghostkitSR: "", + }; +} + +export default tutorial; diff --git a/apps/climatemappedafrica/src/lib/data/common/index.js b/apps/climatemappedafrica/src/lib/data/common/index.js index e2d6d37fa..fb7918025 100644 --- a/apps/climatemappedafrica/src/lib/data/common/index.js +++ b/apps/climatemappedafrica/src/lib/data/common/index.js @@ -34,7 +34,7 @@ function getFooter(siteSettings, variant) { }; } -function getNavBar(siteSettings, variant) { +function getNavBar(siteSettings, variant, { slug }) { const { connect: { links = [] }, primaryNavigation: { menus = [], connect = [] }, @@ -47,6 +47,7 @@ function getNavBar(siteSettings, variant) { return { logo: imageFromMedia(title, primaryLogo.url), drawerLogo: imageFromMedia(title, drawerLogo.url), + explorePagePath: slug, menus, socialLinks, variant, @@ -74,12 +75,26 @@ export async function getPageProps(api, context) { page: { value: explorePage }, } = hurumap; - const blocks = await blockify(page.blocks, api, context); + let blocks = await blockify(page.blocks, api, context, hurumap); const variant = page.slug === explorePage.slug ? "explore" : "default"; const siteSettings = await api.findGlobal("settings-site"); const footer = getFooter(siteSettings, variant); - const menus = getNavBar(siteSettings, variant); + const menus = getNavBar(siteSettings, variant, explorePage); + + if (slug === explorePage.slug) { + // The explore page is a special case. The only block we need to render is map and tutorial. + const explorePageBlocks = [ + { + blockType: "explore-page", + slugs: slugs.slice(1), + }, + { + blockType: "tutorial", + }, + ]; + blocks = await blockify(explorePageBlocks, api, context, hurumap); + } return { blocks, diff --git a/apps/climatemappedafrica/src/pages/[[...slugs]].js b/apps/climatemappedafrica/src/pages/[[...slugs]].js index 5115ccff3..8682150fa 100644 --- a/apps/climatemappedafrica/src/pages/[[...slugs]].js +++ b/apps/climatemappedafrica/src/pages/[[...slugs]].js @@ -1,3 +1,4 @@ +import { useRouter } from "next/router"; import { NextSeo } from "next-seo"; import React from "react"; import { SWRConfig } from "swr"; @@ -5,9 +6,11 @@ import { SWRConfig } from "swr"; import AboutTeam from "@/climatemappedafrica/components/AboutTeam"; import DataIndicators from "@/climatemappedafrica/components/DataIndicators"; import DataVisualisationGuide from "@/climatemappedafrica/components/DataVisualisationGuide"; +import ExplorePage from "@/climatemappedafrica/components/ExplorePage"; import Footer from "@/climatemappedafrica/components/Footer"; import Hero from "@/climatemappedafrica/components/Hero"; import HowItWorks from "@/climatemappedafrica/components/HowItWorks"; +import Tutorial from "@/climatemappedafrica/components/HURUmap/Tutorial"; import Navigation from "@/climatemappedafrica/components/Navigation"; import PageHero from "@/climatemappedafrica/components/PageHero"; import Summary from "@/climatemappedafrica/components/Summary"; @@ -16,6 +19,7 @@ import { getPageServerSideProps } from "@/climatemappedafrica/lib/data"; const componentsBySlugs = { "data-indicators": DataIndicators, "data-visualisation-guide": DataVisualisationGuide, + "explore-page": ExplorePage, hero: Hero, "how-it-works": HowItWorks, "page-hero": PageHero, @@ -24,6 +28,10 @@ const componentsBySlugs = { }; function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) { + const { + query: { showTutorial }, + } = useRouter(); + const pageSeo = {}; pageSeo.title = seo?.title || null; pageSeo.description = seo?.metaDesc || null; @@ -43,6 +51,13 @@ function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) { } } + const tutorialBlock = blocks.find((block) => block.blockType === "tutorial"); + + let TutorialComponent = React.Fragment; + if (tutorialBlock) { + TutorialComponent = Tutorial; + } + let PageConfig = React.Fragment; let pageConfigProps; if (fallback) { @@ -50,7 +65,11 @@ function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) { pageConfigProps = { value: { fallback } }; } return ( - <> +