crawled-result.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import CheckboxWithLabel from './checkbox-with-label'
  6. import CrawledResultItem from './crawled-result-item'
  7. import cn from '@/utils/classnames'
  8. import type { CrawlResultItem } from '@/models/datasets'
  9. const I18N_PREFIX = 'datasetCreation.stepOne.website'
  10. type Props = {
  11. className?: string
  12. list: CrawlResultItem[]
  13. checkedList: CrawlResultItem[]
  14. onSelectedChange: (selected: CrawlResultItem[]) => void
  15. onPreview: (payload: CrawlResultItem) => void
  16. usedTime: number
  17. }
  18. const CrawledResult: FC<Props> = ({
  19. className = '',
  20. list,
  21. checkedList,
  22. onSelectedChange,
  23. onPreview,
  24. usedTime,
  25. }) => {
  26. const { t } = useTranslation()
  27. const isCheckAll = checkedList.length === list.length
  28. const handleCheckedAll = useCallback(() => {
  29. if (!isCheckAll)
  30. onSelectedChange(list)
  31. else
  32. onSelectedChange([])
  33. }, [isCheckAll, list, onSelectedChange])
  34. const handleItemCheckChange = useCallback((item: CrawlResultItem) => {
  35. return (checked: boolean) => {
  36. if (checked)
  37. onSelectedChange([...checkedList, item])
  38. else
  39. onSelectedChange(checkedList.filter(checkedItem => checkedItem.source_url !== item.source_url))
  40. }
  41. }, [checkedList, onSelectedChange])
  42. const [previewIndex, setPreviewIndex] = React.useState<number>(-1)
  43. const handlePreview = useCallback((index: number) => {
  44. return () => {
  45. setPreviewIndex(index)
  46. onPreview(list[index])
  47. }
  48. }, [list, onPreview])
  49. return (
  50. <div className={cn(className, 'border-t border-gray-200')}>
  51. <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'>
  52. <CheckboxWithLabel
  53. isChecked={isCheckAll}
  54. onChange={handleCheckedAll} label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)}
  55. labelClassName='!font-medium'
  56. />
  57. <div>{t(`${I18N_PREFIX}.scrapTimeInfo`, {
  58. total: list.length,
  59. time: usedTime.toFixed(1),
  60. })}</div>
  61. </div>
  62. <div className='p-2'>
  63. {list.map((item, index) => (
  64. <CrawledResultItem
  65. key={item.source_url}
  66. isPreview={index === previewIndex}
  67. onPreview={handlePreview(index)}
  68. payload={item}
  69. isChecked={checkedList.some(checkedItem => checkedItem.source_url === item.source_url)}
  70. onCheckChange={handleItemCheckChange(item)}
  71. />
  72. ))}
  73. </div>
  74. </div>
  75. )
  76. }
  77. export default React.memo(CrawledResult)