Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
gilour
/
gitep_front
/
src
/
entities
/
article
/
ui
:
articleInputSelect.tsx
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
import React, { useState, useEffect, useMemo } from 'react'; import { Flex, Select } from 'antd'; import styles from './article-input-select.module.scss'; import ArrowShow from '@shared/assets/images/icons/arrow-show.svg?react'; import CheckSvg from '@shared/assets/images/icons/check-new.svg'; import { belongsToProject, safeFind } from '@/pages/main/utils'; import { useUnit } from 'effector-react'; const { Option, OptGroup } = Select; import { $articlesGroupsStore } from '@/entities/article/model'; interface Organization { id: number; name: string; } interface OrganizationSelectProps { initialOptions?: Organization[]; isArticleValidate?: boolean; value?: number | null; onChange?: (value: number) => void; onSearch?: (value: string) => void; disabled: boolean; paymentCard: any; index: number; } const ArticleInputSelect: React.FC<OrganizationSelectProps> = ({ initialOptions = [], value, isArticleValidate, onChange, onSearch, disabled, paymentCard, index, }) => { const [options, setOptions] = useState<Organization[]>(initialOptions); const [selectedValue, setSelectedValue] = useState<number | null | undefined>( value, ); const [searchQuery, setSearchQuery] = useState<string>(''); const [open, setOpen] = useState<boolean>(false); const articles = useUnit($articlesGroupsStore).articlesGroups; const isArticleBelongProject = (articleId: any) => { const art = safeFind( articles, (a: any) => String(a.id) === String(articleId), ); return belongsToProject(art, paymentCard?.distributions[index]?.project_id); }; useEffect(() => { if (paymentCard?.distributions[index]?.project_id) { const filteredArticlesByPaymentType = articles.filter((article: any) => paymentCard.payment_type === 'reception_from_1c' ? article.article_type === 'credit' : article.article_type === 'debit', ); const idsToRemove = new Set(initialOptions.map((item) => item.id)); const articlesWithoutExistArticleInProject = filteredArticlesByPaymentType.filter( (item: any) => !idsToRemove.has(item.id), ); setOptions( Array.isArray(initialOptions) ? [...initialOptions, ...articlesWithoutExistArticleInProject] : [], ); } else { setOptions( Array.isArray(initialOptions) ? initialOptions.filter((option: any) => !option.default_in_project) : [], ); } }, [initialOptions, paymentCard?.distributions[index]?.project_id]); useEffect(() => { setSelectedValue(value); }, [value]); // разделение статей на группы const groupedOptions = useMemo(() => { const filteredOptions = options.filter((item: any) => item.id !== 1); if (!searchQuery) { return { projectArticles: filteredOptions.filter((option) => isArticleBelongProject(option.id), ), nonProjectArticles: filteredOptions.filter( (option) => !isArticleBelongProject(option.id), ), }; } const filteredBySearch = filteredOptions.filter((option) => option.name.toLowerCase().includes(searchQuery.toLowerCase()), ); return { projectArticles: filteredBySearch.filter((option) => isArticleBelongProject(option.id), ), nonProjectArticles: filteredBySearch.filter( (option) => !isArticleBelongProject(option.id), ), }; }, [options, searchQuery, paymentCard?.distributions[index]?.project_id]); const handleSelectChange = (value: number) => { setSelectedValue(value); onChange?.(value); setOpen(false); }; const handleClear = () => { setSelectedValue(null); setSearchQuery(''); }; const handleSearch = (searchText: string) => { setSearchQuery(searchText); onSearch?.(searchText); }; const handleDropdownOpenChange = (open: boolean) => { setOpen(open); if (!open) { setSearchQuery(''); } }; const renderOptions = () => { const hasProject = paymentCard?.distributions[index]?.project_id; if (!hasProject || searchQuery) { const allOptions = [ ...groupedOptions.projectArticles, ...groupedOptions.nonProjectArticles, ]; return allOptions.map((option) => ( <Option key={option.id} value={option.id} label={option.name}> <Flex align='center' justify='space-between' style={{ width: '100%' }} > <span style={{ maxWidth: '260px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', }} > {option.name} {hasProject && !isArticleBelongProject(option.id) && ( <span style={{ marginLeft: '8px', fontSize: '12px' }}> Не в проекте </span> )} </span> {option.id === selectedValue && <img src={CheckSvg} alt='' />} </Flex> </Option> )); } return ( <> {/* В проекте */} {groupedOptions.projectArticles.length > 0 && ( <OptGroup key='in-project' label={ <span style={{ fontSize: '12px', fontWeight: 400 }}> В проекте </span> } > {groupedOptions.projectArticles.map((option) => ( <Option key={`in-${option.id}`} value={option.id} label={option.name} > <Flex align='center' justify='space-between' style={{ width: '100%' }} > <span style={{ maxWidth: '260px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', }} > {option.name} </span> {option.id === selectedValue && <img src={CheckSvg} alt='' />} </Flex> </Option> ))} </OptGroup> )} {/* "Не в проекте" */} {groupedOptions.nonProjectArticles.length > 0 && ( <OptGroup key='not-in-project' label={ <span style={{ fontSize: '12px', fontWeight: 400 }}> Не в проекте </span> } > {groupedOptions.nonProjectArticles.map((option) => ( <Option key={`out-${option.id}`} value={option.id} label={option.name} > <Flex align='center' justify='space-between' style={{ width: '100%' }} > <span style={{ maxWidth: '260px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', }} > {option.name} </span> {option.id === selectedValue && <img src={CheckSvg} alt='' />} </Flex> </Option> ))} </OptGroup> )} {groupedOptions.projectArticles.length === 0 && groupedOptions.nonProjectArticles.length === 0 && ( <Option disabled value='no-data'> Нет доступных статей </Option> )} </> ); }; return ( <Select showSearch style={{ width: '100%', height: '40px' }} placeholder='Выберите статью' onChange={handleSelectChange} onClear={handleClear} allowClear onSearch={handleSearch} value={selectedValue} status={isArticleValidate ? 'error' : ''} notFoundContent={options.length === 0 ? 'Ничего не найдено' : null} filterOption={false} disabled={disabled} open={open} onDropdownVisibleChange={handleDropdownOpenChange} suffixIcon={<ArrowShow className={styles.arrowIcon} />} optionFilterProp='children' optionLabelProp='label' popupMatchSelectWidth={400} > {renderOptions()} </Select> ); }; export default ArticleInputSelect;