import Spinner from '@components/Spinner/Spinner'; import { ExpandableWidget, List } from '@components/WidgetParts'; import { getAllTopics } from '@services/graphql/queries'; import { TitleLevel } from '@ts/types/app'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; import useSWR from 'swr'; const TopicsList = ({ title, titleLevel, }: { title: string; titleLevel?: TitleLevel; }) => { const intl = useIntl(); const router = useRouter(); const isTopic = () => router.asPath.includes('/sujet/'); const currentTopicSlug = isTopic() ? router.asPath.replace('/sujet/', '') : ''; const { data, error } = useSWR('/api/topics', getAllTopics); const getList = () => { if (error) return ( ); if (!data) return ( ); const topics = data.map((topic) => { return currentTopicSlug !== topic.slug ? (
  • {topic.title}
  • ) : ( '' ); }); return ; }; return ( {getList()} ); }; export default TopicsList; tive' href='/www.armandphilippot.com/tree/src/utils/helpers/server/projects.ts?id=d5ade2359539648845a5854ed353b29367961d74'>treecommitdiffstats
    path: root/src/utils/helpers/server/projects.ts
    blob: ed73da89d9353af890859804b4a1ef69aabdd5ba (plain)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    
    import { readdirSync } from 'fs';
    import path from 'path';
    import {
      type MDXProjectMeta,
      type ProjectCard,
      type ProjectPreview,
    } from '../../../types';
    
    /**
     * Retrieve all the projects filename.
     *
     * @returns {string[]} An array of filenames.
     */
    export const getProjectFilenames = (): string[] => {
      const projectsDirectory = path.join(process.cwd(), 'src/content/projects');
      const filenames = readdirSync(projectsDirectory);
    
      return filenames.map((filename) => filename.replace(/\.mdx$/, ''));
    };
    
    /**
     * Retrieve the data of a project by filename.
     *
     * @param {string} filename - The project filename.
     * @returns {Promise<ProjectPreview>}
     */
    export const getProjectData = async (
      filename: string
    ): Promise<ProjectPreview> => {
      try {
        const {
          meta,
        }: {
          meta: MDXProjectMeta;
        } = await import(`../../../content/projects/${filename}.mdx`);
    
        const { dates, intro, title, ...projectMeta } = meta;
        const { publication, update } = dates;
        const cover = await import(`../../../../public/projects/${filename}.jpg`);
    
        return {
          id: filename,
          intro,
          meta: {
            ...projectMeta,
            dates: { publication, update },
            // Dynamic import source does not work so I use it only to get sizes
            cover: {
              ...cover.default,
              alt: `${title} image`,
              src: `/projects/${filename}.jpg`,
              title,
            },
          },
          slug: filename,
          title: title,
        };
      } catch (err) {
        console.error(err);
        throw err;
      }
    };
    
    /**
     * Retrieve all the projects data using filenames.
     *
     * @param {string[]} filenames - The filenames without extension.
     * @returns {Promise<ProjectCard[]>} - An array of projects data.
     */
    export const getProjectsData = async (
      filenames: string[]
    ): Promise<ProjectCard[]> => {
      return Promise.all(
        filenames.map(async (filename) => {
          const { id, meta, slug, title } = await getProjectData(filename);
          const { cover, dates, tagline, technologies } = meta;
          return { id, meta: { cover, dates, tagline, technologies }, slug, title };
        })
      );
    };
    
    /**
     * Method to sort an array of projects by publication date.
     *
     * @param {ProjectCard} a - A single project.
     * @param {ProjectCard} b - A single project.
     * @returns The result used by Array.sort() method: 1 || -1 || 0.
     */
    const sortProjectsByPublicationDate = (a: ProjectCard, b: ProjectCard) => {
      if (a.meta.dates.publication < b.meta.dates.publication) return 1;
      if (a.meta.dates.publication > b.meta.dates.publication) return -1;
      return 0;
    };
    
    /**
     * Retrieve all projects in content folder sorted by publication date.
     *
     * @returns {Promise<ProjectCard[]>} An array of projects.
     */
    export const getProjectsCard = async (): Promise<ProjectCard[]> => {
      const filenames = getProjectFilenames();
      const projects = await getProjectsData(filenames);
    
      return [...projects].sort(sortProjectsByPublicationDate);
    };