ConceptPortal-public/rsconcept/frontend/src/pages/LibraryPage/SearchPanel.tsx

182 lines
5.4 KiB
TypeScript
Raw Normal View History

'use client';
2023-08-26 19:39:49 +03:00
import clsx from 'clsx';
import { useCallback } from 'react';
2023-08-27 15:39:49 +03:00
2024-06-04 11:19:21 +03:00
import { LocationIcon, SubscribeIcon, VisibilityIcon } from '@/components/DomainIcons';
import { IconEditor, IconFolder, IconOwner } from '@/components/Icons';
import BadgeHelp from '@/components/info/BadgeHelp';
import Dropdown from '@/components/ui/Dropdown';
import DropdownButton from '@/components/ui/DropdownButton';
import MiniButton from '@/components/ui/MiniButton';
import SearchBar from '@/components/ui/SearchBar';
import SelectorButton from '@/components/ui/SelectorButton';
import useDropdown from '@/hooks/useDropdown';
import { LocationHead } from '@/models/library';
import { HelpTopic } from '@/models/miscellaneous';
import { prefixes } from '@/utils/constants';
import { describeLocationHead, labelLocationHead } from '@/utils/labels';
import { tripleToggleColor } from '@/utils/utils';
2023-08-26 19:39:49 +03:00
interface SearchPanelProps {
2023-12-28 14:04:44 +03:00
total: number;
filtered: number;
2023-12-28 14:04:44 +03:00
query: string;
setQuery: React.Dispatch<React.SetStateAction<string>>;
path: string;
setPath: React.Dispatch<React.SetStateAction<string>>;
head: LocationHead | undefined;
setHead: React.Dispatch<React.SetStateAction<LocationHead | undefined>>;
isVisible: boolean | undefined;
toggleVisible: () => void;
isOwned: boolean | undefined;
toggleOwned: () => void;
isSubscribed: boolean | undefined;
toggleSubscribed: () => void;
isEditor: boolean | undefined;
toggleEditor: () => void;
2023-08-26 19:39:49 +03:00
}
function SearchPanel({
total,
filtered,
query,
setQuery,
path,
setPath,
head,
setHead,
isVisible,
toggleVisible,
isOwned,
toggleOwned,
isSubscribed,
toggleSubscribed,
isEditor,
toggleEditor
}: SearchPanelProps) {
const headMenu = useDropdown();
2023-08-27 15:39:49 +03:00
const handleChange = useCallback(
(newValue: LocationHead | undefined) => {
headMenu.hide();
setHead(newValue);
},
[headMenu, setHead]
2024-05-02 17:04:18 +03:00
);
2023-08-26 19:39:49 +03:00
return (
2023-12-30 19:43:24 +03:00
<div
className={clsx(
2024-01-04 14:35:46 +03:00
'sticky top-0', // prettier: split lines
2024-02-22 11:35:27 +03:00
'w-full h-[2.2rem]',
'pr-3 flex items-center',
2023-12-30 19:43:24 +03:00
'border-b',
2024-01-16 13:47:29 +03:00
'text-sm',
2023-12-30 19:43:24 +03:00
'clr-input'
)}
>
<div className={clsx('px-2 self-center', 'min-w-[9rem]', 'select-none', 'whitespace-nowrap')}>
2023-12-28 14:04:44 +03:00
Фильтр
<span className='ml-2'>
{filtered} из {total}
</span>
</div>
<div className='cc-icons'>
<MiniButton
title='Видимость'
icon={<VisibilityIcon value={true} className={tripleToggleColor(isVisible)} />}
onClick={toggleVisible}
/>
<MiniButton
title='Я - Подписчик'
icon={<SubscribeIcon value={true} className={tripleToggleColor(isSubscribed)} />}
onClick={toggleSubscribed}
/>
<MiniButton
title='Я - Владелец'
icon={<IconOwner size='1.25rem' className={tripleToggleColor(isOwned)} />}
onClick={toggleOwned}
/>
<MiniButton
title='Я - Редактор'
icon={<IconEditor size='1.25rem' className={tripleToggleColor(isEditor)} />}
onClick={toggleEditor}
/>
</div>
<div className='flex items-center h-full mx-auto'>
<SearchBar
id='library_search'
2024-06-04 00:25:18 +03:00
placeholder='Атрибуты'
noBorder
2024-06-04 00:25:18 +03:00
className='min-w-[8rem]'
value={query}
onChange={setQuery}
/>
<div ref={headMenu.ref} className='flex items-center h-full py-1 select-none'>
<SelectorButton
transparent
className='h-full rounded-lg'
title={head ? describeLocationHead(head) : 'Выберите каталог'}
hideTitle={headMenu.isOpen}
icon={
head ? (
2024-06-04 11:19:21 +03:00
<LocationIcon value={head} size='1.25rem' />
) : (
<IconFolder size='1.25rem' className='clr-text-controls' />
)
}
onClick={headMenu.toggle}
text={head ?? '//'}
/>
<Dropdown isOpen={headMenu.isOpen} className='z-modalTooltip'>
<DropdownButton className='w-[10rem]' onClick={() => handleChange(undefined)}>
<div className='inline-flex items-center gap-3'>
<IconFolder size='1rem' className='clr-text-controls' />
<span>отображать все</span>
</div>
</DropdownButton>
{Object.values(LocationHead).map((head, index) => {
return (
<DropdownButton
className='w-[10rem]'
key={`${prefixes.location_head_list}${index}`}
onClick={() => handleChange(head)}
title={describeLocationHead(head)}
>
<div className='inline-flex items-center gap-3'>
2024-06-04 11:19:21 +03:00
<LocationIcon value={head} size='1rem' />
{labelLocationHead(head)}
</div>
</DropdownButton>
);
})}
</Dropdown>
</div>
<SearchBar
id='path_search'
placeholder='Путь'
noIcon
noBorder
2024-06-04 00:25:18 +03:00
className='min-w-[5rem]'
value={path}
onChange={setPath}
/>
</div>
<BadgeHelp topic={HelpTopic.UI_LIBRARY} className='max-w-[30rem] text-sm' offset={5} place='right-start' />
</div>
2023-12-28 14:04:44 +03:00
);
2023-08-26 19:39:49 +03:00
}
2023-12-28 14:04:44 +03:00
export default SearchPanel;