aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pages/blog/index.tsx90
-rw-r--r--src/services/graphql/api.ts10
-rw-r--r--src/services/graphql/thematics.query.ts11
-rw-r--r--src/services/graphql/thematics.ts34
-rw-r--r--src/services/graphql/topics.query.ts11
-rw-r--r--src/services/graphql/topics.ts42
6 files changed, 188 insertions, 10 deletions
diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx
index 1e7581c..05e73db 100644
--- a/src/pages/blog/index.tsx
+++ b/src/pages/blog/index.tsx
@@ -1,5 +1,9 @@
+import Notice from '@components/atoms/layout/notice';
import { type BreadcrumbItem } from '@components/molecules/nav/breadcrumb';
import PostsList, { type Post } from '@components/organisms/layout/posts-list';
+import LinksListWidget, {
+ LinksListItems,
+} from '@components/organisms/widgets/links-list-widget';
import PageLayout from '@components/templates/page/page-layout';
import { type EdgesResponse } from '@services/graphql/api';
import {
@@ -7,8 +11,17 @@ import {
getArticles,
getTotalArticles,
} from '@services/graphql/articles';
+import {
+ getThematicsPreview,
+ getTotalThematics,
+} from '@services/graphql/thematics';
+import { getTopicsPreview, getTotalTopics } from '@services/graphql/topics';
import { type Article, type Meta } from '@ts/types/app';
-import { type RawArticle } from '@ts/types/raw-data';
+import {
+ RawThematicPreview,
+ RawTopicPreview,
+ type RawArticle,
+} from '@ts/types/raw-data';
import { settings } from '@utils/config';
import { loadTranslation, type Messages } from '@utils/helpers/i18n';
import usePagination from '@utils/hooks/use-pagination';
@@ -22,6 +35,8 @@ import { Blog, Graph, WebPage } from 'schema-dts';
type BlogPageProps = {
articles: EdgesResponse<RawArticle>;
+ thematicsList: RawThematicPreview[];
+ topicsList: RawTopicPreview[];
totalArticles: number;
translation: Messages;
};
@@ -29,7 +44,12 @@ type BlogPageProps = {
/**
* Blog index page.
*/
-const BlogPage: NextPage<BlogPageProps> = ({ articles, totalArticles }) => {
+const BlogPage: NextPage<BlogPageProps> = ({
+ articles,
+ thematicsList,
+ topicsList,
+ totalArticles,
+}) => {
const intl = useIntl();
const title = intl.formatMessage({
defaultMessage: 'Blog',
@@ -183,6 +203,32 @@ const BlogPage: NextPage<BlogPageProps> = ({ articles, totalArticles }) => {
setSize((prevSize) => prevSize + 1);
};
+ const getLinksListItems = (
+ rawData: RawThematicPreview[] | RawTopicPreview[],
+ kind: 'thematic' | 'topic'
+ ): LinksListItems[] => {
+ const baseUrl = kind === 'thematic' ? '/thematique/' : '/sujet/';
+
+ return rawData.map((taxonomy) => {
+ return {
+ name: taxonomy.title,
+ url: `${baseUrl}${taxonomy.slug}`,
+ };
+ });
+ };
+
+ const thematicsListTitle = intl.formatMessage({
+ defaultMessage: 'Thematics',
+ description: 'BlogPage: thematics list widget title',
+ id: 'HriY57',
+ });
+
+ const topicsListTitle = intl.formatMessage({
+ defaultMessage: 'Topics',
+ description: 'BlogPage: topics list widget title',
+ id: '2D9tB5',
+ });
+
return (
<>
<Head>
@@ -202,6 +248,20 @@ const BlogPage: NextPage<BlogPageProps> = ({ articles, totalArticles }) => {
title={title}
breadcrumb={breadcrumb}
headerMeta={{ total: postsCount }}
+ widgets={[
+ <LinksListWidget
+ key="thematics-list"
+ items={getLinksListItems(thematicsList, 'thematic')}
+ title={thematicsListTitle}
+ level={2}
+ />,
+ <LinksListWidget
+ key="topics-list"
+ items={getLinksListItems(topicsList, 'topic')}
+ title={topicsListTitle}
+ level={2}
+ />,
+ ]}
>
{data && (
<PostsList
@@ -213,25 +273,37 @@ const BlogPage: NextPage<BlogPageProps> = ({ articles, totalArticles }) => {
total={totalArticles}
/>
)}
- {error &&
- intl.formatMessage({
- defaultMessage: 'Failed to load.',
- description: 'BlogPage: failed to load text',
- id: 'C/XGkH',
- })}
+ {error && (
+ <Notice
+ kind="error"
+ message={intl.formatMessage({
+ defaultMessage: 'Failed to load.',
+ description: 'BlogPage: failed to load text',
+ id: 'C/XGkH',
+ })}
+ />
+ )}
</PageLayout>
</>
);
};
-export const getStaticProps: GetStaticProps = async ({ locale }) => {
+export const getStaticProps: GetStaticProps<BlogPageProps> = async ({
+ locale,
+}) => {
const articles = await getArticles({ first: settings.postsPerPage });
const totalArticles = await getTotalArticles();
+ const totalThematics = await getTotalThematics();
+ const thematics = await getThematicsPreview({ first: totalThematics });
+ const totalTopics = await getTotalTopics();
+ const topics = await getTopicsPreview({ first: totalTopics });
const translation = await loadTranslation(locale);
return {
props: {
articles: JSON.parse(JSON.stringify(articles)),
+ thematicsList: thematics.edges.map((edge) => edge.node),
+ topicsList: topics.edges.map((edge) => edge.node),
totalArticles,
translation,
},
diff --git a/src/services/graphql/api.ts b/src/services/graphql/api.ts
index 9811d86..5bed9f9 100644
--- a/src/services/graphql/api.ts
+++ b/src/services/graphql/api.ts
@@ -12,11 +12,13 @@ import {
thematicBySlugQuery,
thematicsListQuery,
thematicsSlugQuery,
+ totalThematicsQuery,
} from './thematics.query';
import {
topicBySlugQuery,
topicsListQuery,
topicsSlugQuery,
+ totalTopicsQuery,
} from './topics.query';
export type Mutations = typeof sendMailMutation;
@@ -33,7 +35,9 @@ export type Queries =
| typeof topicBySlugQuery
| typeof topicsListQuery
| typeof topicsSlugQuery
- | typeof totalArticlesQuery;
+ | typeof totalArticlesQuery
+ | typeof totalThematicsQuery
+ | typeof totalTopicsQuery;
export type ArticleResponse<T> = {
post: T;
@@ -105,6 +109,8 @@ export type ResponseMap<T> = {
[topicsListQuery]: TopicsResponse<EdgesResponse<T>>;
[topicsSlugQuery]: TopicsResponse<EdgesResponse<T>>;
[totalArticlesQuery]: ArticlesResponse<T>;
+ [totalThematicsQuery]: ThematicsResponse<T>;
+ [totalTopicsQuery]: TopicsResponse<T>;
};
export type GraphQLResponse<
@@ -162,6 +168,8 @@ export type VariablesMap = {
[topicsListQuery]: EdgesVars;
[topicsSlugQuery]: EdgesVars;
[totalArticlesQuery]: null;
+ [totalThematicsQuery]: null;
+ [totalTopicsQuery]: null;
};
export type FetchAPIProps<T extends Queries | Mutations> = {
diff --git a/src/services/graphql/thematics.query.ts b/src/services/graphql/thematics.query.ts
index 76949ad..db8e751 100644
--- a/src/services/graphql/thematics.query.ts
+++ b/src/services/graphql/thematics.query.ts
@@ -114,3 +114,14 @@ export const thematicsSlugQuery = `query ThematicsSlug($first: Int = 10, $after:
}
}
}`;
+
+/**
+ * Query the total number of thematics.
+ */
+export const totalThematicsQuery = `query ThematicsTotal {
+ thematics {
+ pageInfo {
+ total
+ }
+ }
+}`;
diff --git a/src/services/graphql/thematics.ts b/src/services/graphql/thematics.ts
new file mode 100644
index 0000000..7003e08
--- /dev/null
+++ b/src/services/graphql/thematics.ts
@@ -0,0 +1,34 @@
+import { RawThematicPreview, TotalItems } from '@ts/types/raw-data';
+import { EdgesResponse, EdgesVars, fetchAPI, getAPIUrl } from './api';
+import { thematicsListQuery, totalThematicsQuery } from './thematics.query';
+
+/**
+ * Retrieve the total number of thematics.
+ *
+ * @returns {Promise<number>} - The thematics total number.
+ */
+export const getTotalThematics = async (): Promise<number> => {
+ const response = await fetchAPI<TotalItems, typeof totalThematicsQuery>({
+ api: getAPIUrl(),
+ query: totalThematicsQuery,
+ });
+
+ return response.thematics.pageInfo.total;
+};
+
+/**
+ * Retrieve the given number of thematics from API.
+ *
+ * @param {EdgesVars} props - An object of GraphQL variables.
+ * @returns {Promise<EdgesResponse<RawThematicPreview>>} The thematics data.
+ */
+export const getThematicsPreview = async (
+ props: EdgesVars
+): Promise<EdgesResponse<RawThematicPreview>> => {
+ const response = await fetchAPI<
+ RawThematicPreview,
+ typeof thematicsListQuery
+ >({ api: getAPIUrl(), query: thematicsListQuery, variables: props });
+
+ return response.thematics;
+};
diff --git a/src/services/graphql/topics.query.ts b/src/services/graphql/topics.query.ts
index 8783799..6cc525e 100644
--- a/src/services/graphql/topics.query.ts
+++ b/src/services/graphql/topics.query.ts
@@ -115,3 +115,14 @@ export const topicsSlugQuery = `query TopicsSlug($first: Int = 10, $after: Strin
}
}
}`;
+
+/**
+ * Query the total number of topics.
+ */
+export const totalTopicsQuery = `query TopicsTotal {
+ topics {
+ pageInfo {
+ total
+ }
+ }
+}`;
diff --git a/src/services/graphql/topics.ts b/src/services/graphql/topics.ts
new file mode 100644
index 0000000..0f59bad
--- /dev/null
+++ b/src/services/graphql/topics.ts
@@ -0,0 +1,42 @@
+import { RawTopicPreview, TotalItems } from '@ts/types/raw-data';
+import { EdgesResponse, EdgesVars, fetchAPI, getAPIUrl } from './api';
+import { topicsListQuery, totalTopicsQuery } from './topics.query';
+
+/**
+ * Retrieve the total number of topics.
+ *
+ * @returns {Promise<number>} - The topics total number.
+ */
+export const getTotalTopics = async (): Promise<number> => {
+ const response = await fetchAPI<TotalItems, typeof totalTopicsQuery>({
+ api: getAPIUrl(),
+ query: totalTopicsQuery,
+ });
+
+ return response.topics.pageInfo.total;
+};
+
+/**
+ * Retrieve the given number of topics from API.
+ *
+ * @param {EdgesVars} props - An object of GraphQL variables.
+ * @returns {Promise<EdgesResponse<RawTopicPreview>>} The topics data.
+ */
+export const getTopicsPreview = async (
+ props: EdgesVars
+): Promise<EdgesResponse<RawTopicPreview>> => {
+ const response = await fetchAPI<RawTopicPreview, typeof topicsListQuery>({
+ api: getAPIUrl(),
+ query: topicsListQuery,
+ variables: props,
+ });
+
+ return response.topics;
+};
+
+export const getAllTopicsLinks = async () => {
+ const allTopics = [];
+ const initialTopics = await getTopicsPreview({ first: 1 });
+
+ if (!initialTopics.pageInfo.hasNextPage) return initialTopics;
+};