Skip to content

Commit

Permalink
feat: update search result
Browse files Browse the repository at this point in the history
  • Loading branch information
fpasquet committed Nov 2, 2023
1 parent 4b8257b commit bb13377
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 30 deletions.
26 changes: 26 additions & 0 deletions src/components/ArticleMetadata/ArticleMetadata.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Meta, StoryFn } from '@storybook/react';
import React from 'react';

import { ArticleMetadata } from '@/components';
import { ContentTypeEnum } from '@/constants';

export default {
title: 'Components/ArticleMetadata',
component: ArticleMetadata,
args: {
contentType: ContentTypeEnum.ARTICLE,
date: '09 fév. 2021',
readingTime: 24,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
isLoading: false,
},
} as Meta<typeof ArticleMetadata>;

const Template: StoryFn<typeof ArticleMetadata> = (args) => <ArticleMetadata {...args} />;

export const Overview = Template.bind({});

export const ArticleMetadataIsLoading = Template.bind({});
ArticleMetadataIsLoading.args = {
isLoading: true,
};
66 changes: 66 additions & 0 deletions src/components/ArticleMetadata/ArticleMetadata.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { ColorSystemProps, Flex, Skeleton, SpacingSystemProps, Text } from '@eleven-labs/design-system';
import React from 'react';

import { SeparatorCircle } from '@/components';

export type ArticleMetadataOptions = {
date?: React.ReactNode;
readingTime?: number;
authors?: { username: string; name: string }[];
isLoading?: boolean;
displayedFields?: ('contentType' | 'date' | 'readingTime' | 'authors')[];
};

export type ArticleMetadataProps = ArticleMetadataOptions & SpacingSystemProps & ColorSystemProps;

export const ArticleMetadata: React.FC<ArticleMetadataProps> = ({
date,
readingTime,
authors,
isLoading = false,
displayedFields = ['date', 'readingTime', 'authors'],
...props
}) => {
const fields = displayedFields.reduce<React.ReactNode[]>((currentFields, displayedField, index) => {
switch (displayedField) {
case 'date':
currentFields.push(
<Skeleton isLoading={isLoading} display="inline-block" style={{ width: 100 }}>
{date && <Text as="span">{date}</Text>}
</Skeleton>
);
break;
case 'readingTime':
currentFields.push(
<Skeleton isLoading={isLoading} display="inline-block" style={{ width: 50 }}>
{readingTime && <Text as="span">{`${readingTime}mn`}</Text>}
</Skeleton>
);
break;
case 'authors':
currentFields.push(
<Skeleton isLoading={isLoading} display="inline-block" style={{ width: 100 }}>
{authors &&
authors.map((author, authorIndex) => (
<Text key={author.username} as="span">
{author.name}
{authorIndex !== authors.length - 1 ? ' & ' : ''}
</Text>
))}
</Skeleton>
);
break;
}

if (index !== displayedFields.length - 1) {
currentFields.push(<SeparatorCircle />);
}

return currentFields;
}, []);
return (
<Flex {...props} textSize="xs" alignItems="center">
{fields}
</Flex>
);
};
1 change: 1 addition & 0 deletions src/components/ArticleMetadata/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ArticleMetadata';
25 changes: 25 additions & 0 deletions src/components/AutocompleteField/AutocompleteField.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Meta, StoryFn } from '@storybook/react';
import React from 'react';

import { AutocompleteField } from '@/components';
import { ContentTypeEnum } from '@/constants';

