diff --git a/packages/website/src/app.jsx b/packages/website/src/app.jsx index 073bace..cf5b01e 100644 --- a/packages/website/src/app.jsx +++ b/packages/website/src/app.jsx @@ -127,6 +127,16 @@ const App = () => { )} /> + + + + + + + + + + diff --git a/packages/website/src/components/contentful-blog-list/contentful-blog-list.jsx b/packages/website/src/components/contentful-blog-list/contentful-blog-list.jsx new file mode 100644 index 0000000..d0741c0 --- /dev/null +++ b/packages/website/src/components/contentful-blog-list/contentful-blog-list.jsx @@ -0,0 +1,52 @@ +import React, { useState, useEffect } from 'react' +import { PageWrapper, Hero, Blog, Blogs, BlogImage, BlogTitle, BlogSection } from './contentful-blog-list.styles' +import { getBlogs } from './helpers/blogs' +import { Break } from '../panels' + +export const ContentfulBlogList = ({ slug }) => { + const [blogs, setBlogs] = useState([]) + + const getData = async () => { + const blogItems = await getBlogs() + if (!blogItems) return + + setBlogs(blogItems) + } + + useEffect(() => { + getData() + }, [slug]) + + return !blogs + ? '' + : ( + + Blogs + + + + + Blogs/News + + + {blogs.length} results + + + + {blogs.map((blog) => ( + + + + + + {blog.title} + {blog.dateFormatted} + View + + + ))} + + + + ) +} diff --git a/packages/website/src/components/contentful-blog-list/contentful-blog-list.styles.jsx b/packages/website/src/components/contentful-blog-list/contentful-blog-list.styles.jsx new file mode 100644 index 0000000..19f9788 --- /dev/null +++ b/packages/website/src/components/contentful-blog-list/contentful-blog-list.styles.jsx @@ -0,0 +1,114 @@ +import styled from 'styled-components' + +export const PageWrapper = styled.div` +padding-top: 67px; +background-color: white; + +font-size: 16px; +` +export const Hero = styled.div` +padding: 120px 0; +background-image: url(${props => props.background}); +background-size: cover; +background-position: center center; +font-size: 35px; +text-align: center; +h1{ + background-color: rgba(0,0,0,.5); + padding: 0.3rem 2.5rem; + font-size: 2rem; + color: white; + display: inline-block; + border-radius: 6px; + margin: 20px; +} + +@media (max-width: 640px) { + padding: 80px 0; + h1{ + font-size: 1.5rem; + } + } +` +export const Breadcrumb = styled.div` + background-color: #f9f9fa; + padding: 30px 20px; + border-bottom: solid 1px #ddd; + .content{ + max-width: 750px; + margin: 0 auto; + } + a, span{ + color: #9da0b6; + } +` +export const BlogSection = styled.div` + max-width: 750px; + margin: 0 auto; + padding: 20px 0; + + @media (max-width: 640px) { + padding: 20px 20px; + } +` + +export const Blogs = styled.div` + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 30px 10px; + + @media (max-width: 640px) { + grid-template-columns: 1fr 1fr; + } +` + +export const Blog = styled.div` + border: 1px #dcdcdc; solid; + border-radius: 6px; + h2{ + font-size: 18px; + } + .text{ + padding: 5px; + p{ + color: #9c9c9c; + font-size:12px; + } + } + .button{ + background-color: #2e6dcb; + border: none; + color: white; + padding: 10px 25px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + border-radius: 6px; + + &:hover{ + background-color: #2459a8; + } + } +` + +export const BlogImage = styled.div` +background-color: #dcdcdc; +height: 150px; +background-image: url(${props => props.background}); +background-size: cover; +background-position: center center; +background-color: #dcdcdc; +border-radius: 5px; +` + +export const BlogTitle = styled.div` + display: flex; + align-items: center; + & > * { + flex: 1; + } + .column-right{ + text-align: right; + } +` diff --git a/packages/website/src/components/contentful-blog-list/helpers/blogs.jsx b/packages/website/src/components/contentful-blog-list/helpers/blogs.jsx new file mode 100644 index 0000000..471bfd0 --- /dev/null +++ b/packages/website/src/components/contentful-blog-list/helpers/blogs.jsx @@ -0,0 +1,27 @@ +import { setupClient } from '../../../shared/contentful' + +export const getBlogs = async () => { + const client = setupClient() + const entries = await client.getEntries({ + content_type: 'blog', + limit: 100, + include: 10 + }) + const items = entries?.items || null + if (!items.length > 0) return null + + const blogs = [] + items.forEach((item) => { + const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } + const date = new Date(item.fields.date) + const dateFormatted = date.toLocaleDateString('en-GB', options) + blogs.push( + { + ...item.fields, + dateFormatted + } + ) + }) + + return blogs +} diff --git a/packages/website/src/components/contentful-blog-list/index.jsx b/packages/website/src/components/contentful-blog-list/index.jsx new file mode 100644 index 0000000..622e5c3 --- /dev/null +++ b/packages/website/src/components/contentful-blog-list/index.jsx @@ -0,0 +1 @@ +export { ContentfulBlogList } from './contentful-blog-list' diff --git a/packages/website/src/components/contentful-blog-page/contentful-blog-page.jsx b/packages/website/src/components/contentful-blog-page/contentful-blog-page.jsx new file mode 100644 index 0000000..7bd4881 --- /dev/null +++ b/packages/website/src/components/contentful-blog-page/contentful-blog-page.jsx @@ -0,0 +1,43 @@ +import React, { useState, useEffect } from 'react' +import { PageWrapper, Hero, Article, Author, Breadcrumb } from './contentful-blog-page.styles' +import { getBlogFromSlug } from './helpers/blog' +import { Break } from '../panels' + +export const ContentfulBlogPage = ({ slug }) => { + const [page, setPage] = useState(null) + + const getData = async () => { + const page = await getBlogFromSlug(slug.replace('/blog', '')) + setPage(page) + } + + useEffect(() => { + getData() + }, [slug]) + + return !page + ? '' + : ( + + {page.title} + + + + Blogs / {page.title} + + + + + + + + {page.author}, {page.authorTitle} + {page.dateFormatted} + + + + {page.bodyComponents} + + + ) +} diff --git a/packages/website/src/components/contentful-blog-page/contentful-blog-page.styles.jsx b/packages/website/src/components/contentful-blog-page/contentful-blog-page.styles.jsx new file mode 100644 index 0000000..7176e18 --- /dev/null +++ b/packages/website/src/components/contentful-blog-page/contentful-blog-page.styles.jsx @@ -0,0 +1,86 @@ +import styled from 'styled-components' + +export const PageWrapper = styled.div` +padding-top: 67px; +background-color: white; + +font-size: 16px; +` +export const Hero = styled.div` +padding: 120px 0; +background-image: url(${props => props.background}); +background-size: cover; +background-position: center center; +background-color: #dcdcdc; +font-size: 35px; +text-align: center; +h1{ + background-color: rgba(0,0,0,.5); + padding: 0.3rem 2.5rem; + font-size: 2rem; + color: white; + display: inline-block; + border-radius: 6px; + margin: 20px; +} + +@media (max-width: 640px) { + padding: 80px 0; + h1{ + font-size: 1.5rem; + } + } +` +export const Breadcrumb = styled.div` + background-color: #f9f9fa; + padding: 30px 20px; + border-bottom: solid 1px #ddd; + .content{ + max-width: 750px; + margin: 0 auto; + } + a, span{ + color: #9da0b6; + } +` +export const Article = styled.div` + max-width: 750px; + margin: 0 auto; + padding-bottom: 40px; + + line-height: 1.6; + a{ + color: #2e6dcb; + } + + hr{ + border: solid 1px #f1f1f1; + margin: 30px 0; + } + + @media (max-width: 640px) { + padding-left: 20px; + padding-right: 20px; + } +` +export const Author = styled.div` + display: flex; + max-width: 750px; + margin: 0 auto; + padding: 20px 0; + border-bottom: solid 1px #ddd; + .author-column-image{ +margin-right: 30px; + } + .author-column-text{ + p{color: #6372a1;} + } + img{ + border-radius: 50%; + } + + @media (max-width: 640px) { + padding-left: 20px; + padding-right: 20px; + } +` diff --git a/packages/website/src/components/contentful-blog-page/helpers/blog.jsx b/packages/website/src/components/contentful-blog-page/helpers/blog.jsx new file mode 100644 index 0000000..180a394 --- /dev/null +++ b/packages/website/src/components/contentful-blog-page/helpers/blog.jsx @@ -0,0 +1,30 @@ +import { setupClient, renderOptions } from '../../../shared/contentful' +import { documentToReactComponents } from '@contentful/rich-text-react-renderer' + +export const getBlogFromSlug = async (slug = '') => { + const client = setupClient() + const entries = await client.getEntries({ + content_type: 'blog', + limit: 1, + include: 10, + 'fields.url': slug, + order: '-fields.date' + }) + const entry = entries?.items[0] || null + if (!entry) return null + + const bodyComponents = documentToReactComponents( + entry.fields.body, + renderOptions + ) + + const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } + const date = new Date(entry.fields.date) + const dateFormatted = date.toLocaleDateString('en-GB', options) + + return { + ...entry.fields, + bodyComponents, + dateFormatted + } +} diff --git a/packages/website/src/components/contentful-blog-page/index.jsx b/packages/website/src/components/contentful-blog-page/index.jsx new file mode 100644 index 0000000..226d9fc --- /dev/null +++ b/packages/website/src/components/contentful-blog-page/index.jsx @@ -0,0 +1 @@ +export { ContentfulBlogPage } from './contentful-blog-page' diff --git a/packages/website/src/components/contentful-home/contentful-home.jsx b/packages/website/src/components/contentful-home/contentful-home.jsx new file mode 100644 index 0000000..a0dcc2e --- /dev/null +++ b/packages/website/src/components/contentful-home/contentful-home.jsx @@ -0,0 +1,91 @@ +import React, { useState, useEffect } from 'react' +import { Break } from '../panels' +import Logo from '../logo' +import { PageWrapper, Hero, Blog, Blogs, BlogImage, TextStrip, BlogSection, BlogTitle } from './contentful-home.styles' +import { getBlogs } from './helpers/blogs' +import { getContentBlocks } from './helpers/contentBlocks' + +export const ContentfulHome = ({ slug }) => { + const [blogs, setBlogs] = useState([]) + const [contentBlocks, setContentBlocks] = useState(null) + const getContentBlockValue = (key) => { + const blocks = contentBlocks?.filter((item) => item.fields.key === key) + if (!(blocks && blocks.length > 0)) return null + + return blocks[0].fields.value + } + const homeBlock1 = getContentBlockValue('home.text.block.1') + const homeBlock2 = getContentBlockValue('home.text.block.2') + const homeImage = getContentBlockValue('home.hero.image') + const blogTitle = getContentBlockValue('home.blog.title') + const blogLinkAll = getContentBlockValue('home.blog.link.all') + const hasBlogs = blogs?.length > 0 + + const getData = async () => { + const blogItems = await getBlogs() + const contentBlockItems = await getContentBlocks() + setBlogs(blogItems) + setContentBlocks(contentBlockItems) + } + + useEffect(() => { + getData() + }, [slug]) + + return !contentBlocks + ? '' + : ( + + + + + + + {homeBlock1} + + + + {hasBlogs && ( + <> + + + + {blogTitle} + + + {blogLinkAll} + + + + {blogs.map((blog) => ( + + + + + + {blog.title} + {blog.dateFormatted} + View + + + ))} + + + + + + {homeBlock2} + + + + > + )} + + ) +} diff --git a/packages/website/src/components/contentful-home/contentful-home.styles.jsx b/packages/website/src/components/contentful-home/contentful-home.styles.jsx new file mode 100644 index 0000000..ac301a5 --- /dev/null +++ b/packages/website/src/components/contentful-home/contentful-home.styles.jsx @@ -0,0 +1,150 @@ +import styled from 'styled-components' + +export const PageWrapper = styled.div` +padding-top: 67px; +background-color: white; + +font-size: 16px; +` +export const Hero = styled.div` +padding: 70px 0; +background-image: url(${props => props.background}); +background-size: cover; +background-position: center center; +background-color: #000; +font-size: 35px; +text-align: center; +position: relative; +h1{ + background-color: rgba(0,0,0,.5); + padding: 0.3rem 2.5rem; + font-size: 2rem; + color: white; + display: inline-block; + border-radius: 6px; + margin: 20px; +} +svg{ + width: 500px; +} +&:after{ + content: ''; + position: absolute; + bottom:0; + left: 0; + width: 100%; + height: 100%; + background-image: linear-gradient(transparent, black); +} + +@media (max-width: 640px) { + padding: 40px 0; + h1{ + font-size: 1.5rem; + } + svg{ + width: 70vw; + } + } +` +export const Breadcrumb = styled.div` + background-color: #f9f9fa; + padding: 30px 20px; + border-bottom: solid 1px #ddd; + .content{ + max-width: 750px; + margin: 0 auto; + } + a, span{ + color: #9da0b6; + } +` + +export const BlogSection = styled.div` + max-width: 750px; + margin: 0 auto; + padding: 20px 0; + + @media (max-width: 640px) { + padding: 20px 20px; + } +` + +export const Blogs = styled.div` + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 30px 10px; + + @media (max-width: 640px) { + grid-template-columns: 1fr 1fr; + } +` + +export const Blog = styled.div` + border: 1px #dcdcdc; solid; + border-radius: 6px; + h2{ + font-size: 18px; + } + .text{ + padding: 5px; + p{ + color: #9c9c9c; + font-size:12px; + } + } + .button{ + background-color: #2e6dcb; + border: none; + color: white; + padding: 10px 25px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + border-radius: 6px; + + &:hover{ + background-color: #2459a8; + } + } +` + +export const BlogImage = styled.div` +background-color: #dcdcdc; +height: 150px; +background-image: url(${props => props.background}); +background-size: cover; +background-position: center center; +background-color: #dcdcdc; +border-radius: 5px; +` +export const TextStrip = styled.div` +.text{ + max-width: 750px; + margin: 0 auto; + color: #fff; + font-size: 30px; + line-height: 1.5; +} + background-color: #000; + padding: 50px 0; + + @media (max-width: 640px) { + padding: 40px 20px; + .text{ + font-size: 24px; + } + } +` + +export const BlogTitle = styled.div` + display: flex; + align-items: center; + & > * { + flex: 1; + } + .column-right{ + text-align: right; + } +` diff --git a/packages/website/src/components/contentful-home/helpers/blogs.js b/packages/website/src/components/contentful-home/helpers/blogs.js new file mode 100644 index 0000000..77ab760 --- /dev/null +++ b/packages/website/src/components/contentful-home/helpers/blogs.js @@ -0,0 +1,28 @@ +import { setupClient } from '../../../shared/contentful' + +export const getBlogs = async () => { + const client = setupClient() + const entries = await client.getEntries({ + content_type: 'blog', + limit: 6, + include: 10, + order: '-fields.date' + }) + const items = entries?.items || null + if (!items.length > 0) return null + + const blogs = [] + items.forEach((item) => { + const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } + const date = new Date(item.fields.date) + const dateFormatted = date.toLocaleDateString('en-GB', options) + blogs.push( + { + ...item.fields, + dateFormatted + } + ) + }) + + return blogs +} diff --git a/packages/website/src/components/contentful-home/helpers/contentBlocks.js b/packages/website/src/components/contentful-home/helpers/contentBlocks.js new file mode 100644 index 0000000..e75747f --- /dev/null +++ b/packages/website/src/components/contentful-home/helpers/contentBlocks.js @@ -0,0 +1,14 @@ +import { setupClient } from '../../../shared/contentful' + +export const getContentBlocks = async () => { + const client = setupClient() + const entries = await client.getEntries({ + content_type: 'contentBlock', + limit: 100, + include: 10 + }) + const items = entries?.items || null + if (!items.length > 0) return null + + return items +} diff --git a/packages/website/src/components/contentful-home/index.jsx b/packages/website/src/components/contentful-home/index.jsx new file mode 100644 index 0000000..b5a6c78 --- /dev/null +++ b/packages/website/src/components/contentful-home/index.jsx @@ -0,0 +1 @@ +export { ContentfulHome } from './contentful-home' diff --git a/packages/website/src/components/contentful-page/contentful-page.jsx b/packages/website/src/components/contentful-page/contentful-page.jsx index 3629eb9..0bdc096 100644 --- a/packages/website/src/components/contentful-page/contentful-page.jsx +++ b/packages/website/src/components/contentful-page/contentful-page.jsx @@ -1,18 +1,12 @@ import React, { useState, useEffect } from 'react' -import { PageWrapper, Panel, Hero, LinkPanel } from '../panels' +import { Break } from '../panels' import { getPageFromSlug } from './helpers/page' -import SlideShow from '../slide-show' -import { shuffle } from './helpers/images' -import { Logo } from './contentful-page.styles' -import { Link } from 'react-router-dom' +import { Hero, Article, PageWrapper } from './contentful-page.styles' export const ContentfulPage = ({ slug }) => { const [page, setPage] = useState(null) const hasImage = page?.image?.length > 0 - const hasMultiImages = page?.image?.length > 1 - const multiImageArray = page?.image?.map( - (image) => image.fields.file.url + '?w=1100&h=700&fit=fill' - ) + const isHomePage = slug === '/' const getData = async () => { const page = await getPageFromSlug(slug) @@ -26,31 +20,17 @@ export const ContentfulPage = ({ slug }) => { return !page ? '' : ( - - {slug === '/' && Peckham Cycle Club} + {hasImage && - (hasMultiImages - ? ( - - ) - : ( - - ))} - {page.bodyComponents} - {page?.previousPage?.fields?.image[0]?.fields.file.url && ( - - {page.previousPage.fields.title} - - )} - {page?.nextPage?.fields?.image[0]?.fields.file.url && ( - - {page.nextPage.fields.title} - - )} + <> + + + {page.title} + + + + >} + {page.bodyComponents} ) } diff --git a/packages/website/src/components/contentful-page/contentful-page.styles.jsx b/packages/website/src/components/contentful-page/contentful-page.styles.jsx index 43a1483..f612dd6 100644 --- a/packages/website/src/components/contentful-page/contentful-page.styles.jsx +++ b/packages/website/src/components/contentful-page/contentful-page.styles.jsx @@ -1,18 +1,54 @@ -import logoImage from '../../../assets/pcc-logo@2x.png' import styled from 'styled-components' -export const Logo = styled.h1` - margin: 0; - padding: 250px 0 0 0; - height: 0; - overflow: hidden; - background: url(${logoImage}) no-repeat; - background-position: center; - background-size: contain; +export const PageWrapper = styled.div` +padding-top: ${(props) => props.isHomePage ? '0px' : '67px'}; +background-color: white; +font-size: 16px; +` + +export const Hero = styled.div` +padding: 120px 0; +background-image: url(${props => props.background}); +background-size: cover; +background-position: center center; +background-color: #dcdcdc; +font-size: 35px; +text-align: center; +h1{ + background-color: rgba(0,0,0,.5); + padding: 0.3rem 2.5rem; + font-size: 2rem; + color: white; + display: inline-block; + border-radius: 6px; + margin: 20px; +} + +@media (max-width: 640px) { + padding: 80px 0; + h1{ + font-size: 1.5rem; + } + } +` + +export const Article = styled.div` + max-width: 750px; + margin: 0 auto; + padding: 40px 0; + + line-height: 1.6; + a{ + color: #2e6dcb; + } + + hr{ + border: solid 1px #f1f1f1; + margin: 30px 0; + } - position: absolute; - top: 80px; - left: 0; - right: 0; - z-index: 450; + @media (max-width: 640px) { + padding-left: 20px; + padding-right: 20px; + } ` diff --git a/packages/website/src/components/footer.jsx b/packages/website/src/components/footer.jsx index 9c820a5..a4df823 100644 --- a/packages/website/src/components/footer.jsx +++ b/packages/website/src/components/footer.jsx @@ -7,7 +7,6 @@ import { } from 'react-icons/fa' import { pccLightBlue, - panelLevel3Background, panelLevel3Text } from '../colours' import { @@ -15,15 +14,15 @@ import { FlexContentLeft, FlexContentRight } from './panels' -import Comment from './comment' +import UnitedWeRoll from './united-we-roll' import { spacing } from '../units' const Footer = styled.footer` clear: both; - padding: ${spacing(3)} ${spacing(2)} ${spacing(1)} ${spacing(2)}; + padding: ${spacing(3)} ${spacing(2)}; font-size: 16px; color: ${panelLevel3Text}; - background-color: ${panelLevel3Background}; + background-color: #000; @media (max-width: 640px) { font-size: 12px; @@ -32,8 +31,8 @@ const Footer = styled.footer` const SocialLink = styled.a` color: ${panelLevel3Text}; - font-size: 18px; - margin-left: 10px; + font-size: 25px; + margin-left: 20px; &:link { color: ${panelLevel3Text}; @@ -49,7 +48,7 @@ const FooterWrapper = () => {
{blog.dateFormatted}
{page.dateFormatted}