|
'use client' |
|
import type { FC } from 'react' |
|
import React, { useCallback } from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import CheckboxWithLabel from './base/checkbox-with-label' |
|
import CrawledResultItem from './crawled-result-item' |
|
import cn from '@/utils/classnames' |
|
import type { CrawlResultItem } from '@/models/datasets' |
|
|
|
const I18N_PREFIX = 'datasetCreation.stepOne.website' |
|
|
|
type Props = { |
|
className?: string |
|
list: CrawlResultItem[] |
|
checkedList: CrawlResultItem[] |
|
onSelectedChange: (selected: CrawlResultItem[]) => void |
|
onPreview: (payload: CrawlResultItem) => void |
|
usedTime: number |
|
} |
|
|
|
const CrawledResult: FC<Props> = ({ |
|
className = '', |
|
list, |
|
checkedList, |
|
onSelectedChange, |
|
onPreview, |
|
usedTime, |
|
}) => { |
|
const { t } = useTranslation() |
|
|
|
const isCheckAll = checkedList.length === list.length |
|
|
|
const handleCheckedAll = useCallback(() => { |
|
if (!isCheckAll) |
|
onSelectedChange(list) |
|
|
|
else |
|
onSelectedChange([]) |
|
}, [isCheckAll, list, onSelectedChange]) |
|
|
|
const handleItemCheckChange = useCallback((item: CrawlResultItem) => { |
|
return (checked: boolean) => { |
|
if (checked) |
|
onSelectedChange([...checkedList, item]) |
|
|
|
else |
|
onSelectedChange(checkedList.filter(checkedItem => checkedItem.source_url !== item.source_url)) |
|
} |
|
}, [checkedList, onSelectedChange]) |
|
|
|
const [previewIndex, setPreviewIndex] = React.useState<number>(-1) |
|
const handlePreview = useCallback((index: number) => { |
|
return () => { |
|
setPreviewIndex(index) |
|
onPreview(list[index]) |
|
} |
|
}, [list, onPreview]) |
|
|
|
return ( |
|
<div className={cn(className, 'border-t border-gray-200')}> |
|
<div className='flex items-center justify-between h-[34px] px-4 bg-gray-50 shadow-xs border-b-[0.5px] border-black/8 text-xs font-normal text-gray-700'> |
|
<CheckboxWithLabel |
|
isChecked={isCheckAll} |
|
onChange={handleCheckedAll} label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)} |
|
labelClassName='!font-medium' |
|
/> |
|
<div>{t(`${I18N_PREFIX}.scrapTimeInfo`, { |
|
total: list.length, |
|
time: usedTime.toFixed(1), |
|
})}</div> |
|
</div> |
|
<div className='p-2'> |
|
{list.map((item, index) => ( |
|
<CrawledResultItem |
|
key={item.source_url} |
|
isPreview={index === previewIndex} |
|
onPreview={handlePreview(index)} |
|
payload={item} |
|
isChecked={checkedList.some(checkedItem => checkedItem.source_url === item.source_url)} |
|
onCheckChange={handleItemCheckChange(item)} |
|
/> |
|
))} |
|
</div> |
|
</div> |
|
) |
|
} |
|
export default React.memo(CrawledResult) |
|
|