import { XMarkIcon } from '@heroicons/react/24/outline'; import { t } from 'i18next'; import { useCallback, useEffect, useState } from 'react'; import { toast, Toaster } from 'sonner'; import DefaultRadioGroup from '../../../components/button/DefaultRadioGroup'; import PrimaryButton from '../../../components/button/PrimaryButton'; import SelectDropdown from '../../../components/dropdown/SelectDropdown'; import { mergeVulnerability } from '../../../services/vulnerabilities'; type Details = { locale: string; title?: string; vulnType?: string; description?: string; observation?: string; remediation?: string; cwes: string[]; references: string[]; customFields: string[]; }; type VulnerabilityData = { _id: string; details: Details[]; }; type ListItem = { id: number; value: string; label?: string; locale?: string; }; type RadioOption = { id: string; label: string; value: string; disabled?: boolean; }; type MergeVulnerability = { idIzq: string; rightSide: { vulnId: string; locale: string; }; }; type MergeVulnProps = { isOpen: boolean; handlerIsOpen: React.Dispatch>; vulnerabilities: VulnerabilityData[]; languages: ListItem[]; refreshVulns: () => void; handleOnSuccess: (message: string) => void; }; const MergeVulnerabilities: React.FC = ({ isOpen, handlerIsOpen, vulnerabilities, languages, refreshVulns, handleOnSuccess, }) => { const [selectedLanguageLeft, setSelectedLanguageLeft] = useState(null); const [currentRadioOptionsLeft, setCurrentRadioOptionsLeft] = useState< RadioOption[] >([]); const [selectedRadioLeft, setSelectedRadioLeft] = useState(''); const [selectedLanguageRight, setSelectedLanguageRight] = useState(null); const [currentRadioOptionsRight, setCurrentRadioOptionsRight] = useState< RadioOption[] >([]); const [selectedRadioRight, setSelectedRadioRight] = useState(''); const [allDetails] = useState( vulnerabilities.flatMap(vuln => vuln.details.map(detail => ({ id: vuln._id, locale: detail.locale, title: detail.title, })), ), ); const checkLeft = useCallback(() => { const leftFiltered = allDetails.filter( detailIter => detailIter.locale === selectedLanguageLeft?.value, ); const rightFilteredIds = new Set( allDetails .filter( detailIter => detailIter.locale === selectedLanguageRight?.value, ) .map(item => item.id), ); const leftOptions = leftFiltered .filter(item => !rightFilteredIds.has(item.id)) .map(item => ({ id: item.id, value: [item.id, item.locale].join('.'), label: item.title ?? '', })); setCurrentRadioOptionsLeft(leftOptions); }, [allDetails, selectedLanguageLeft?.value, selectedLanguageRight?.value]); const checkRight = useCallback(() => { const rightFiltered = allDetails.filter( detailIter => detailIter.locale === selectedLanguageRight?.value, ); const leftFilteredIds = new Set( allDetails .filter(detailIter => detailIter.locale === selectedLanguageLeft?.value) .map(item => item.id), ); const rightOptions = rightFiltered .filter(item => !leftFilteredIds.has(item.id)) .map(item => ({ id: item.id, value: [item.id, item.locale].join('.'), label: item.title ?? '', })); setCurrentRadioOptionsRight(rightOptions); }, [allDetails, selectedLanguageLeft?.value, selectedLanguageRight?.value]); useEffect(() => { checkLeft(); checkRight(); }, [checkLeft, checkRight, selectedLanguageLeft, selectedLanguageRight]); const handlerLeftChange = (item: ListItem) => { setSelectedLanguageLeft(item); }; const handlerRightChange = (item: ListItem) => { setSelectedLanguageRight(item); }; const onSubmitMerge = async () => { if (selectedRadioLeft !== '' && selectedRadioRight !== '') { try { const [leftId] = selectedRadioLeft.split('.'); const [rightId, rightLocale] = selectedRadioRight.split('.'); const mergeObject: MergeVulnerability = { idIzq: leftId, rightSide: { vulnId: rightId, locale: rightLocale, }, }; const response = await mergeVulnerability(mergeObject); if (response.status === 'success') { handleOnSuccess(t('msg.vulnerabilityMergeOk')); } } catch (error) { console.error('Error:', error); toast.error(t('err.failedMergeVulnerabilities')); return; } } else { toast.error(t('err.mergeNoVulnerabilitiesSelected')); return; } refreshVulns(); handlerIsOpen(false); }; return (