Files
frontend-app-authoring/src/search-manager/SearchSortWidget.tsx
Navin Karkera 77a55d9ad3 feat: course libraries review tab [FC-0076] (#1699)
Adds review tab to course libraries page. Also refactors all libraries page as per new designs.
2025-03-12 12:58:27 -05:00

124 lines
4.2 KiB
TypeScript

import React, { useMemo } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Icon, Dropdown } from '@openedx/paragon';
import { Check, SwapVert } from '@openedx/paragon/icons';
import classNames from 'classnames';
import messages from './messages';
import { SearchSortOption } from './data/api';
import { useSearchContext } from './SearchManager';
export const SearchSortWidget = ({
iconOnly = false,
disableOptions,
}: {
iconOnly?: boolean;
disableOptions?: SearchSortOption[];
}) => {
const intl = useIntl();
const {
searchSortOrder,
setSearchSortOrder,
defaultSearchSortOrder,
} = useSearchContext();
const menuItems = useMemo(
() => [
{
id: 'search-sort-option-most-relevant',
name: intl.formatMessage(messages.searchSortMostRelevant),
value: SearchSortOption.RELEVANCE,
show: (
!disableOptions?.includes(SearchSortOption.RELEVANCE)
&& defaultSearchSortOrder === SearchSortOption.RELEVANCE
),
},
{
id: 'search-sort-option-recently-modified',
name: intl.formatMessage(messages.searchSortRecentlyModified),
value: SearchSortOption.RECENTLY_MODIFIED,
show: !disableOptions?.includes(SearchSortOption.RECENTLY_MODIFIED),
},
{
id: 'search-sort-option-recently-published',
name: intl.formatMessage(messages.searchSortRecentlyPublished),
value: SearchSortOption.RECENTLY_PUBLISHED,
show: !disableOptions?.includes(SearchSortOption.RECENTLY_PUBLISHED),
},
{
id: 'search-sort-option-title-az',
name: intl.formatMessage(messages.searchSortTitleAZ),
value: SearchSortOption.TITLE_AZ,
show: !disableOptions?.includes(SearchSortOption.TITLE_AZ),
},
{
id: 'search-sort-option-title-za',
name: intl.formatMessage(messages.searchSortTitleZA),
value: SearchSortOption.TITLE_ZA,
show: !disableOptions?.includes(SearchSortOption.TITLE_ZA),
},
{
id: 'search-sort-option-newest',
name: intl.formatMessage(messages.searchSortNewest),
value: SearchSortOption.NEWEST,
show: !disableOptions?.includes(SearchSortOption.NEWEST),
},
{
id: 'search-sort-option-oldest',
name: intl.formatMessage(messages.searchSortOldest),
value: SearchSortOption.OLDEST,
show: !disableOptions?.includes(SearchSortOption.OLDEST),
},
],
[intl, defaultSearchSortOrder],
);
const menuHeader = intl.formatMessage(messages.searchSortWidgetLabel);
const defaultSortOption = menuItems.find(
({ value }) => (value === defaultSearchSortOrder),
);
const shownMenuItems = menuItems.filter(({ show }) => show);
// Show the currently selected sort option as the toggle button label.
const selectedSortOption = shownMenuItems.find(
({ value }) => (value === searchSortOrder),
) ?? defaultSortOption;
const toggleLabel = selectedSortOption ? selectedSortOption.name : menuHeader;
return (
<Dropdown id="search-sort-dropdown">
<Dropdown.Toggle
id="search-sort-toggle"
title={intl.formatMessage(messages.searchSortWidgetAltTitle)}
alt={intl.formatMessage(messages.searchSortWidgetAltTitle)}
variant="outline-primary"
className={classNames('dropdown-toggle-menu-items d-flex', {
'border-0': iconOnly,
})}
size="sm"
>
<Icon src={SwapVert} className="d-inline" />
{ !iconOnly && <div className="py-0 px-1">{toggleLabel}</div>}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Header>{menuHeader}</Dropdown.Header>
{shownMenuItems.map(({ id, name, value }) => (
<Dropdown.Item
key={id}
onClick={() => {
// If the selected sort option was re-clicked, de-select it (reset to default)
const searchOrder = value === searchSortOrder ? defaultSearchSortOrder : value;
setSearchSortOrder(searchOrder);
}}
>
{name}
{(value === searchSortOrder) && <Icon src={Check} className="ml-2" />}
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
);
};
export default SearchSortWidget;