aboutsummaryrefslogtreecommitdiffstats
path: root/src/services
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-05-13 19:29:41 +0200
committerArmand Philippot <git@armandphilippot.com>2022-05-13 22:35:55 +0200
commit5f3799ee75b3ac5cffe726023d8e5df129b919dd (patch)
tree573fddbe37e2257d67d81693ed0be5c46f049f2a /src/services
parent06ea295857e508a830669cb402d2156204309b1e (diff)
chore: add Thematic page
Diffstat (limited to 'src/services')
-rw-r--r--src/services/graphql/thematics.query.ts7
-rw-r--r--src/services/graphql/thematics.ts133
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);
+};