diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-13 19:29:41 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-05-13 22:35:55 +0200 |
| commit | 5f3799ee75b3ac5cffe726023d8e5df129b919dd (patch) | |
| tree | 573fddbe37e2257d67d81693ed0be5c46f049f2a /src/services | |
| parent | 06ea295857e508a830669cb402d2156204309b1e (diff) | |
chore: add Thematic page
Diffstat (limited to 'src/services')
| -rw-r--r-- | src/services/graphql/thematics.query.ts | 7 | ||||
| -rw-r--r-- | src/services/graphql/thematics.ts | 133 |
2 files changed, 138 insertions, 2 deletions
diff --git a/src/services/graphql/thematics.query.ts b/src/services/graphql/thematics.query.ts index db8e751..3b3ebd6 100644 --- a/src/services/graphql/thematics.query.ts +++ b/src/services/graphql/thematics.query.ts @@ -15,6 +15,13 @@ export const thematicBySlugQuery = `query ThematicBy($slug: ID!) { } } } + author { + node { + gravatarUrl + name + url + } + } commentCount contentParts { beforeMore diff --git a/src/services/graphql/thematics.ts b/src/services/graphql/thematics.ts index 7003e08..e526db8 100644 --- a/src/services/graphql/thematics.ts +++ b/src/services/graphql/thematics.ts @@ -1,6 +1,20 @@ -import { RawThematicPreview, TotalItems } from '@ts/types/raw-data'; +import { PageLink, Slug, Thematic } from '@ts/types/app'; +import { + RawArticle, + RawThematic, + RawThematicPreview, + TotalItems, +} from '@ts/types/raw-data'; +import { getImageFromRawData } from '@utils/helpers/images'; +import { getPageLinkFromRawData } from '@utils/helpers/pages'; import { EdgesResponse, EdgesVars, fetchAPI, getAPIUrl } from './api'; -import { thematicsListQuery, totalThematicsQuery } from './thematics.query'; +import { getArticleFromRawData } from './articles'; +import { + thematicBySlugQuery, + thematicsListQuery, + thematicsSlugQuery, + totalThematicsQuery, +} from './thematics.query'; /** * Retrieve the total number of thematics. @@ -32,3 +46,118 @@ export const getThematicsPreview = async ( return response.thematics; }; + +/** + * Convert raw data to an Thematic object. + * + * @param {RawThematic} data - The page raw data. + * @returns {Thematic} The page data. + */ +export const getThematicFromRawData = (data: RawThematic): Thematic => { + const { + acfThematics, + contentParts, + databaseId, + date, + featuredImage, + info, + modified, + slug, + title, + seo, + } = data; + + /** + * Retrieve an array of related topics. + * + * @param posts - The thematic posts. + * @returns {PageLink[]} An array of topics links. + */ + const getRelatedTopics = (posts: RawArticle[]): PageLink[] => { + const topics: PageLink[] = []; + + posts.forEach((post) => { + if (post.acfPosts.postsInTopic) { + post.acfPosts.postsInTopic.forEach((topic) => + topics.push(getPageLinkFromRawData(topic)) + ); + } + }); + + const topicsIds = topics.map((topic) => topic.id); + const uniqueTopics = topics.filter( + ({ id }, index) => !topicsIds.includes(id, index + 1) + ); + const sortTopicByName = (a: PageLink, b: PageLink) => { + var nameA = a.name.toUpperCase(); // ignore upper and lowercase + var nameB = b.name.toUpperCase(); // ignore upper and lowercase + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } + + // names must be equal + return 0; + }; + + return uniqueTopics.sort(sortTopicByName); + }; + + return { + content: contentParts.afterMore, + id: databaseId, + intro: contentParts.beforeMore, + meta: { + articles: acfThematics.postsInThematic.map((post) => + getArticleFromRawData(post) + ), + cover: featuredImage?.node + ? getImageFromRawData(featuredImage.node) + : undefined, + dates: { publication: date, update: modified }, + readingTime: info.readingTime, + seo: { + description: seo?.metaDesc || '', + title: seo?.title || '', + }, + topics: getRelatedTopics(acfThematics.postsInThematic), + wordsCount: info.wordsCount, + }, + slug, + title, + }; +}; + +/** + * Retrieve a Thematic object by slug. + * + * @param {string} slug - The thematic slug. + * @returns {Promise<Article>} The requested thematic. + */ +export const getThematicBySlug = async (slug: string): Promise<Thematic> => { + const response = await fetchAPI<RawThematic, typeof thematicBySlugQuery>({ + api: getAPIUrl(), + query: thematicBySlugQuery, + variables: { slug }, + }); + + return getThematicFromRawData(response.thematic); +}; + +/** + * Retrieve all the thematics slugs. + * + * @returns {Promise<string[]>} - An array of thematics slugs. + */ +export const getAllThematicsSlugs = async (): Promise<string[]> => { + const totalThematics = await getTotalThematics(); + const response = await fetchAPI<Slug, typeof thematicsSlugQuery>({ + api: getAPIUrl(), + query: thematicsSlugQuery, + variables: { first: totalThematics }, + }); + + return response.thematics.edges.map((edge) => edge.node.slug); +}; |
