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

221 lines
7.8 KiB
TypeScript
Raw Normal View History

'use client';
2023-08-26 19:39:49 +03:00
import clsx from 'clsx';
2023-08-27 15:39:49 +03:00
import { LocationIcon, VisibilityIcon } from '@/components/DomainIcons';
2024-09-27 12:04:10 +03:00
import {
IconEditor,
IconFilterReset,
IconFolder,
IconFolderSearch,
IconFolderTree,
IconOwner,
IconUserSearch
} from '@/components/Icons';
2024-06-19 22:10:15 +03:00
import { CProps } from '@/components/props';
2024-09-27 12:04:10 +03:00
import SelectUser from '@/components/select/SelectUser';
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';
2024-09-27 12:04:10 +03:00
import { useUsers } from '@/context/UsersContext';
import useDropdown from '@/hooks/useDropdown';
import { LocationHead } from '@/models/library';
import { useHasCustomFilter, useLibrarySearchStore } from '@/stores/librarySearch';
2024-06-21 11:17:50 +03:00
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 ToolbarSearchProps {
2023-12-28 14:04:44 +03:00
total: number;
filtered: number;
2023-08-26 19:39:49 +03:00
}
function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
const headMenu = useDropdown();
2024-09-27 12:04:10 +03:00
const userMenu = useDropdown();
const { users } = useUsers();
const query = useLibrarySearchStore(state => state.query);
const setQuery = useLibrarySearchStore(state => state.setQuery);
const path = useLibrarySearchStore(state => state.path);
const setPath = useLibrarySearchStore(state => state.setPath);
const head = useLibrarySearchStore(state => state.head);
const setHead = useLibrarySearchStore(state => state.setHead);
const folderMode = useLibrarySearchStore(state => state.folderMode);
const toggleFolderMode = useLibrarySearchStore(state => state.toggleFolderMode);
const isOwned = useLibrarySearchStore(state => state.isOwned);
const toggleOwned = useLibrarySearchStore(state => state.toggleOwned);
const isEditor = useLibrarySearchStore(state => state.isEditor);
const toggleEditor = useLibrarySearchStore(state => state.toggleEditor);
const isVisible = useLibrarySearchStore(state => state.isVisible);
const toggleVisible = useLibrarySearchStore(state => state.toggleVisible);
const filterUser = useLibrarySearchStore(state => state.filterUser);
const setFilterUser = useLibrarySearchStore(state => state.setFilterUser);
const resetFilter = useLibrarySearchStore(state => state.resetFilter);
const hasCustomFilter = useHasCustomFilter();
const userActive = isOwned !== undefined || isEditor !== undefined || filterUser !== undefined;
2023-08-27 15:39:49 +03:00
function handleChange(newValue: LocationHead | undefined) {
headMenu.hide();
setHead(newValue);
}
2024-05-02 17:04:18 +03:00
function handleToggleFolder() {
2024-06-19 22:10:15 +03:00
headMenu.hide();
toggleFolderMode();
}
function handleFolderClick(event: CProps.EventMouse) {
if (event.ctrlKey || event.metaKey) {
toggleFolderMode();
} else {
headMenu.toggle();
}
}
2024-06-19 22:10:15 +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-09-15 21:19:17 +03:00
'h-[2.2rem]',
'flex items-center gap-3',
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
2024-09-15 21:19:17 +03:00
className={clsx(
'ml-3 pt-1 self-center',
2024-09-27 12:04:10 +03:00
'min-w-[4.5rem] sm:min-w-[7.4rem]',
2024-09-15 21:19:17 +03:00
'select-none',
'whitespace-nowrap'
)}
>
2024-06-05 19:42:48 +03:00
{filtered} из {total}
2023-12-28 14:04:44 +03:00
</div>
2024-09-27 12:04:10 +03:00
<div className='cc-icons'>
<MiniButton
title='Видимость'
icon={<VisibilityIcon value={true} className={tripleToggleColor(isVisible)} />}
onClick={toggleVisible}
/>
2024-06-18 15:07:41 +03:00
2024-09-27 12:04:10 +03:00
<div ref={userMenu.ref} className='flex'>
2024-06-18 15:07:41 +03:00
<MiniButton
2024-09-27 12:04:10 +03:00
title='Поиск пользователя'
hideTitle={userMenu.isOpen}
icon={<IconUserSearch size='1.25rem' className={userActive ? 'icon-green' : 'icon-primary'} />}
onClick={userMenu.toggle}
2024-06-18 15:07:41 +03:00
/>
2024-09-27 12:04:10 +03:00
<Dropdown isOpen={userMenu.isOpen}>
<DropdownButton
text='Я - Владелец'
icon={<IconOwner size='1.25rem' className={tripleToggleColor(isOwned)} />}
onClick={toggleOwned}
/>
<DropdownButton
text='Я - Редактор'
icon={<IconEditor size='1.25rem' className={tripleToggleColor(isEditor)} />}
onClick={toggleEditor}
/>
<SelectUser
noBorder
placeholder='Выберите владельца'
className='min-w-[15rem] text-sm mx-1 mb-1'
items={users}
value={filterUser}
onSelectValue={setFilterUser}
/>
2024-09-27 12:04:10 +03:00
</Dropdown>
2024-06-14 21:43:37 +03:00
</div>
2024-09-27 12:04:10 +03:00
<MiniButton
title='Сбросить фильтры'
icon={<IconFilterReset size='1.25rem' className='icon-primary' />}
onClick={resetFilter}
disabled={!hasCustomFilter}
/>
</div>
<div className='flex h-full flex-grow pr-4'>
<SearchBar
id='library_search'
2024-06-05 19:42:48 +03:00
placeholder='Поиск'
noBorder
2024-09-27 12:04:10 +03:00
className={clsx('min-w-[7rem] sm:min-w-[10rem] max-w-[20rem]', folderMode && 'flex-grow')}
query={query}
onChangeQuery={setQuery}
/>
2024-06-19 22:10:15 +03:00
{!folderMode ? (
<div ref={headMenu.ref} className='flex items-center h-full py-1 select-none'>
<SelectorButton
transparent
className='h-full rounded-lg'
titleHtml={(head ? describeLocationHead(head) : 'Выберите каталог') + '<br/>Ctrl + клик - Проводник'}
hideTitle={headMenu.isOpen}
icon={
head ? (
<LocationIcon value={head} size='1.25rem' />
) : (
2024-09-27 12:04:10 +03:00
<IconFolderSearch size='1.25rem' className='clr-text-controls' />
2024-06-19 22:10:15 +03:00
)
}
onClick={handleFolderClick}
text={head ?? '//'}
/>
<Dropdown isOpen={headMenu.isOpen} stretchLeft className='z-modalTooltip'>
2024-09-27 12:04:10 +03:00
<DropdownButton title='Переключение в режим Проводник' onClick={handleToggleFolder}>
2024-06-20 11:50:37 +03:00
<div className='inline-flex items-center gap-3'>
<IconFolderTree size='1rem' className='clr-text-controls' />
<span>проводник...</span>
</div>
</DropdownButton>
2024-06-19 22:10:15 +03:00
<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'>
<LocationIcon value={head} size='1rem' />
{labelLocationHead(head)}
</div>
</DropdownButton>
);
})}
</Dropdown>
</div>
) : null}
{!folderMode ? (
<SearchBar
id='path_search'
placeholder='Путь'
noIcon
noBorder
2024-09-27 12:04:10 +03:00
className='w-[4.5rem] sm:w-[5rem] flex-grow'
query={path}
onChangeQuery={setPath}
/>
2024-06-19 22:10:15 +03:00
) : null}
</div>
</div>
2023-12-28 14:04:44 +03:00
);
2023-08-26 19:39:49 +03:00
}
export default ToolbarSearch;