crawled-result.tsx 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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-[0.5px] border-divider-regular shadow-xs shadow-shadow-shadow-3')}>
  51. <div className='flex items-center justify-between h-[34px] px-4'>
  52. <CheckboxWithLabel
  53. isChecked={isCheckAll}
  54. onChange={handleCheckedAll} label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)}
  55. labelClassName='system-[13px] leading-[16px] font-medium text-text-secondary'
  56. />
  57. <div className='text-xs text-text-tertiary'>
  58. {t(`${I18N_PREFIX}.scrapTimeInfo`, {
  59. total: list.length,
  60. time: usedTime.toFixed(1),
  61. })}
  62. </div>
  63. </div>
  64. <div className='p-2'>
  65. {list.map((item, index) => (
  66. <CrawledResultItem
  67. key={item.source_url}
  68. isPreview={index === previewIndex}
  69. onPreview={handlePreview(index)}
  70. payload={item}
  71. isChecked={checkedList.some(checkedItem => checkedItem.source_url === item.source_url)}
  72. onCheckChange={handleItemCheckChange(item)}
  73. />
  74. ))}
  75. </div>
  76. </div>
  77. )
  78. }
  79. export default React.memo(CrawledResult)