aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks/use-breadcrumb.ts
blob: 8b23ff26889db0dc8453797d5b0b2ecb26844f92 (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* eslint-disable max-statements */
import { useIntl } from 'react-intl';
import type { BreadcrumbList } from 'schema-dts';
import type { BreadcrumbsItem } from '../../components';
import { CONFIG } from '../config';
import { ROUTES } from '../constants';
import { slugify } from '../helpers';

const isArticle = (url: string) => url.startsWith(`${ROUTES.ARTICLE}/`);

const isHome = (url: string) => url === '/';

const isPageNumber = (url: string) => url.includes('/page/');

const isProject = (url: string) => url.startsWith(`${ROUTES.PROJECTS}/`);

const isSearch = (url: string) => url.startsWith(ROUTES.SEARCH);

const isThematic = (url: string) => url.startsWith(`${ROUTES.THEMATICS}/`);

const isTopic = (url: string) => url.startsWith(`${ROUTES.TOPICS}/`);

const hasBlogAsParent = (url: string) =>
  isArticle(url) ||
  isPageNumber(url) ||
  isSearch(url) ||
  isThematic(url) ||
  isTopic(url);

export type useBreadcrumbProps = {
  /**
   * The current page title.
   */
  title: string;
  /**
   * The current page url.
   */
  url: string;
};

export type useBreadcrumbReturn = {
  /**
   * The breadcrumb items.
   */
  items: BreadcrumbsItem[];
  /**
   * The breadcrumb JSON schema.
   */
  schema: BreadcrumbList['itemListElement'][];
};

/**
 * Retrieve the breadcrumb items.
 *
 * @param {useBreadcrumbProps} props - An object (the current page title & url).
 * @returns {useBreadcrumbReturn} The breadcrumb items and its JSON schema.
 */
export const useBreadcrumb = ({
  title,
  url,
}: useBreadcrumbProps): useBreadcrumbReturn => {
  const intl = useIntl();
  const labels = {
    home: intl.formatMessage({
      defaultMessage: 'Home',
      description: 'Breadcrumb: home label',
      id: 'j5k9Fe',
    }),
    blog: intl.formatMessage({
      defaultMessage: 'Blog',
      description: 'Breadcrumb: blog label',
      id: 'Es52wh',
    }),
    projects: intl.formatMessage({
      defaultMessage: 'Projects',
      description: 'Breadcrumb: projects label',
      id: '28GZdv',
    }),
  };

  const items: BreadcrumbsItem[] = [
    { id: 'home', name: labels.home, url: '/' },
  ];
  const schema: BreadcrumbList['itemListElement'][] = [
    {
      '@type': 'ListItem',
      position: 1,
      name: labels.home,
      item: CONFIG.url,
    },
  ];

  if (isHome(url)) return { items, schema };

  if (hasBlogAsParent(url)) {
    items.push({ id: 'blog', name: labels.blog, url: ROUTES.BLOG });
    schema.push({
      '@type': 'ListItem',
      position: 2,
      name: labels.blog,
      item: `${CONFIG.url}${ROUTES.BLOG}`,
    });
  }

  if (isProject(url)) {
    items.push({ id: 'projects', name: labels.projects, url: ROUTES.PROJECTS });
    schema.push({
      '@type': 'ListItem',
      position: 2,
      name: labels.projects,
      item: `${CONFIG.url}${ROUTES.PROJECTS}`,
    });
  }

  items.push({ id: slugify(title), name: title, url });
  schema.push({
    '@type': 'ListItem',
    position: schema.length + 1,
    name: title,
    item: `${CONFIG.url}${url}`,
  });

  return { items, schema };
};