diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-12-07 18:48:53 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-12-08 19:13:47 +0100 |
| commit | d375e5c9f162cbd84a6e6462977db56519d09f75 (patch) | |
| tree | aed9bc81c426e3e9fb60292cb244613cb8083dea /src/components/organisms/project-overview/project-overview.tsx | |
| parent | b8eb008dd5927fb736e56699637f5f8549965eae (diff) | |
refactor(pages): refine Project pages
* refactor ProjectOverview component to let consumers handle the value
* extract project overview depending on Github to avoid fetching
Github API if the project is not on Github
* wrap dynamic import in a useMemo hook to avoid infinite rerender
* fix table of contents by adding a useMutationObserver hook to refresh
headings tree (without it useHeadingsTree is not retriggered once the
dynamic import is done)
* add Cypress tests
Diffstat (limited to 'src/components/organisms/project-overview/project-overview.tsx')
| -rw-r--r-- | src/components/organisms/project-overview/project-overview.tsx | 93 |
1 files changed, 20 insertions, 73 deletions
diff --git a/src/components/organisms/project-overview/project-overview.tsx b/src/components/organisms/project-overview/project-overview.tsx index f524120..d7416ec 100644 --- a/src/components/organisms/project-overview/project-overview.tsx +++ b/src/components/organisms/project-overview/project-overview.tsx @@ -6,35 +6,23 @@ import { type ReactElement, } from 'react'; import { useIntl } from 'react-intl'; -import type { ValueOf } from '../../../types'; +import { Figure } from '../../atoms'; import { - Time, - type SocialWebsite, - Link, - SocialLink, - Figure, -} from '../../atoms'; -import { MetaItem, type MetaItemProps, MetaList } from '../../molecules'; + MetaItem, + type MetaItemProps, + MetaList, + type MetaValue, + type MetaValues, +} from '../../molecules'; import styles from './project-overview.module.scss'; -export type Repository = { - id: Extract<SocialWebsite, 'Github' | 'Gitlab'>; - label: string; - url: string; -}; - -export type ProjectPopularity = { - count: number; - url?: string; -}; - -export type ProjectMeta = { - creationDate: string; - lastUpdateDate: string; - license: string; - popularity: ProjectPopularity; - repositories: Repository[]; - technologies: string[]; +export type OverviewMeta = { + creationDate: MetaValue; + lastUpdateDate: MetaValue; + license: MetaValue; + popularity: MetaValue; + repositories: MetaValue | MetaValues[]; + technologies: MetaValues[]; }; const validMeta = [ @@ -44,9 +32,9 @@ const validMeta = [ 'popularity', 'repositories', 'technologies', -] satisfies (keyof ProjectMeta)[]; +] satisfies (keyof OverviewMeta)[]; -const isValidMetaKey = (key: string): key is keyof ProjectMeta => +const isValidMetaKey = (key: string): key is keyof OverviewMeta => (validMeta as string[]).includes(key); export type ProjectOverviewProps = Omit< @@ -60,7 +48,7 @@ export type ProjectOverviewProps = Omit< /** * The project meta. */ - meta: Partial<ProjectMeta>; + meta: Partial<OverviewMeta>; /** * The project name. */ @@ -112,48 +100,7 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction< description: 'ProjectOverview: technologies label', id: 'OWkqXt', }), - } satisfies Record<keyof ProjectMeta, string>; - - const getMetaValue = useCallback( - (key: keyof ProjectMeta, value: ValueOf<ProjectMeta>) => { - if (typeof value === 'string') { - return key === 'license' ? value : <Time date={value} />; - } - - if ( - (value instanceof Object || typeof value === 'object') && - !Array.isArray(value) - ) { - const stars = intl.formatMessage( - { - defaultMessage: - '{starsCount, plural, =0 {No stars} one {# star} other {# stars}}', - description: 'ProjectOverview: stars count', - id: 'PBdVsm', - }, - { starsCount: value.count } - ); - - return value.url ? ( - <> - ⭐ <Link href={value.url}>{stars}</Link> - </> - ) : ( - `⭐\u00A0${stars}` - ); - } - - return value.map((v) => { - if (typeof v === 'string') return { id: v, value: v }; - - return { - id: v.id, - value: <SocialLink icon={v.id} label={v.label} url={v.url} />, - }; - }); - }, - [intl] - ); + } satisfies Record<keyof OverviewMeta, string>; const getMetaItems = useCallback(() => { const keys = Object.keys(meta).filter(isValidMetaKey); @@ -172,7 +119,7 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction< } key={key} label={metaLabels[key]} - value={getMetaValue(key, value)} + value={value} /> ) : undefined; }) @@ -180,7 +127,7 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction< (item): item is ReactElement<MetaItemProps> => typeof item !== 'undefined' ); - }, [getMetaValue, meta, metaLabels]); + }, [meta, metaLabels]); return ( <div {...props} className={wrapperClass} ref={ref}> |
