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); +}; | 
