aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pages/projets/[slug].tsx239
-rw-r--r--src/utils/hooks/use-github-repo-meta/use-github-repo-meta.ts32
2 files changed, 124 insertions, 147 deletions
diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx
index 958f61f..b29c477 100644
--- a/src/pages/projets/[slug].tsx
+++ b/src/pages/projets/[slug].tsx
@@ -1,9 +1,10 @@
+/* eslint-disable max-statements */
import type { MDXComponents } from 'mdx/types';
import type { GetStaticPaths, GetStaticProps } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import NextImage from 'next/image';
-import { useMemo, type ComponentType, type FC } from 'react';
+import { useMemo, type ComponentType, useCallback } from 'react';
import { useIntl } from 'react-intl';
import {
Heading,
@@ -20,7 +21,7 @@ import {
Spinner,
Time,
getLayout,
- type ProjectOverviewProps,
+ type OverviewMeta,
} from '../../components';
import { mdxComponents } from '../../components/mdx';
import { fetchGithubRepoMeta } from '../../services/github';
@@ -30,7 +31,6 @@ import type {
Maybe,
NextPageWithLayout,
Project,
- ProjectMeta,
} from '../../types';
import { CONFIG } from '../../utils/config';
import {
@@ -71,107 +71,6 @@ const getGithubRepoInputFrom = (namespace: string) => {
const isValidRepo = (name: string): name is 'github' | 'gitlab' =>
['github', 'gitlab'].includes(name);
-type GithubRepoOverviewProps = Omit<
- ProjectOverviewProps,
- 'cover' | 'meta' | 'name'
-> &
- Pick<ProjectMeta, 'cover' | 'license' | 'technologies'> & {
- repos: {
- github: string;
- gitlab?: string;
- };
- title: string;
- };
-
-const GithubRepoOverview: FC<GithubRepoOverviewProps> = ({
- cover,
- license,
- repos,
- technologies,
- title,
- ...props
-}) => {
- const intl = useIntl();
- const { isLoading, meta: repoMeta } = useGithubRepoMeta(
- getGithubRepoInputFrom(repos.github)
- );
- const reposLabels = {
- github: intl.formatMessage({
- defaultMessage: 'Github',
- description: 'ProjectPage: Github repo label',
- id: 'l82UU5',
- }),
- gitlab: intl.formatMessage({
- defaultMessage: 'Gitlab',
- description: 'ProjectPage: Gitlab repo label',
- id: '1msHuZ',
- }),
- };
- const stars = intl.formatMessage(
- {
- defaultMessage:
- '{starsCount, plural, =0 {No stars} one {# star} other {# stars}}',
- description: 'ProjectPage: stars count',
- id: '4M71hp',
- },
- { starsCount: repoMeta?.stargazerCount }
- );
- const popularityURL = `https://github.com/${repos.github}/stargazers`;
-
- return isLoading ? (
- <Spinner>
- {intl.formatMessage({
- defaultMessage: 'Loading the repository metadata...',
- description: 'ProjectPage: loading repository metadata',
- id: 'EET/tC',
- })}
- </Spinner>
- ) : (
- <ProjectOverview
- {...props}
- cover={cover ? <NextImage {...cover} /> : undefined}
- meta={{
- creationDate: repoMeta?.createdAt ? (
- <Time date={repoMeta.createdAt} />
- ) : undefined,
- lastUpdateDate: repoMeta?.updatedAt ? (
- <Time date={repoMeta.updatedAt} />
- ) : undefined,
- license,
- popularity: (
- <>
- ⭐&nbsp;<Link href={popularityURL}>{stars}</Link>
- </>
- ),
- repositories: Object.entries(repos)
- .map(([key, value]): Maybe<MetaValues> => {
- if (!isValidRepo(key)) return undefined;
-
- return {
- id: key,
- value: (
- <SocialLink
- icon={capitalize(key)}
- key={key}
- label={reposLabels[key]}
- url={value}
- />
- ),
- };
- })
- .filter((entry): entry is MetaValues => !!entry),
- technologies: technologies?.map((techno) => {
- return {
- id: techno,
- value: techno,
- };
- }),
- }}
- name={title}
- />
- );
-};
-
type ProjectPageProps = {
data: {
githubMeta: Maybe<GithubRepositoryMeta>;
@@ -189,6 +88,11 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ data }) => {
const { items: breadcrumbItems, schema: breadcrumbSchema } =
useBreadcrumbs(title);
const { ref, tree } = useHeadingsTree<HTMLDivElement>({ fromLevel: 2 });
+ const { isLoading: isGithubMetaLoading, meta: githubMeta } =
+ useGithubRepoMeta(
+ meta.repos.github ? getGithubRepoInputFrom(meta.repos.github) : null,
+ data.githubMeta
+ );
const page = {
title: `${meta.seo.title} - ${CONFIG.name}`,
@@ -209,6 +113,11 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ data }) => {
const messages = {
repos: {
+ github: intl.formatMessage({
+ defaultMessage: 'Github',
+ description: 'ProjectPage: Github repo label',
+ id: 'l82UU5',
+ }),
gitlab: intl.formatMessage({
defaultMessage: 'Gitlab',
description: 'ProjectPage: Gitlab repo label',
@@ -229,6 +138,65 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ data }) => {
},
};
+ const getAdditionalMeta = useCallback(
+ (
+ repo: string,
+ repoMeta: Maybe<GithubRepositoryMeta>
+ ): Partial<OverviewMeta> => {
+ const loading = {
+ creationDate: intl.formatMessage({
+ defaultMessage: 'Loading the repository creation date...',
+ description: 'ProjectPage: loading repository metadata',
+ id: 'OzVOKP',
+ }),
+ popularity: intl.formatMessage({
+ defaultMessage: 'Loading the repository popularity...',
+ description: 'ProjectPage: loading repository metadata',
+ id: 'RfXzNe',
+ }),
+ updateDate: intl.formatMessage({
+ defaultMessage: 'Loading the repository update date...',
+ description: 'ProjectPage: loading repository metadata',
+ id: 'VEHEEs',
+ }),
+ };
+ const stars = intl.formatMessage(
+ {
+ defaultMessage:
+ '{starsCount, plural, =0 {No stars} one {# star} other {# stars}}',
+ description: 'ProjectPage: stars count',
+ id: '4M71hp',
+ },
+ { starsCount: repoMeta?.stargazerCount }
+ );
+ const popularityURL = `https://github.com/${repo}/stargazers`;
+
+ return {
+ creationDate:
+ isGithubMetaLoading || !repoMeta ? (
+ <Spinner aria-label={loading.creationDate} />
+ ) : (
+ <Time date={repoMeta.createdAt} />
+ ),
+ lastUpdateDate:
+ isGithubMetaLoading || !repoMeta ? (
+ <Spinner aria-label={loading.updateDate} />
+ ) : (
+ <Time date={repoMeta.updatedAt} />
+ ),
+ popularity:
+ isGithubMetaLoading || !repoMeta ? (
+ <Spinner aria-label={loading.popularity} />
+ ) : (
+ <>
+ ⭐&nbsp;<Link href={popularityURL}>{stars}</Link>
+ </>
+ ),
+ };
+ },
+ [intl, isGithubMetaLoading]
+ );
+
const ProjectContent: ComponentType<MDXComponents> = useMemo(
() =>
dynamic(async () => import(`../../content/projects/${id}.mdx`), {
@@ -269,39 +237,40 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ data }) => {
/>
</PageSidebar>
<PageBody ref={ref}>
- {meta.repos.github ? (
- <GithubRepoOverview
- className={styles.overview}
- cover={meta.cover}
- license={meta.license}
- repos={{ github: meta.repos.github, gitlab: meta.repos.gitlab }}
- technologies={meta.technologies}
- title={title}
- />
- ) : (
- <ProjectOverview
- className={styles.overview}
- cover={meta.cover ? <NextImage {...meta.cover} /> : undefined}
- meta={{
- license: meta.license,
- repositories: meta.repos.gitlab ? (
- <SocialLink
- // eslint-disable-next-line react/jsx-no-literals
- icon="Gitlab"
- label={messages.repos.gitlab}
- url={meta.repos.gitlab}
- />
- ) : undefined,
- technologies: meta.technologies?.map((techno) => {
+ <ProjectOverview
+ className={styles.overview}
+ cover={meta.cover ? <NextImage {...meta.cover} /> : undefined}
+ meta={{
+ ...(githubMeta === null || !meta.repos.github
+ ? {}
+ : getAdditionalMeta(meta.repos.github, githubMeta)),
+ license: meta.license,
+ repositories: Object.entries(meta.repos)
+ .map(([key, value]): Maybe<MetaValues> => {
+ if (!isValidRepo(key)) return undefined;
+
return {
- id: techno,
- value: techno,
+ id: key,
+ value: (
+ <SocialLink
+ icon={capitalize(key)}
+ key={key}
+ label={messages.repos[key]}
+ url={value}
+ />
+ ),
};
- }),
- }}
- name={title}
- />
- )}
+ })
+ .filter((entry): entry is MetaValues => !!entry),
+ technologies: meta.technologies?.map((techno) => {
+ return {
+ id: techno,
+ value: techno,
+ };
+ }),
+ }}
+ name={title}
+ />
<ProjectContent components={mdxComponents} />
</PageBody>
<PageSidebar>
diff --git a/src/utils/hooks/use-github-repo-meta/use-github-repo-meta.ts b/src/utils/hooks/use-github-repo-meta/use-github-repo-meta.ts
index 888682e..3567311 100644
--- a/src/utils/hooks/use-github-repo-meta/use-github-repo-meta.ts
+++ b/src/utils/hooks/use-github-repo-meta/use-github-repo-meta.ts
@@ -3,19 +3,27 @@ import {
type FetchGithubRepoMetaInput,
fetchGithubRepoMeta,
} from '../../../services/github';
-import type { GithubRepositoryMeta, Maybe } from '../../../types';
+import type { GithubRepositoryMeta, Maybe, Nullable } from '../../../types';
-export type UseGithubRepoMetaReturn<T extends Maybe<GithubRepositoryMeta>> = {
- isError: boolean;
- isLoading: boolean;
- isValidating: boolean;
- meta: T extends undefined
- ? Maybe<GithubRepositoryMeta>
- : GithubRepositoryMeta;
+export type UseGithubRepoMetaReturn<
+ I extends Nullable<FetchGithubRepoMetaInput>,
+ T extends Maybe<GithubRepositoryMeta>,
+> = {
+ isError: I extends null ? false : boolean;
+ isLoading: I extends null ? false : boolean;
+ isValidating: I extends null ? false : boolean;
+ meta: I extends null
+ ? null
+ : T extends undefined
+ ? Maybe<GithubRepositoryMeta>
+ : GithubRepositoryMeta;
};
-export const useGithubRepoMeta = <T extends Maybe<GithubRepositoryMeta>>(
- input: FetchGithubRepoMetaInput,
+export const useGithubRepoMeta = <
+ I extends Nullable<FetchGithubRepoMetaInput>,
+ T extends Maybe<GithubRepositoryMeta>,
+>(
+ input: I,
fallback?: T
) => {
const { data, error, isLoading, isValidating } = useSWR(
@@ -30,8 +38,8 @@ export const useGithubRepoMeta = <T extends Maybe<GithubRepositoryMeta>>(
return {
isError: !!error,
- isLoading,
+ isLoading: input !== null && isLoading && !data,
isValidating,
meta: data,
- } as UseGithubRepoMetaReturn<T>;
+ } as UseGithubRepoMetaReturn<I, T>;
};