2021-12-30 10:24:16 +01:00
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
2021-12-24 10:08:41 +01:00
|
|
|
/* eslint-disable react/jsx-key */
|
2021-12-30 10:24:16 +01:00
|
|
|
import { Box, Checkbox, Flex } from '@chakra-ui/react'
|
2022-01-06 09:40:56 +01:00
|
|
|
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
2022-01-04 15:50:56 +01:00
|
|
|
import React, { useEffect, useMemo, useRef } from 'react'
|
2022-01-04 09:15:33 +01:00
|
|
|
import { Hooks, useFlexLayout, useRowSelect, useTable } from 'react-table'
|
2021-12-24 10:08:41 +01:00
|
|
|
import { parseSubmissionsColumns } from 'services/publicTypebot'
|
2021-12-30 10:24:16 +01:00
|
|
|
import { LoadingRows } from './LoadingRows'
|
2021-12-24 10:08:41 +01:00
|
|
|
|
2022-01-04 09:15:33 +01:00
|
|
|
const defaultCellWidth = 180
|
|
|
|
|
2021-12-30 10:24:16 +01:00
|
|
|
type SubmissionsTableProps = {
|
2022-01-04 15:50:56 +01:00
|
|
|
data?: any
|
2022-01-04 12:25:48 +01:00
|
|
|
hasMore?: boolean
|
2022-01-04 15:50:56 +01:00
|
|
|
onNewSelection: (indices: number[]) => void
|
2022-01-04 12:25:48 +01:00
|
|
|
onScrollToBottom: () => void
|
2021-12-30 10:24:16 +01:00
|
|
|
}
|
2021-12-24 10:08:41 +01:00
|
|
|
|
2021-12-30 10:24:16 +01:00
|
|
|
export const SubmissionsTable = ({
|
2022-01-04 15:50:56 +01:00
|
|
|
data,
|
2022-01-04 12:25:48 +01:00
|
|
|
hasMore,
|
2021-12-30 10:24:16 +01:00
|
|
|
onNewSelection,
|
2022-01-04 12:25:48 +01:00
|
|
|
onScrollToBottom,
|
2021-12-30 10:24:16 +01:00
|
|
|
}: SubmissionsTableProps) => {
|
2021-12-24 10:08:41 +01:00
|
|
|
const { publishedTypebot } = useTypebot()
|
2022-01-04 15:50:56 +01:00
|
|
|
const columns: any = useMemo(
|
2021-12-24 10:08:41 +01:00
|
|
|
() => parseSubmissionsColumns(publishedTypebot),
|
|
|
|
[publishedTypebot]
|
|
|
|
)
|
2022-01-04 15:50:56 +01:00
|
|
|
|
2022-01-04 12:25:48 +01:00
|
|
|
const bottomElement = useRef<HTMLDivElement | null>(null)
|
|
|
|
const tableWrapper = useRef<HTMLDivElement | null>(null)
|
2021-12-30 10:24:16 +01:00
|
|
|
|
|
|
|
const {
|
|
|
|
getTableProps,
|
|
|
|
headerGroups,
|
|
|
|
rows,
|
|
|
|
prepareRow,
|
|
|
|
getTableBodyProps,
|
|
|
|
selectedFlatRows,
|
2022-01-04 09:15:33 +01:00
|
|
|
} = useTable(
|
|
|
|
{ columns, data, defaultColumn: { width: defaultCellWidth } },
|
|
|
|
useRowSelect,
|
|
|
|
checkboxColumnHook,
|
|
|
|
useFlexLayout
|
|
|
|
) as any
|
2021-12-30 10:24:16 +01:00
|
|
|
|
|
|
|
useEffect(() => {
|
2022-01-04 15:50:56 +01:00
|
|
|
onNewSelection(selectedFlatRows.map((row: any) => row.index))
|
2021-12-30 10:24:16 +01:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [selectedFlatRows])
|
|
|
|
|
2022-01-04 12:25:48 +01:00
|
|
|
useEffect(() => {
|
|
|
|
if (!bottomElement.current) return
|
|
|
|
const options: IntersectionObserverInit = {
|
|
|
|
root: tableWrapper.current,
|
|
|
|
threshold: 0,
|
|
|
|
}
|
|
|
|
const observer = new IntersectionObserver(handleObserver, options)
|
|
|
|
if (bottomElement.current) observer.observe(bottomElement.current)
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [bottomElement.current])
|
|
|
|
|
|
|
|
const handleObserver = (entities: any[]) => {
|
|
|
|
const target = entities[0]
|
|
|
|
if (target.isIntersecting) onScrollToBottom()
|
|
|
|
}
|
|
|
|
|
2021-12-24 10:08:41 +01:00
|
|
|
return (
|
2022-01-04 12:25:48 +01:00
|
|
|
<Flex
|
|
|
|
overflow="scroll"
|
|
|
|
maxW="full"
|
|
|
|
maxH="full"
|
|
|
|
className="table-wrapper"
|
|
|
|
rounded="md"
|
|
|
|
data-testid="table-wrapper"
|
|
|
|
pb="20"
|
|
|
|
ref={tableWrapper}
|
|
|
|
>
|
|
|
|
<Box as="table" rounded="md" {...getTableProps()} w="full" h="full">
|
|
|
|
<Box as="thead" pos="sticky" top="0" zIndex={2}>
|
2021-12-30 10:24:16 +01:00
|
|
|
{headerGroups.map((headerGroup: any) => {
|
2021-12-24 10:08:41 +01:00
|
|
|
return (
|
2021-12-30 10:24:16 +01:00
|
|
|
<Flex as="tr" {...headerGroup.getHeaderGroupProps()}>
|
|
|
|
{headerGroup.headers.map((column: any, idx: number) => {
|
2021-12-24 10:08:41 +01:00
|
|
|
return (
|
2021-12-30 10:24:16 +01:00
|
|
|
<Flex
|
2021-12-24 10:08:41 +01:00
|
|
|
py={2}
|
|
|
|
px={4}
|
|
|
|
border="1px"
|
|
|
|
borderColor="gray.200"
|
|
|
|
as="th"
|
|
|
|
color="gray.500"
|
|
|
|
fontWeight="normal"
|
|
|
|
textAlign="left"
|
2022-01-04 12:25:48 +01:00
|
|
|
bgColor={'white'}
|
2021-12-24 10:08:41 +01:00
|
|
|
{...column.getHeaderProps()}
|
2022-01-04 09:15:33 +01:00
|
|
|
style={{
|
|
|
|
width: idx === 0 ? '50px' : `${defaultCellWidth}px`,
|
|
|
|
}}
|
2021-12-24 10:08:41 +01:00
|
|
|
>
|
|
|
|
{column.render('Header')}
|
2021-12-30 10:24:16 +01:00
|
|
|
</Flex>
|
2021-12-24 10:08:41 +01:00
|
|
|
)
|
|
|
|
})}
|
2021-12-30 10:24:16 +01:00
|
|
|
</Flex>
|
2021-12-24 10:08:41 +01:00
|
|
|
)
|
|
|
|
})}
|
|
|
|
</Box>
|
|
|
|
|
|
|
|
<Box as="tbody" {...getTableBodyProps()}>
|
2022-01-04 12:25:48 +01:00
|
|
|
{rows.map((row: any, idx: number) => {
|
2021-12-24 10:08:41 +01:00
|
|
|
prepareRow(row)
|
|
|
|
return (
|
2022-01-04 12:25:48 +01:00
|
|
|
<Flex
|
|
|
|
as="tr"
|
|
|
|
{...row.getRowProps()}
|
|
|
|
ref={(ref) => {
|
2022-01-04 15:50:56 +01:00
|
|
|
if (idx === data.length - 10) bottomElement.current = ref
|
2022-01-04 12:25:48 +01:00
|
|
|
}}
|
|
|
|
>
|
2021-12-30 10:24:16 +01:00
|
|
|
{row.cells.map((cell: any, idx: number) => {
|
2021-12-24 10:08:41 +01:00
|
|
|
return (
|
2021-12-30 10:24:16 +01:00
|
|
|
<Flex
|
2021-12-24 10:08:41 +01:00
|
|
|
py={2}
|
|
|
|
px={4}
|
|
|
|
border="1px"
|
|
|
|
as="td"
|
|
|
|
borderColor="gray.200"
|
2022-01-04 12:25:48 +01:00
|
|
|
bgColor={'white'}
|
2021-12-24 10:08:41 +01:00
|
|
|
{...cell.getCellProps()}
|
2022-01-04 09:15:33 +01:00
|
|
|
style={{
|
|
|
|
width: idx === 0 ? '50px' : `${defaultCellWidth}px`,
|
|
|
|
}}
|
2021-12-24 10:08:41 +01:00
|
|
|
>
|
|
|
|
{cell.render('Cell')}
|
2021-12-30 10:24:16 +01:00
|
|
|
</Flex>
|
2021-12-24 10:08:41 +01:00
|
|
|
)
|
|
|
|
})}
|
2021-12-30 10:24:16 +01:00
|
|
|
</Flex>
|
2021-12-24 10:08:41 +01:00
|
|
|
)
|
|
|
|
})}
|
2022-01-04 15:50:56 +01:00
|
|
|
{hasMore === true && <LoadingRows totalColumns={columns.length} />}
|
2021-12-24 10:08:41 +01:00
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
</Flex>
|
|
|
|
)
|
|
|
|
}
|
2021-12-30 10:24:16 +01:00
|
|
|
|
|
|
|
const checkboxColumnHook = (hooks: Hooks<any>) => {
|
|
|
|
hooks.visibleColumns.push((columns) => [
|
|
|
|
{
|
|
|
|
id: 'selection',
|
|
|
|
Header: ({ getToggleAllRowsSelectedProps }: any) => (
|
|
|
|
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
|
|
|
|
),
|
|
|
|
Cell: ({ row }: any) => (
|
|
|
|
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
|
|
|
|
),
|
|
|
|
},
|
|
|
|
...columns,
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
|
|
|
const IndeterminateCheckbox = React.forwardRef(
|
|
|
|
({ indeterminate, checked, ...rest }: any, ref) => {
|
|
|
|
const defaultRef = React.useRef()
|
|
|
|
const resolvedRef: any = ref || defaultRef
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Checkbox
|
|
|
|
ref={resolvedRef}
|
|
|
|
{...rest}
|
|
|
|
isIndeterminate={indeterminate}
|
|
|
|
isChecked={checked}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|