export default {
title: 'Components/AutocompleteField',
Expand Down Expand Up @@ -30,29 +31,53 @@ AutocompleteFieldWithResult.args = {
defaultValue: 'React',
items: [
{
contentType: ContentTypeEnum.ARTICLE,
title: 'React SSR',
description: 'Lorem ipsum dolor sit react, consectetur adipiscing elit. In nec blandit neque',
date: '24 fév. 2021',
readingTime: 24,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
},
{
contentType: ContentTypeEnum.ARTICLE,
title: 'React SSG',
description: 'Mauris semper venenatis dolor vel posuere. Fusce imperdiet react purus euismod fermentum',
date: '22 fév. 2021',
readingTime: 22,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
},
{
contentType: ContentTypeEnum.TUTORIAL,
title: 'React + Astro',
description: 'Ut velit elit, finibus eu turpis quis, luctus sodales elit',
date: '18 fév. 2021',
readingTime: 18,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
},
{
contentType: ContentTypeEnum.ARTICLE,
title: 'React + NextJS',
description: 'Quisque ac consectetur massa. Praesent pellentesque, orci sit amet cursus venenatis',
date: '16 fév. 2021',
readingTime: 9,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
},
{
contentType: ContentTypeEnum.ARTICLE,
title: 'React + Apollo Client',
description: 'Phasellus ac sodales mi. Ut egestas dui react enim vehicula pulvinar',
date: '12 fév. 2021',
readingTime: 10,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
},
{
contentType: ContentTypeEnum.ARTICLE,
title: 'React vs Vue',
description:
'Suspendisse potenti. Etiam egestas lacus velit, et tempor metus mollis react. Donec ut vulputate leo',
date: '09 fév. 2021',
readingTime: 6,
authors: [{ username: 'jdoe', name: 'J. Doe' }],
},
],
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
import './AutocompleteResult.scss';

import { AsProps, Box, BoxProps, forwardRef, Heading, Link, Text, TextHighlight } from '@eleven-labs/design-system';
import {
AsProps,
Box,
BoxProps,
Flex,
forwardRef,
Heading,
Link,
Text,
TextHighlight,
} from '@eleven-labs/design-system';
import classNames from 'classnames';
import React from 'react';

import { ArticleMetadata, TutoTag } from '@/components';
import { ContentTypeEnum } from '@/constants';
import { getPathFile } from '@/helpers/assetHelper';

export interface AutocompleteItem {
contentType: ContentTypeEnum.ARTICLE | ContentTypeEnum.TUTORIAL;
title: string;
description: string;
date: React.ReactNode;
readingTime: number;
authors?: { username: string; name: string }[];
}

export type AutocompleteResultOptions = {
Expand Down Expand Up @@ -41,7 +57,7 @@ export const AutocompleteResult = forwardRef<AutocompleteResultProps, 'div'>(
<Box className={classNames('autocomplete-result', props.className)} ref={ref} hidden={!isOpen}>
{items.length > 0 && (
<>
{items.map(({ title, description, ...itemProps }, index) => {
{items.map(({ contentType, title, description, date, readingTime, authors, ...itemProps }, index) => {
const isHighlighted = highlightedIndex === index;
return (
<React.Fragment key={index}>
Expand All @@ -54,8 +70,12 @@ export const AutocompleteResult = forwardRef<AutocompleteResultProps, 'div'>(
'autocomplete-result__item--is-highlighted': isHighlighted,
})}
>
<TextHighlight size="s" text={title} textQuery={searchValue} />
<Flex alignItems="center" gap="xxs">
{contentType === ContentTypeEnum.TUTORIAL && <TutoTag />}
<TextHighlight size="s" text={title} textQuery={searchValue} />
</Flex>
<TextHighlight size="xs" text={description} textQuery={searchValue} hiddenBelow="sm" />
<ArticleMetadata color="black" date={date} authors={authors} displayedFields={['date', 'authors']} />
</Box>
</React.Fragment>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/PostPreview/PostPreview.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default {

const Template: StoryFn<typeof PostPreview> = (args) => <PostPreview {...args} />;

export const PostPreviewWithData = Template.bind({});
export const Overview = Template.bind({});

export const PostPreviewIsLoading = Template.bind({});
PostPreviewIsLoading.args = {
Expand Down
22 changes: 2 additions & 20 deletions src/components/PostPreview/PostPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AsProps, Box, BoxProps, Flex, Heading, Link, Skeleton, Text } from '@el
import classNames from 'classnames';
import React from 'react';

import { SeparatorCircle, TutoTag } from '@/components';
import { ArticleMetadata, TutoTag } from '@/components';
import { ContentTypeEnum } from '@/constants';

export type PostPreviewOptions = {
Expand Down Expand Up @@ -65,25 +65,7 @@ export const PostPreview: React.FC<PostPreviewProps> = ({
{excerpt}
</Text>
</Skeleton>
<Box mt={{ xs: 'xs', md: 's' }} textSize="xs">
<Skeleton isLoading={isLoading} display="inline-block" style={{ width: 100 }}>
{date && <Text as="span">{date}</Text>}
</Skeleton>
<SeparatorCircle />
<Skeleton isLoading={isLoading} display="inline-block" style={{ width: 50 }}>
{readingTime && <Text as="span">{`${readingTime}mn`}</Text>}
</Skeleton>
<SeparatorCircle />
<Skeleton isLoading={isLoading} display="inline-block" style={{ width: 100 }}>
{authors &&
authors.map((author, authorIndex) => (
<Text key={author.username} as="span">
{author.name}
{authorIndex !== authors.length - 1 ? ' & ' : ''}
</Text>
))}
</Skeleton>
</Box>
<ArticleMetadata mt={{ xs: 'xs', md: 's' }} date={date} readingTime={readingTime} authors={authors} />
</Box>
);
};
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './SeparatorCircle';
export * from './BackLink';
export * from './ShareLinks';
export * from './TutoTag';
export * from './ArticleMetadata';
16 changes: 12 additions & 4 deletions src/containers/HeaderContainer/useHeaderContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ import { LinkContainer } from '@/containers/LinkContainer';
import { trackContentSearchEvent } from '@/helpers/dataLayerHelper';
import { generatePath } from '@/helpers/routerHelper';
import { useAlgoliaSearchIndex } from '@/hooks/useAlgoliaSearchIndex';
import { useDateToString } from '@/hooks/useDateToString';
import { useDebounce } from '@/hooks/useDebounce';
import { HeaderProps } from '@/templates/LayoutTemplate';
import { AlgoliaPostData } from '@/types';

export const useHeaderContainer = (): HeaderProps => {
const { t, i18n } = useTranslation();
const location = useLocation();
const navigate = useNavigate();
const { getDateToString } = useDateToString();
const searchParams = new URLSearchParams(!IS_SSR ? location.search : '');

const [autocompleteIsDisplayed, setAutocompleteIsDisplayed] = React.useState<boolean>(false);
const [search, setSearch] = React.useState<string>(searchParams.get('search') ?? '');
const debouncedSearch = useDebounce<string>(search, 500);
const [searchHits, setSearchHits] = React.useState<
{ objectID: string; slug: string; title: string; excerpt: string }[]
>([]);
const [searchHits, setSearchHits] = React.useState<AlgoliaPostData[]>([]);
const algoliaSearchIndex = useAlgoliaSearchIndex();

const onToggleSearch = React.useCallback(() => {
Expand All @@ -49,7 +50,7 @@ export const useHeaderContainer = (): HeaderProps => {
trackContentSearchEvent(debouncedSearch);
setAutocompleteIsDisplayed(true);
algoliaSearchIndex
.search<{ slug: string; title: string; excerpt: string }>(debouncedSearch, {
.search<AlgoliaPostData>(debouncedSearch, {
hitsPerPage: NUMBER_OF_ITEMS_PER_PAGE,
facetFilters: [`lang:${i18n.language}`],
})
Expand All @@ -63,8 +64,15 @@ export const useHeaderContainer = (): HeaderProps => {
() =>
searchHits.map<AutocompleteFieldProps['items'][0]>((hit) => ({
id: hit.objectID,
contentType: hit.contentType,
title: hit.title,
description: hit.excerpt,
date: getDateToString({ date: hit.date }),
readingTime: hit.readingTime,
authors: hit.authorUsernames.map((authorUsername, index) => ({
username: authorUsername,
name: hit.authorNames[index],
})),
as: LinkContainer,
hrefLang: i18n.language,
to: generatePath(PATHS.POST, { lang: i18n.language, slug: hit.slug }),
Expand Down
1 change: 1 addition & 0 deletions src/helpers/indexationAlgoliaHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const indexationAlglolia = async (options: {
const algoliaSearchClient = getAlgoliaSearchClient({ appId: options.appId, apiKey: options.apiIndexingKey });
const algoliaSearchIndex = getAlgoliaSearchIndex({ algoliaSearchClient, index: options.index });

await algoliaSearchIndex.clearObjects();
const objectIDs = await savePosts({ posts, authors, algoliaSearchIndex });
console.info(`Number of posts indexed on algolia: ${objectIDs.length}`);

Expand Down
10 changes: 8 additions & 2 deletions src/templates/LayoutTemplate/LayoutTemplate.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@ LayoutTemplateWithAutocompleteIsOpen.args = {
href: '#',
},
autocompleteIsDisplayed: true,
autocomplete: AutocompleteFieldStories.AutocompleteFieldWithResult.args as HeaderProps['autocomplete'],
autocomplete: {
...AutocompleteFieldStories.default.args,
...AutocompleteFieldStories.AutocompleteFieldWithResult.args,
} as HeaderProps['autocomplete'],
}),
};

Expand All @@ -124,6 +127,9 @@ LayoutTemplateWithAutocompleteAndResultNotFound.args = {
href: '#',
},
autocompleteIsDisplayed: true,
autocomplete: AutocompleteFieldStories.AutocompleteFieldWithNoResult.args as HeaderProps['autocomplete'],
autocomplete: {
...AutocompleteFieldStories.default.args,
...AutocompleteFieldStories.AutocompleteFieldWithResult.args,
} as HeaderProps['autocomplete'],
}),
};

0 comments on commit bb13377

Please sign in to comment.