From 54da1f120774ed6fd91e4884377c4618477e1936 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 21 Sep 2023 11:21:54 +0300 Subject: [PATCH 01/25] Setup Stories collection --- apps/codeforafrica/payload.config.ts | 2 + .../src/payload/collections/Stories.js | 53 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 apps/codeforafrica/src/payload/collections/Stories.js diff --git a/apps/codeforafrica/payload.config.ts b/apps/codeforafrica/payload.config.ts index 3022d93ff..cf05d7454 100644 --- a/apps/codeforafrica/payload.config.ts +++ b/apps/codeforafrica/payload.config.ts @@ -7,6 +7,7 @@ import Media from "./src/payload/collections/Media"; import Pages from "./src/payload/collections/Pages"; import Partners from "./src/payload/collections/Partners"; import Settings from "./src/payload/globals/Settings"; +import Stories from "./src/payload/collections/Stories"; import Tags from "./src/payload/collections/Tags"; import { CollectionConfig, GlobalConfig } from "payload/types"; import dotenv from "dotenv"; @@ -39,6 +40,7 @@ export default buildConfig({ Pages, Media, Partners, + Stories, Tags, ] as CollectionConfig[], globals: [Settings] as GlobalConfig[], diff --git a/apps/codeforafrica/src/payload/collections/Stories.js b/apps/codeforafrica/src/payload/collections/Stories.js new file mode 100644 index 000000000..fcf002c01 --- /dev/null +++ b/apps/codeforafrica/src/payload/collections/Stories.js @@ -0,0 +1,53 @@ +import authors from "../fields/authors"; +import content from "../fields/content"; +import publishedOn from "../fields/publishedOn"; +import richText from "../fields/richText"; +import slug from "../fields/slug"; +import tags from "../fields/tags"; + +const Stories = { + slug: "stories", + access: { + read: () => true, + }, + versions: { + drafts: true, + }, + admin: { + useAsTitle: "title", + defaultColumns: ["title", "authors", "publishedOn"], + }, + fields: [ + { + name: "title", + type: "text", + label: "Title", + required: true, + }, + slug(), + authors(), + { + name: "coverImage", + label: "Cover Image", + type: "upload", + relationTo: "media", + required: true, + filterOptions: { + mimeType: { contains: "image" }, + }, + }, + richText({ + name: "excerpt", + label: "Excerpt", + localized: true, + admin: { + elements: ["leaves"], + }, + }), + tags(), + content(), + publishedOn(), + ], +}; + +export default Stories; From 7f8d972b415d07048b15066b0ca464028fba70a9 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 21 Sep 2023 11:38:29 +0300 Subject: [PATCH 02/25] Add stories field --- .../src/payload/collections/Stories.js | 2 +- apps/codeforafrica/src/payload/fields/stories.js | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 apps/codeforafrica/src/payload/fields/stories.js diff --git a/apps/codeforafrica/src/payload/collections/Stories.js b/apps/codeforafrica/src/payload/collections/Stories.js index fcf002c01..1423d99e5 100644 --- a/apps/codeforafrica/src/payload/collections/Stories.js +++ b/apps/codeforafrica/src/payload/collections/Stories.js @@ -6,7 +6,7 @@ import slug from "../fields/slug"; import tags from "../fields/tags"; const Stories = { - slug: "stories", + slug: "story", access: { read: () => true, }, diff --git a/apps/codeforafrica/src/payload/fields/stories.js b/apps/codeforafrica/src/payload/fields/stories.js new file mode 100644 index 000000000..e56a518ef --- /dev/null +++ b/apps/codeforafrica/src/payload/fields/stories.js @@ -0,0 +1,14 @@ +import { deepmerge } from "@mui/utils"; + +const stories = (overrides) => + deepmerge( + { + name: "stories", + type: "relationship", + relationTo: "story", + hasMany: true, + }, + overrides, + ); + +export default stories; From d0969a4f013d774b50ac18de8f95bbde959de55c Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Thu, 21 Sep 2023 11:46:18 +0300 Subject: [PATCH 03/25] Add stories block --- .../src/payload/blocks/Stories.js | 27 +++++++++++++++++++ .../src/payload/collections/Pages.js | 2 ++ 2 files changed, 29 insertions(+) create mode 100644 apps/codeforafrica/src/payload/blocks/Stories.js diff --git a/apps/codeforafrica/src/payload/blocks/Stories.js b/apps/codeforafrica/src/payload/blocks/Stories.js new file mode 100644 index 000000000..6ebb2cc78 --- /dev/null +++ b/apps/codeforafrica/src/payload/blocks/Stories.js @@ -0,0 +1,27 @@ +import stories from "../fields/stories"; + +const Stories = { + slug: "stories-list", + fields: [ + stories({ + name: "featured", + label: "Featured Story", + hasMany: false, + }), + { + name: "title", + label: "Title", + required: true, + type: "text", + }, + { + name: "search", + label: "Search Label", + required: true, + type: "text", + defaultValue: "Search Stories", + }, + ], +}; + +export default Stories; diff --git a/apps/codeforafrica/src/payload/collections/Pages.js b/apps/codeforafrica/src/payload/collections/Pages.js index 67cc7d863..efc35eefc 100644 --- a/apps/codeforafrica/src/payload/collections/Pages.js +++ b/apps/codeforafrica/src/payload/collections/Pages.js @@ -9,6 +9,7 @@ import MeetOurTeam from "../blocks/MeetOurTeam"; import OurImpact from "../blocks/OurImpact"; import OurPartners from "../blocks/OurPartners"; import PageHeader from "../blocks/PageHeader"; +import Stories from "../blocks/Stories"; import fullTitle from "../fields/fullTitle"; import slug from "../fields/slug"; import formatDraftUrl from "../utils/formatDraftUrl"; @@ -55,6 +56,7 @@ const Pages = { CustomPageHeader, OurImpact, OurPartners, + Stories, ], admin: { initCollapsed: true, From 13398a2f2575ac6d34b2eb5017a1fd95f9f8d30e Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 22 Sep 2023 10:31:26 +0300 Subject: [PATCH 04/25] Stories block --- .../src/lib/data/blockify/index.js | 2 ++ .../src/lib/data/blockify/stories.js | 32 +++++++++++++++++++ .../src/lib/data/longform/index.js | 0 3 files changed, 34 insertions(+) create mode 100644 apps/codeforafrica/src/lib/data/blockify/stories.js create mode 100644 apps/codeforafrica/src/lib/data/longform/index.js diff --git a/apps/codeforafrica/src/lib/data/blockify/index.js b/apps/codeforafrica/src/lib/data/blockify/index.js index 696f0540e..6a87db0fa 100644 --- a/apps/codeforafrica/src/lib/data/blockify/index.js +++ b/apps/codeforafrica/src/lib/data/blockify/index.js @@ -2,12 +2,14 @@ import getInvolved from "./get-involved"; import hero from "./hero"; import meetOurTeam from "./meetOurTeam"; import ourImpact from "./our-impact"; +import stories from "./stories"; const propsifyBlockBySlug = { hero, "meet-our-team": meetOurTeam, "our-impact": ourImpact, "get-involved": getInvolved, + "stories-list": stories, }; async function blockify(blocks) { diff --git a/apps/codeforafrica/src/lib/data/blockify/stories.js b/apps/codeforafrica/src/lib/data/blockify/stories.js new file mode 100644 index 000000000..98d2eb869 --- /dev/null +++ b/apps/codeforafrica/src/lib/data/blockify/stories.js @@ -0,0 +1,32 @@ +import { imageFromMedia } from "@/codeforafrica/lib/data/utils"; + +function stories(block) { + const { featured = {}, title, search, excerpt, ...other } = block; + const { + title: featuredStoryTitle, + coverImage: featuredStoryCoverImage, + excerpt: featuredStoryExcerpt, + } = featured; + + const featuredStory = { + title: featuredStoryTitle, + image: imageFromMedia({ + alt: featuredStoryTitle, + ...featuredStoryCoverImage, + }), + excerpt: featuredStoryExcerpt, + slug: "featured-story", + }; + + const storiesList = { + ...other, + slug: "stories-list", + }; + + return { + ...featuredStory, + storiesList, + }; +} + +export default stories; diff --git a/apps/codeforafrica/src/lib/data/longform/index.js b/apps/codeforafrica/src/lib/data/longform/index.js new file mode 100644 index 000000000..e69de29bb From ab7cc8e31566289824d0aaa17c56fe9a99e337d5 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:44:12 +0300 Subject: [PATCH 05/25] Blockified articles --- .../src/lib/data/blockify/index.js | 4 +- .../src/lib/data/blockify/stories.js | 57 +++++++++++++------ .../src/lib/data/common/index.js | 2 +- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/apps/codeforafrica/src/lib/data/blockify/index.js b/apps/codeforafrica/src/lib/data/blockify/index.js index 6a87db0fa..f3cc9611f 100644 --- a/apps/codeforafrica/src/lib/data/blockify/index.js +++ b/apps/codeforafrica/src/lib/data/blockify/index.js @@ -12,13 +12,13 @@ const propsifyBlockBySlug = { "stories-list": stories, }; -async function blockify(blocks) { +async function blockify(blocks, api) { const promises = blocks?.map(async (block) => { const slug = block.blockType; const propsifyBlock = propsifyBlockBySlug[slug]; if (propsifyBlock) { - return propsifyBlock(block); + return propsifyBlock(block, api); } return { ...block, diff --git a/apps/codeforafrica/src/lib/data/blockify/stories.js b/apps/codeforafrica/src/lib/data/blockify/stories.js index 98d2eb869..bcefa78e1 100644 --- a/apps/codeforafrica/src/lib/data/blockify/stories.js +++ b/apps/codeforafrica/src/lib/data/blockify/stories.js @@ -1,31 +1,56 @@ -import { imageFromMedia } from "@/codeforafrica/lib/data/utils"; - -function stories(block) { - const { featured = {}, title, search, excerpt, ...other } = block; +async function stories(block, api) { + const { featured = {}, title, search } = block; const { title: featuredStoryTitle, coverImage: featuredStoryCoverImage, excerpt: featuredStoryExcerpt, + slug: featuredStorySlug, } = featured; + const { docs: storyList } = await api.getCollection("story", { + where: { + slug: { + not_equals: featuredStorySlug, + }, + }, + }); + + const uniqueTags = new Set( + storyList + .reduce((acc, story) => { + const { tags = [] } = story; + return [...acc, ...tags.map((tag) => tag.name)]; + }, []) + .sort(), + ); + const featuredStory = { title: featuredStoryTitle, - image: imageFromMedia({ - alt: featuredStoryTitle, - ...featuredStoryCoverImage, - }), + image: featuredStoryCoverImage, excerpt: featuredStoryExcerpt, - slug: "featured-story", - }; - - const storiesList = { - ...other, - slug: "stories-list", + slug: featuredStorySlug, }; return { - ...featuredStory, - storiesList, + title, + search, + tags: Array.from(uniqueTags), + featured: featuredStory, + list: storyList.map((story) => { + const { + title: storyTitle, + coverImage: storyCoverImage, + excerpt: storyExcerpt, + slug: storySlug, + } = story; + return { + title: storyTitle, + image: storyCoverImage, + excerpt: storyExcerpt, + slug: storySlug, + }; + }), + slug: "stories", }; } diff --git a/apps/codeforafrica/src/lib/data/common/index.js b/apps/codeforafrica/src/lib/data/common/index.js index 56331a583..185b46a29 100644 --- a/apps/codeforafrica/src/lib/data/common/index.js +++ b/apps/codeforafrica/src/lib/data/common/index.js @@ -157,7 +157,7 @@ export async function getPageProps(api, context) { if (params?.slugs?.length > 2) { page = await pagify(page, api, context); } - const blocks = await blockify(page?.blocks); + const blocks = await blockify(page?.blocks, api); const settings = await api.findGlobal("settings"); const navbar = getNavBar(settings); const footer = getFooter(settings); From b98d40df921e2bcf1abb1f747a3febca305bc86b Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:59:38 +0300 Subject: [PATCH 06/25] Renamed stories to articles --- apps/codeforafrica/payload.config.ts | 4 ++-- apps/codeforafrica/src/lib/data/blockify/index.js | 2 +- apps/codeforafrica/src/lib/data/blockify/stories.js | 4 ++-- apps/codeforafrica/src/payload/blocks/Stories.js | 6 +++--- .../payload/collections/{Stories.js => Articles.js} | 10 +++++++--- .../src/payload/fields/{stories.js => articles.js} | 8 ++++---- 6 files changed, 19 insertions(+), 15 deletions(-) rename apps/codeforafrica/src/payload/collections/{Stories.js => Articles.js} (88%) rename apps/codeforafrica/src/payload/fields/{stories.js => articles.js} (55%) diff --git a/apps/codeforafrica/payload.config.ts b/apps/codeforafrica/payload.config.ts index 0e887c300..071c388a8 100644 --- a/apps/codeforafrica/payload.config.ts +++ b/apps/codeforafrica/payload.config.ts @@ -1,6 +1,7 @@ import path from "path"; import { buildConfig } from "payload/config"; +import Articles from "./src/payload/collections/Articles"; import Authors from "./src/payload/collections/Authors"; import GuidingPrinciples from "./src/payload/collections/GuidingPrinciples"; import Impact from "./src/payload/collections/Impact"; @@ -8,7 +9,6 @@ import Media from "./src/payload/collections/Media"; import Pages from "./src/payload/collections/Pages"; import Partners from "./src/payload/collections/Partners"; import Settings from "./src/payload/globals/Settings"; -import Stories from "./src/payload/collections/Stories"; import Tags from "./src/payload/collections/Tags"; import { CollectionConfig, GlobalConfig } from "payload/types"; import dotenv from "dotenv"; @@ -36,13 +36,13 @@ const adapter = s3Adapter({ export default buildConfig({ serverURL: appURL, collections: [ + Articles, Authors, GuidingPrinciples, Impact, Pages, Media, Partners, - Stories, Tags, ] as CollectionConfig[], globals: [Settings] as GlobalConfig[], diff --git a/apps/codeforafrica/src/lib/data/blockify/index.js b/apps/codeforafrica/src/lib/data/blockify/index.js index f3cc9611f..90d06ca2e 100644 --- a/apps/codeforafrica/src/lib/data/blockify/index.js +++ b/apps/codeforafrica/src/lib/data/blockify/index.js @@ -9,7 +9,7 @@ const propsifyBlockBySlug = { "meet-our-team": meetOurTeam, "our-impact": ourImpact, "get-involved": getInvolved, - "stories-list": stories, + stories, }; async function blockify(blocks, api) { diff --git a/apps/codeforafrica/src/lib/data/blockify/stories.js b/apps/codeforafrica/src/lib/data/blockify/stories.js index bcefa78e1..b2809ea1f 100644 --- a/apps/codeforafrica/src/lib/data/blockify/stories.js +++ b/apps/codeforafrica/src/lib/data/blockify/stories.js @@ -7,7 +7,7 @@ async function stories(block, api) { slug: featuredStorySlug, } = featured; - const { docs: storyList } = await api.getCollection("story", { + const { docs: storyList } = await api.getCollection("article", { where: { slug: { not_equals: featuredStorySlug, @@ -50,7 +50,7 @@ async function stories(block, api) { slug: storySlug, }; }), - slug: "stories", + slug: "articles", }; } diff --git a/apps/codeforafrica/src/payload/blocks/Stories.js b/apps/codeforafrica/src/payload/blocks/Stories.js index 6ebb2cc78..b97c1ab23 100644 --- a/apps/codeforafrica/src/payload/blocks/Stories.js +++ b/apps/codeforafrica/src/payload/blocks/Stories.js @@ -1,9 +1,9 @@ -import stories from "../fields/stories"; +import articles from "../fields/articles"; const Stories = { - slug: "stories-list", + slug: "stories", fields: [ - stories({ + articles({ name: "featured", label: "Featured Story", hasMany: false, diff --git a/apps/codeforafrica/src/payload/collections/Stories.js b/apps/codeforafrica/src/payload/collections/Articles.js similarity index 88% rename from apps/codeforafrica/src/payload/collections/Stories.js rename to apps/codeforafrica/src/payload/collections/Articles.js index 1423d99e5..c965ca1db 100644 --- a/apps/codeforafrica/src/payload/collections/Stories.js +++ b/apps/codeforafrica/src/payload/collections/Articles.js @@ -5,8 +5,12 @@ import richText from "../fields/richText"; import slug from "../fields/slug"; import tags from "../fields/tags"; -const Stories = { - slug: "story", +const Articles = { + slug: "article", + labels: { + singular: "Story", + plural: "Stories", + }, access: { read: () => true, }, @@ -50,4 +54,4 @@ const Stories = { ], }; -export default Stories; +export default Articles; diff --git a/apps/codeforafrica/src/payload/fields/stories.js b/apps/codeforafrica/src/payload/fields/articles.js similarity index 55% rename from apps/codeforafrica/src/payload/fields/stories.js rename to apps/codeforafrica/src/payload/fields/articles.js index e56a518ef..3f0aabf16 100644 --- a/apps/codeforafrica/src/payload/fields/stories.js +++ b/apps/codeforafrica/src/payload/fields/articles.js @@ -1,14 +1,14 @@ import { deepmerge } from "@mui/utils"; -const stories = (overrides) => +const articles = (overrides) => deepmerge( { - name: "stories", + name: "articles", type: "relationship", - relationTo: "story", + relationTo: "article", hasMany: true, }, overrides, ); -export default stories; +export default articles; From 556276cf46d37bc0f461575da9eff6d3536815de Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:58:57 +0300 Subject: [PATCH 07/25] Render stories list --- .../ArticleCardList/ArticleCardList.js | 4 +- .../src/components/ArticleGrid/ArticleGrid.js | 3 +- .../ArticleGrid/ArticleGrid.snap.js | 1 - .../src/components/Articles/Articles.js | 86 +++---------------- .../src/components/Articles/Articles.snap.js | 53 ++++++++++++ .../src/components/Articles/Articles.test.js | 10 ++- .../FeaturedArticle/FeaturedArticle.js | 24 +++--- .../FeaturedArticle/FeaturedArticle.snap.js | 16 ++-- .../FeaturedArticle/FeaturedArticle.test.js | 20 +++-- .../src/lib/data/blockify/stories.js | 29 ++++++- .../src/pages/[...slugs].page.js | 2 + apps/codeforafrica/src/utils/formatDate.js | 23 +++++ 12 files changed, 166 insertions(+), 105 deletions(-) create mode 100644 apps/codeforafrica/src/utils/formatDate.js diff --git a/apps/codeforafrica/src/components/ArticleCardList/ArticleCardList.js b/apps/codeforafrica/src/components/ArticleCardList/ArticleCardList.js index f66884e1f..1e5b68758 100644 --- a/apps/codeforafrica/src/components/ArticleCardList/ArticleCardList.js +++ b/apps/codeforafrica/src/components/ArticleCardList/ArticleCardList.js @@ -37,7 +37,7 @@ const ArticleCardList = React.forwardRef(function ArticleCardList(props, ref) { display: { xs: "none", sm: "block" }, height: "217.64px", }} - src={article.featureImage} + src={article.image.src} /> {article.title} @@ -45,7 +45,7 @@ const ArticleCardList = React.forwardRef(function ArticleCardList(props, ref) { sx={{ color: "#9F9494", display: "block", mt: 2 }} variant="caption" > - {article.publishedAt} + {article.publishedOn} diff --git a/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js b/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js index da277cd96..827b0bc5c 100644 --- a/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js +++ b/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js @@ -18,6 +18,7 @@ const ArticleGrid = React.forwardRef(function ArticleGrid(props, ref) { sx, tags, title, + searchLabel, ...other } = props; @@ -44,7 +45,7 @@ const ArticleGrid = React.forwardRef(function ArticleGrid(props, ref) { tag={selectedTag} tags={tags} SearchInputProps={{ - placeholder: "Search", + placeholder: searchLabel, }} sx={{ mb: { xs: 2.5, md: 5 }, diff --git a/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.snap.js b/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.snap.js index 00358526b..ea2ebac89 100644 --- a/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.snap.js +++ b/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.snap.js @@ -24,7 +24,6 @@ exports[` renders unchanged 1`] = ` aria-invalid="false" class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputTypeSearch MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd css-h7q3zr-MuiInputBase-input-MuiOutlinedInput-input" id=":r0:" - placeholder="Search" type="search" value="" /> diff --git a/apps/codeforafrica/src/components/Articles/Articles.js b/apps/codeforafrica/src/components/Articles/Articles.js index b8069cf6d..f995804f0 100644 --- a/apps/codeforafrica/src/components/Articles/Articles.js +++ b/apps/codeforafrica/src/components/Articles/Articles.js @@ -1,99 +1,35 @@ -import { useRouter } from "next/router"; -import React, { useEffect, useState } from "react"; - -import useArticles from "./useArticles"; +import React from "react"; import ArticleGrid from "@/codeforafrica/components/ArticleGrid"; import NextPreviousPagination from "@/codeforafrica/components/NextPreviousPagination"; -import useFilterQuery, { - ALL_TAG, -} from "@/codeforafrica/components/useFilterQuery"; -import equalsIgnoreCase from "@/codeforafrica/utils/equalsIgnoreCase"; const Articles = React.forwardRef(function Articles(props, ref) { const { - articles: { - pagination: { count: countProp, page: pageProp = 1 }, - results: resultsProp, - }, + articles, + featured, sx, tags, title, + search, + pagination: { count, page = 1 }, } = props; - const [articles, setArticles] = useState(resultsProp); - const [count, setCount] = useState(countProp); - const [featuredArticle, setFeaturedArticle] = useState(() => - resultsProp?.find((article) => article.featured), - ); - const [page, setPage] = useState(pageProp); - const [q, setQ] = useState(); - const [filtering, setFiltering] = useState(false); - const [tag, setTag] = useState(ALL_TAG); - const queryParams = useFilterQuery({ page, q, tag }); - const router = useRouter(); - - const handleChangePage = (_, value) => { - setPage(value); - }; - - const handleChangeQ = (_, value) => { - setQ(value || undefined); - }; - - const handleChangeTag = (_, value) => { - const newValue = - (value && tags.find((t) => equalsIgnoreCase(value, t))) || ALL_TAG; - setTag(newValue); - setPage(1); - }; - - useEffect(() => { - const isFiltering = page !== 1 || q || !equalsIgnoreCase(tag, ALL_TAG); - setFiltering(isFiltering); - }, [page, q, tag]); - const { data } = useArticles({ page, q, tag }); - useEffect(() => { - if (data) { - const { results, pagination } = data; - let newFeaturedArticle; - let newArticles = results; - if (!filtering) { - newFeaturedArticle = newArticles.find((article) => article.featured); - if (newFeaturedArticle) { - newArticles = newArticles.filter( - (article) => article.id !== newFeaturedArticle.id, - ); - } - } - setCount(pagination.count); - setFeaturedArticle( - newFeaturedArticle ? { ...newFeaturedArticle } : undefined, - ); - setArticles([...newArticles]); - } - }, [data, filtering]); + // TODO: Kelvin Handle filtering and pagination + const handleChangePage = () => {}; - useEffect(() => { - router.push(queryParams, undefined, { - scroll: true, - shallow: true, - }); + const handleChangeQ = () => {}; - // We don't want to listen to router changes here since we're the ones - // updating them - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [queryParams]); + const handleChangeTag = () => {}; return (
diff --git a/apps/codeforafrica/src/components/Articles/Articles.snap.js b/apps/codeforafrica/src/components/Articles/Articles.snap.js index 6ada19eca..9ef33b963 100644 --- a/apps/codeforafrica/src/components/Articles/Articles.snap.js +++ b/apps/codeforafrica/src/components/Articles/Articles.snap.js @@ -12,6 +12,11 @@ exports[` renders unchanged 1`] = `
+
+ Title +
@@ -58,10 +63,58 @@ exports[` renders unchanged 1`] = `
+
+
+ + tag1 + +
+
+ + tag2 + +
+
+ `; diff --git a/apps/codeforafrica/src/components/Articles/Articles.test.js b/apps/codeforafrica/src/components/Articles/Articles.test.js index 9be808705..0d1955901 100644 --- a/apps/codeforafrica/src/components/Articles/Articles.test.js +++ b/apps/codeforafrica/src/components/Articles/Articles.test.js @@ -9,7 +9,15 @@ import theme from "@/codeforafrica/theme"; const render = createRender({ theme }); const defaultProps = { - articles: { pagination: {}, results: [] }, + articles: [], + featured: [], + pagination: { + count: 10, + page: 1, + }, + search: "Search", + tags: ["tag1", "tag2"], + title: "Title", }; describe("", () => { diff --git a/apps/codeforafrica/src/components/FeaturedArticle/FeaturedArticle.js b/apps/codeforafrica/src/components/FeaturedArticle/FeaturedArticle.js index 0d7e932de..c6d89037c 100644 --- a/apps/codeforafrica/src/components/FeaturedArticle/FeaturedArticle.js +++ b/apps/codeforafrica/src/components/FeaturedArticle/FeaturedArticle.js @@ -6,13 +6,14 @@ import React from "react"; import ArticleCard from "@/codeforafrica/components/ArticleCard"; import ArticleCardContent from "@/codeforafrica/components/ArticleCardContent"; import ArticleCardMedia from "@/codeforafrica/components/ArticleCardMedia"; +import RichText from "@/codeforafrica/components/RichText"; const FeaturedArticle = React.forwardRef(function FeaturedArticle(props, ref) { const { excerpt, - featureImage, + image, href, - publishedAt, + publishedOn, sx, title, variant = "standard", @@ -35,8 +36,8 @@ const FeaturedArticle = React.forwardRef(function FeaturedArticle(props, ref) { {title} - - {excerpt} - + /> renders unchanged 1`] = ` tabindex="0" type="button" > - READ STORY + Read Story { - const { - title: storyTitle, - coverImage: storyCoverImage, - excerpt: storyExcerpt, - slug: storySlug, - publishedOn: storyPublishedOn, - } = story; - return { - title: storyTitle, - image: storyCoverImage, - excerpt: storyExcerpt, - publishedOn: formatDate(storyPublishedOn, { - includeTime: false, - month: "short", - }), - href: `/stories/${storySlug}`, - }; - }), + featured: featuredStory || null, + articles, pagination: { count: totalPages, page, diff --git a/apps/codeforafrica/src/payload/blocks/Stories.js b/apps/codeforafrica/src/payload/blocks/Stories.js index b97c1ab23..dcabf847d 100644 --- a/apps/codeforafrica/src/payload/blocks/Stories.js +++ b/apps/codeforafrica/src/payload/blocks/Stories.js @@ -15,11 +15,25 @@ const Stories = { type: "text", }, { - name: "search", - label: "Search Label", - required: true, - type: "text", - defaultValue: "Search Stories", + name: "labels", + label: "Labels", + type: "group", + fields: [ + { + name: "search", + label: "Search", + required: true, + type: "text", + defaultValue: "Search Stories", + }, + { + name: "readMore", + label: "Read More", + required: true, + type: "text", + defaultValue: "Read More", + }, + ], }, ], }; From c5284424298d5aa665057458ee84a9f98ab22eb2 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:55:12 +0300 Subject: [PATCH 10/25] Render featured story --- .../src/components/ArticleGrid/ArticleGrid.js | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js b/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js index 25afbebec..129229596 100644 --- a/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js +++ b/apps/codeforafrica/src/components/ArticleGrid/ArticleGrid.js @@ -53,29 +53,30 @@ const ArticleGrid = React.forwardRef(function ArticleGrid(props, ref) { }} /> - {articles?.length > 0 ? ( - <> - {featuredArticle ? ( - - - - ) : null} + + <> + {featuredArticle ? ( + + + + ) : null} + {articles?.length > 0 ? ( - - ) : null} + ) : null} + ); From 490073c0f1560b510651e0cc97ee4452f8196ec3 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:21:13 +0300 Subject: [PATCH 11/25] Add pagination use effect --- .../src/components/Articles/Articles.js | 59 ++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/apps/codeforafrica/src/components/Articles/Articles.js b/apps/codeforafrica/src/components/Articles/Articles.js index 15a73ebe2..7ff88c67a 100644 --- a/apps/codeforafrica/src/components/Articles/Articles.js +++ b/apps/codeforafrica/src/components/Articles/Articles.js @@ -1,31 +1,76 @@ -import React from "react"; +import { useRouter } from "next/router"; +import React, { useState, useEffect } from "react"; + +import useArticles from "./useArticles"; import ArticleGrid from "@/codeforafrica/components/ArticleGrid"; import NextPreviousPagination from "@/codeforafrica/components/NextPreviousPagination"; +import useFilterQuery from "@/codeforafrica/components/useFilterQuery"; const Articles = React.forwardRef(function Articles(props, ref) { const { - articles, + articles: articlesList, featured, sx, tags, title, labels: { search, readMore }, - pagination: { count, page = 1 }, + pagination: { count: countProp, page: pageProp = 1 }, } = props; + const [articles, setArticles] = useState(articlesList); + const [count, setCount] = useState(countProp); + const [featuredArticle, setFeaturedArticle] = useState(featured); + const [page, setPage] = useState(pageProp); + const [filtering, setFiltering] = useState(false); + const queryParams = useFilterQuery({ page }); + const router = useRouter(); + const handleChangePage = (_, value) => { + setPage(value); + }; - // TODO: Kelvin Handle filtering and pagination - const handleChangePage = () => {}; - + // TODO: Kelvin Handle filtering a const handleChangeQ = () => {}; const handleChangeTag = () => {}; + useEffect(() => { + const isFiltering = page !== 1; + setFiltering(isFiltering); + }, [page]); + + const { data } = useArticles({ page }); + useEffect(() => { + if (data) { + const { + articles: results, + featured: newFeaturedArticle, + pagination, + } = data; + + if (!filtering) { + setFeaturedArticle(newFeaturedArticle); + } + setCount(pagination.count); + setArticles(results); + } + }, [data, filtering]); + + useEffect(() => { + router.push(queryParams, undefined, { + scroll: true, + shallow: true, + }); + + // We don't want to listen to router changes here since we're the ones + // updating them + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [queryParams]); + return (
Date: Mon, 25 Sep 2023 13:32:09 +0300 Subject: [PATCH 12/25] Regenerate snapshots --- .../src/components/Articles/Articles.snap.js | 131 ++++++++++++++++++ .../src/components/Articles/Articles.test.js | 44 +++++- 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/apps/codeforafrica/src/components/Articles/Articles.snap.js b/apps/codeforafrica/src/components/Articles/Articles.snap.js index 9ef33b963..3022be3e6 100644 --- a/apps/codeforafrica/src/components/Articles/Articles.snap.js +++ b/apps/codeforafrica/src/components/Articles/Articles.snap.js @@ -94,6 +94,137 @@ exports[` renders unchanged 1`] = `
+ +