docusaurus/website/src/pages/showcase/_utils.tsx
2024-04-10 10:42:27 +02:00

99 lines
2.6 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useCallback, useMemo} from 'react';
import {translate} from '@docusaurus/Translate';
import {
usePluralForm,
useQueryString,
useQueryStringList,
} from '@docusaurus/theme-common';
import type {TagType, User} from '@site/src/data/users';
import {sortedUsers} from '@site/src/data/users';
export function useSearchName() {
return useQueryString('name');
}
export function useTags() {
return useQueryStringList('tags');
}
type Operator = 'OR' | 'AND';
export function useOperator() {
const [searchOperator, setSearchOperator] = useQueryString('operator');
const operator: Operator = searchOperator === 'AND' ? 'AND' : 'OR';
const toggleOperator = useCallback(() => {
const newOperator = operator === 'OR' ? 'AND' : null;
setSearchOperator(newOperator);
}, [operator, setSearchOperator]);
return [operator, toggleOperator] as const;
}
function filterUsers({
users,
tags,
operator,
searchName,
}: {
users: User[];
tags: TagType[];
operator: Operator;
searchName: string | null;
}) {
if (searchName) {
// eslint-disable-next-line no-param-reassign
users = users.filter((user) =>
user.title.toLowerCase().includes(searchName.toLowerCase()),
);
}
if (tags.length === 0) {
return users;
}
return users.filter((user) => {
if (user.tags.length === 0) {
return false;
}
if (operator === 'AND') {
return tags.every((tag) => user.tags.includes(tag));
}
return tags.some((tag) => user.tags.includes(tag));
});
}
export function useFilteredUsers() {
const [tags] = useTags();
const [searchName] = useSearchName();
const [operator] = useOperator();
return useMemo(
() =>
filterUsers({
users: sortedUsers,
tags: tags as TagType[],
operator,
searchName,
}),
[tags, operator, searchName],
);
}
export function useSiteCountPlural() {
const {selectMessage} = usePluralForm();
return (sitesCount: number) =>
selectMessage(
sitesCount,
translate(
{
id: 'showcase.filters.resultCount',
description:
'Pluralized label for the number of sites found on the showcase. Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
message: '1 site|{sitesCount} sites',
},
{sitesCount},
),
);
}