From 1e982fb02a9967e0efdc76c93a44798a9f2dcb43 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Tue, 24 May 2022 16:44:29 +0200 Subject: chore: add a search form when posts list prints no results --- .../organisms/layout/no-results.stories.tsx | 28 ++++++++ .../organisms/layout/no-results.test.tsx | 14 ++++ src/components/organisms/layout/no-results.tsx | 38 ++++++++++ .../organisms/layout/posts-list.fixture.tsx | 2 + .../organisms/layout/posts-list.stories.tsx | 5 +- .../organisms/layout/posts-list.test.tsx | 29 ++++++-- src/components/organisms/layout/posts-list.tsx | 81 ++++++++++------------ .../templates/page/page-layout.stories.tsx | 7 +- 8 files changed, 155 insertions(+), 49 deletions(-) create mode 100644 src/components/organisms/layout/no-results.stories.tsx create mode 100644 src/components/organisms/layout/no-results.test.tsx create mode 100644 src/components/organisms/layout/no-results.tsx (limited to 'src/components') diff --git a/src/components/organisms/layout/no-results.stories.tsx b/src/components/organisms/layout/no-results.stories.tsx new file mode 100644 index 0000000..aa2e51e --- /dev/null +++ b/src/components/organisms/layout/no-results.stories.tsx @@ -0,0 +1,28 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import NoResultsComponent from './no-results'; + +export default { + title: 'Organisms/Layout', + component: NoResultsComponent, + argTypes: { + searchPage: { + control: { + type: 'text', + }, + description: 'The search results page.', + type: { + name: 'string', + required: true, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const NoResults = Template.bind({}); +NoResults.args = { + searchPage: '#', +}; diff --git a/src/components/organisms/layout/no-results.test.tsx b/src/components/organisms/layout/no-results.test.tsx new file mode 100644 index 0000000..7f57177 --- /dev/null +++ b/src/components/organisms/layout/no-results.test.tsx @@ -0,0 +1,14 @@ +import { render, screen } from '@test-utils'; +import NoResults from './no-results'; + +describe('NoResults', () => { + it('renders a no results text', () => { + render(); + expect(screen.getByText(/No results/gi)).toBeInTheDocument(); + }); + + it('renders a search form', () => { + render(); + expect(screen.getByRole('searchbox')).toBeInTheDocument(); + }); +}); diff --git a/src/components/organisms/layout/no-results.tsx b/src/components/organisms/layout/no-results.tsx new file mode 100644 index 0000000..2245dbf --- /dev/null +++ b/src/components/organisms/layout/no-results.tsx @@ -0,0 +1,38 @@ +import SearchForm, { + type SearchFormProps, +} from '@components/organisms/forms/search-form'; +import { FC } from 'react'; +import { useIntl } from 'react-intl'; + +export type NoResultsProps = Pick; + +/** + * NoResults component + * + * Renders a no results text with a search form. + */ +const NoResults: FC = ({ searchPage }) => { + const intl = useIntl(); + + return ( + <> +

+ {intl.formatMessage({ + defaultMessage: 'No results found.', + description: 'NoResults: no results', + id: '5O2vpy', + })} +

+

+ {intl.formatMessage({ + defaultMessage: 'Would you like to try a new search?', + description: 'NoResults: try a new search message', + id: 'DVBwfu', + })} +

+ + + ); +}; + +export default NoResults; diff --git a/src/components/organisms/layout/posts-list.fixture.tsx b/src/components/organisms/layout/posts-list.fixture.tsx index e3f2378..97a746f 100644 --- a/src/components/organisms/layout/posts-list.fixture.tsx +++ b/src/components/organisms/layout/posts-list.fixture.tsx @@ -59,3 +59,5 @@ export const posts: Post[] = [ url: '#', }, ]; + +export const searchPage = '#'; diff --git a/src/components/organisms/layout/posts-list.stories.tsx b/src/components/organisms/layout/posts-list.stories.tsx index 68e3dc0..bff1f28 100644 --- a/src/components/organisms/layout/posts-list.stories.tsx +++ b/src/components/organisms/layout/posts-list.stories.tsx @@ -1,6 +1,6 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; import PostsList from './posts-list'; -import { posts } from './posts-list.fixture'; +import { posts, searchPage } from './posts-list.fixture'; /** * PostsList - Storybook Meta @@ -161,6 +161,7 @@ const Template: ComponentStory = (args) => ( export const Default = Template.bind({}); Default.args = { posts, + searchPage, total: posts.length, }; @@ -171,6 +172,7 @@ export const ByYears = Template.bind({}); ByYears.args = { posts, byYear: true, + searchPage, total: posts.length, }; ByYears.decorators = [ @@ -187,5 +189,6 @@ ByYears.decorators = [ export const NoResults = Template.bind({}); NoResults.args = { posts: [], + searchPage, total: posts.length, }; diff --git a/src/components/organisms/layout/posts-list.test.tsx b/src/components/organisms/layout/posts-list.test.tsx index 1bab466..e58a974 100644 --- a/src/components/organisms/layout/posts-list.test.tsx +++ b/src/components/organisms/layout/posts-list.test.tsx @@ -1,25 +1,46 @@ import { render, screen } from '@test-utils'; import PostsList from './posts-list'; -import { posts } from './posts-list.fixture'; +import { posts, searchPage } from './posts-list.fixture'; describe('PostsList', () => { it('renders the correct number of posts', () => { - render(); + render( + + ); expect(screen.getAllByRole('article')).toHaveLength(posts.length); }); it('renders the number of loaded posts', () => { - render(); + render( + + ); const info = `${posts.length} loaded articles out of a total of ${posts.length}`; expect(screen.getByText(info)).toBeInTheDocument(); }); it('renders a load more button', () => { render( - + ); expect( screen.getByRole('button', { name: /Load more/i }) ).toBeInTheDocument(); }); + + it('renders a search form if no results', () => { + render( + + ); + expect(screen.getByRole('searchbox')).toBeInTheDocument(); + }); }); diff --git a/src/components/organisms/layout/posts-list.tsx b/src/components/organisms/layout/posts-list.tsx index 91fc62d..24869fd 100644 --- a/src/components/organisms/layout/posts-list.tsx +++ b/src/components/organisms/layout/posts-list.tsx @@ -9,6 +9,7 @@ import useIsMounted from '@utils/hooks/use-is-mounted'; import useSettings from '@utils/hooks/use-settings'; import { FC, Fragment, useRef } from 'react'; import { useIntl } from 'react-intl'; +import NoResults, { NoResultsProps } from './no-results'; import styles from './posts-list.module.scss'; import Summary, { type SummaryProps } from './summary'; @@ -23,40 +24,41 @@ export type YearCollection = { [key: string]: Post[]; }; -export type PostsListProps = Pick & { - /** - * True to display the posts by year. Default: false. - */ - byYear?: boolean; - /** - * Determine if the data is loading. - */ - isLoading?: boolean; - /** - * Load more button handler. - */ - loadMore?: () => void; - /** - * The current page number. Default: 1. - */ - pageNumber?: number; - /** - * The posts data. - */ - posts: Post[]; - /** - * Determine if the load more button should be visible. - */ - showLoadMoreBtn?: boolean; - /** - * The posts heading level (hn). - */ - titleLevel?: HeadingLevel; - /** - * The total posts number. - */ - total: number; -}; +export type PostsListProps = Pick & + Pick & { + /** + * True to display the posts by year. Default: false. + */ + byYear?: boolean; + /** + * Determine if the data is loading. + */ + isLoading?: boolean; + /** + * Load more button handler. + */ + loadMore?: () => void; + /** + * The current page number. Default: 1. + */ + pageNumber?: number; + /** + * The posts data. + */ + posts: Post[]; + /** + * Determine if the load more button should be visible. + */ + showLoadMoreBtn?: boolean; + /** + * The posts heading level (hn). + */ + titleLevel?: HeadingLevel; + /** + * The total posts number. + */ + total: number; + }; /** * Create a collection of posts sorted by year. @@ -89,6 +91,7 @@ const PostsList: FC = ({ loadMore, pageNumber = 1, posts, + searchPage, showLoadMoreBtn = false, siblings, titleLevel, @@ -221,15 +224,7 @@ const PostsList: FC = ({ }; if (posts.length === 0) { - return ( -

- {intl.formatMessage({ - defaultMessage: 'No results found.', - description: 'PostsList: no results', - id: 'vK7Sxv', - })} -

- ); + return ; } return ( diff --git a/src/components/templates/page/page-layout.stories.tsx b/src/components/templates/page/page-layout.stories.tsx index 88e3785..06c6c24 100644 --- a/src/components/templates/page/page-layout.stories.tsx +++ b/src/components/templates/page/page-layout.stories.tsx @@ -368,7 +368,12 @@ Blog.args = { headerMeta: { total: posts.length }, children: ( <> - + ), widgets: [ -- cgit v1.2.3