| 'use client' | |
| import type { FC } from 'react' | |
| import React, { useCallback } from 'react' | |
| import { useTranslation } from 'react-i18next' | |
| import CheckboxWithLabel from './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) | |