import * as React from 'react'; import { Icon } from '@tnsu/ui-kit'; import { useProject } from '../../app/project/ProjectContext'; import { ProjectStatusBadge } from '../../app/project/ProjectStatusBadge'; import { IAccessibleProject } from '../../app/project/projectTypes'; import { useOutsideClose } from '../../shared/hooks/useOutsideClose'; import { ProjectList } from './ProjectList'; import { HUB_TEXTS } from './texts'; import styles from './ProjectPicker.module.scss'; const TEXTS = HUB_TEXTS.picker; /** Поле выбора проекта с поиском — как в stroy-bot-main. */ export const ProjectPicker: React.FC = () => { const { projects, loadState, currentProject, selectProject } = useProject(); const selectedTitle = currentProject?.title ?? ''; const [query, setQuery] = React.useState(selectedTitle); const [isOpen, setIsOpen] = React.useState(false); const wrapperRef = React.useRef(null); const inputRef = React.useRef(null); // Выбор мог поменяться извне (адрес, восстановление из сессии) — пока список закрыт, поле показывает его. React.useEffect(() => { if (!isOpen) setQuery(selectedTitle); }, [selectedTitle, isOpen]); useOutsideClose(wrapperRef, isOpen, (reason) => { setIsOpen(false); setQuery(selectedTitle); if (reason === 'escape') inputRef.current?.blur(); }); const onFocus = (event: React.FocusEvent): void => { event.target.select(); setIsOpen(true); }; const onChange = (event: React.ChangeEvent): void => { setQuery(event.target.value); setIsOpen(true); }; // Очистка не сбрасывает выбранный проект — только текст поиска, чтобы сразу искать другой. const onClear = (event: React.MouseEvent): void => { event.preventDefault(); setQuery(''); setIsOpen(true); inputRef.current?.focus(); }; // mousedown, а не click: иначе поле теряет фокус раньше, чем срабатывает выбор. const onPick = (event: React.MouseEvent, project: IAccessibleProject): void => { event.preventDefault(); selectProject(project); setIsOpen(false); }; return (
{query && ( )} {currentProject?.status && ( )} {isOpen && (
)}
); };