diff --git a/apps/climatemappedafrica/public/images/cms/blocks/how-it-works.png b/apps/climatemappedafrica/public/images/cms/blocks/how-it-works.png new file mode 100644 index 000000000..c1922e11b Binary files /dev/null and b/apps/climatemappedafrica/public/images/cms/blocks/how-it-works.png differ diff --git a/apps/climatemappedafrica/src/components/HowItWorks/Player.js b/apps/climatemappedafrica/src/components/HowItWorks/Player.js new file mode 100644 index 000000000..e893f04f4 --- /dev/null +++ b/apps/climatemappedafrica/src/components/HowItWorks/Player.js @@ -0,0 +1,48 @@ +/* eslint-disable jsx-a11y/media-has-caption */ +import PropTypes from "prop-types"; +import React, { useEffect } from "react"; +import videojs from "video.js"; +import "videojs-youtube"; +import "video.js/dist/video-js.css"; + +function Player({ url, type }) { + const videoRef = React.useRef(null); + const playerRef = React.useRef(null); + + useEffect(() => { + if (videoRef.current && !playerRef.current) { + const options = { + autoplay: false, + controls: true, + preload: "auto", + sources: [{ src: url, type }], + techOrder: ["youtube"], + youtube: { ytControls: 2 }, + }; + playerRef.current = videojs(videoRef.current, options); + } + }, [url, type]); + + // Dispose the Video.js player when the functional component unmounts + useEffect(() => { + return () => { + if (playerRef.current) { + playerRef.current.dispose(); + playerRef.current = null; + } + }; + }, []); + + return ( +
+
+ ); +} + +Player.propTypes = { + url: PropTypes.string, + type: PropTypes.string, +}; + +export default Player; diff --git a/apps/climatemappedafrica/src/components/HowItWorks/index.js b/apps/climatemappedafrica/src/components/HowItWorks/index.js new file mode 100644 index 000000000..0133a6093 --- /dev/null +++ b/apps/climatemappedafrica/src/components/HowItWorks/index.js @@ -0,0 +1,195 @@ +import { Link } from "@commons-ui/next"; +import { RichText } from "@commons-ui/payload"; +import { Box, Grid, Typography } from "@mui/material"; +import PropTypes from "prop-types"; +import React from "react"; + +import Player from "@/climatemappedafrica/components/HowItWorks/Player"; +import useStyles from "@/climatemappedafrica/components/HowItWorks/useStyles"; +import Section from "@/climatemappedafrica/components/Section"; + +function HowItWorks({ + title, + description, + link, + video, + backgroundImage, + image: foregroundImage, + ...props +}) { + const classes = useStyles(props); + + return ( + + + ({ + display: { + xs: "none", + md: "block", + lg: "none", + }, + position: "absolute", + left: 0, + top: theme.typography.pxToRem(42), + width: "100%", + background: `linear-gradient(to right, #ffffffE6 0%, #ffffffE6 56%, transparent 56%, transparent 100%)`, + height: theme.typography.pxToRem(524), + })} + /> +
+ + ({ + position: { + md: "relative", + }, + top: { + md: 0, + }, + backgroundColor: { + lg: theme.palette.background.default, + }, + opacity: { + md: 0.9, + }, + height: { + md: theme.typography.pxToRem(524), + lg: theme.typography.pxToRem(600), + }, + padding: { + md: `${theme.typography.pxToRem(66)} ${theme.typography.pxToRem( + 77, + )} ${theme.typography.pxToRem(69)} 0`, + lg: `${theme.typography.pxToRem(81)} ${theme.typography.pxToRem(98)}`, + }, + })} + > + ({ + position: "relative", + "& .video-js": { + width: "100%", + height: "100%", + }, + "& .vjs-poster": { + backgroundColor: "#ffffffE6", + backgroundSize: { + xs: "120%", + md: "auto", + }, + }, + "& .video-js .vjs-big-play-button": { + display: "none", + }, + height: { + xs: theme.typography.pxToRem(227), + md: theme.typography.pxToRem(194), + lg: theme.typography.pxToRem(244), + }, + width: { + xs: "100%", + md: theme.typography.pxToRem(299), + lg: theme.typography.pxToRem(376), + }, + })} + > + + + ({ + marginTop: theme.typography.pxToRem(18), + })} + variant="h4" + > + {title} + + ({ + fontFamily: theme.typography.body1.fontFamily, + margin: `${theme.typography.pxToRem(16.5)} 0`, + color: theme.palette.grey.dark, + width: { + md: theme.typography.pxToRem(278), + }, + })} + /> + + {link.label} + + + + + ({ + position: "relative", + height: { + xs: theme.typography.pxToRem(265), + md: theme.typography.pxToRem(211), + lg: theme.typography.pxToRem(441.6), + }, + width: { + xs: theme.typography.pxToRem(253.6), + md: theme.typography.pxToRem(202), + lg: theme.typography.pxToRem(422.5), + }, + backgroundImage: `url(${foregroundImage.src})`, + backgroundSize: "contain", + backgroundRepeat: "no-repeat", + marginBottom: theme.typography.pxToRem(23), + })} + /> + + +
+
+ ); +} + +HowItWorks.propTypes = { + ctaText: PropTypes.string, + description: PropTypes.string, + href: PropTypes.string, + title: PropTypes.string, +}; + +export default HowItWorks; diff --git a/apps/climatemappedafrica/src/components/HowItWorks/useStyles.js b/apps/climatemappedafrica/src/components/HowItWorks/useStyles.js new file mode 100644 index 000000000..494337cfb --- /dev/null +++ b/apps/climatemappedafrica/src/components/HowItWorks/useStyles.js @@ -0,0 +1,17 @@ +import makeStyles from "@mui/styles/makeStyles"; + +const useStyles = makeStyles(({ breakpoints, typography }) => ({ + section: { + zIndex: 1, + position: "relative", + paddingTop: typography.pxToRem(62), + [breakpoints.up("md")]: { + padding: `${typography.pxToRem(42)} 0`, + }, + [breakpoints.up("lg")]: { + padding: `${typography.pxToRem(64)} 0`, + }, + }, +})); + +export default useStyles; diff --git a/apps/climatemappedafrica/src/pages/[[...slugs]].js b/apps/climatemappedafrica/src/pages/[[...slugs]].js index 24a6d30f9..b82b526b5 100644 --- a/apps/climatemappedafrica/src/pages/[[...slugs]].js +++ b/apps/climatemappedafrica/src/pages/[[...slugs]].js @@ -5,6 +5,7 @@ import { SWRConfig } from "swr"; import AboutTeam from "@/climatemappedafrica/components/AboutTeam"; import Footer from "@/climatemappedafrica/components/Footer"; import Hero from "@/climatemappedafrica/components/Hero"; +import HowItWorks from "@/climatemappedafrica/components/HowItWorks"; import Navigation from "@/climatemappedafrica/components/Navigation"; import PageHero from "@/climatemappedafrica/components/PageHero"; import Summary from "@/climatemappedafrica/components/Summary"; @@ -12,6 +13,7 @@ import { getPageServerSideProps } from "@/climatemappedafrica/lib/data"; const componentsBySlugs = { hero: Hero, + "how-it-works": HowItWorks, "page-hero": PageHero, summary: Summary, team: AboutTeam, diff --git a/apps/climatemappedafrica/src/payload/blocks/HowItWorks.js b/apps/climatemappedafrica/src/payload/blocks/HowItWorks.js new file mode 100644 index 000000000..135b67e99 --- /dev/null +++ b/apps/climatemappedafrica/src/payload/blocks/HowItWorks.js @@ -0,0 +1,86 @@ +import { slateEditor } from "@payloadcms/richtext-slate"; + +import image from "../fields/image"; +import linkGroup from "../fields/links/linkGroup"; +import richText from "../fields/richText"; + +const HowItWorks = { + slug: "how-it-works", + imageURL: "/images/cms/blocks/how-it-works.png", + fields: [ + { + name: "title", + type: "text", + required: true, + localized: true, + }, + richText({ + name: "description", + label: { + en: "Description", + }, + editor: slateEditor({ + admin: { + elements: ["link"], + leaves: ["bold", "code", "italic", "underline"], + }, + }), + required: true, + localized: true, + }), + { + name: "video", + type: "group", + fields: [ + { + name: "url", + type: "text", + label: { + en: "Youtube Video URL", + }, + required: true, + localized: true, + }, + { + name: "type", + type: "text", + required: true, + defaultValue: "video/youtube", + admin: { + description: "The type of video. e.g. video/mp4, video/youtube", + hidden: true, + }, + }, + ], + localized: true, + }, + linkGroup({ + overrides: { + label: { + en: "Find out more", + }, + localized: true, + }, + }), + image({ + overrides: { + name: "image", + required: true, + admin: { + description: "Image to display on the right side of the video.", + }, + }, + }), + image({ + overrides: { + name: "backgroundImage", + required: true, + admin: { + description: "Image to display in the background.", + }, + }, + }), + ], +}; + +export default HowItWorks; diff --git a/apps/climatemappedafrica/src/payload/collections/Pages.js b/apps/climatemappedafrica/src/payload/collections/Pages.js index c98d41908..ac157c44b 100644 --- a/apps/climatemappedafrica/src/payload/collections/Pages.js +++ b/apps/climatemappedafrica/src/payload/collections/Pages.js @@ -1,4 +1,5 @@ import Hero from "../blocks/Hero"; +import HowItWorks from "../blocks/HowItWorks"; import PageHero from "../blocks/PageHero"; import Summary from "../blocks/Summary"; import Team from "../blocks/Team"; @@ -31,7 +32,7 @@ const Pages = { { name: "blocks", type: "blocks", - blocks: [Hero, PageHero, Summary, Team], + blocks: [Hero, HowItWorks, PageHero, Summary, Team], localized: true, admin: { initCollapsed: true,