erp-platform/ui/src/views/list/Card.tsx

149 lines
4.5 KiB
TypeScript
Raw Normal View History

import { useCallback, useEffect, useState } from 'react'
import { GridDto } from '@/proxy/form/models'
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
import { Pagination, Select } from '@/components/ui'
import classNames from 'classnames'
import { getList } from '@/services/form.service'
import { FaInbox } from 'react-icons/fa'
import FormView from '../form/FormView'
interface CardProps {
listFormCode: string
searchParams?: URLSearchParams
}
type Option = {
value: number
label: string
}
const CardItem = ({
row,
gridDto,
listFormCode,
}: {
row: any
gridDto: GridDto
listFormCode: string
}) => {
const keyField = gridDto.gridOptions.keyFieldName
const rowId = row[keyField!]
return (
<div className="bg-white dark:bg-neutral-800 border dark:border-neutral-700 flex flex-col p-4">
<div className="flex-grow">
<FormView listFormCode={listFormCode} id={rowId} isSubForm={true} />
</div>
</div>
)
}
const Card = ({ listFormCode, searchParams }: CardProps) => {
const { createSelectDataSource } = useListFormCustomDataSource({})
const [gridDto, setGridDto] = useState<GridDto>()
const [data, setData] = useState<any[]>([])
const [totalCount, setTotalCount] = useState(0)
const [currentPage, setCurrentPage] = useState(1)
const [pageSize, setPageSize] = useState(20)
const [pageSizeOptions, setPageSizeOptions] = useState<Option[]>([])
const onPageSizeSelect = ({ value }: Option) => {
setPageSize(value)
setCurrentPage(1)
}
const onPageChange = (page: number) => {
setCurrentPage(page)
}
const loadData = useCallback(() => {
if (!gridDto) return
const store = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams)
const loadOptions = {
skip: (currentPage - 1) * pageSize,
take: pageSize,
requireTotalCount: true,
}
store.load(loadOptions).then((res: any) => {
setData(res.data)
setTotalCount(res.totalCount || 0)
})
}, [gridDto, listFormCode, searchParams, currentPage, pageSize])
useEffect(() => {
getList({ listFormCode }).then((res: any) => setGridDto(res.data))
}, [listFormCode])
useEffect(() => {
if (!gridDto) return
const pagerOptions = gridDto.gridOptions.pagerOptionDto
const allowedSizes =
pagerOptions?.allowedPageSizes
?.split(',')
.map((s) => Number(s.trim()))
.filter((n) => !isNaN(n) && n > 0) || [20, 50, 100]
setPageSizeOptions(allowedSizes.map((size) => ({ value: size, label: `${size} page` })))
}, [gridDto, listFormCode, searchParams])
useEffect(() => {
loadData()
}, [loadData])
if (!gridDto) return null
return (
<>
{data.length === 0 && (
<div className="flex flex-col items-center justify-center p-10 bg-gray-50 dark:bg-neutral-800/50 rounded-md border-2 border-dashed border-gray-200 dark:border-neutral-700">
<div className="text-center">
<FaInbox className="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" />
<p className="mt-4 text-lg font-semibold text-gray-700 dark:text-gray-300">
Kayıt Bulunamadı
</p>
<p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
Görüntülenecek herhangi bir veri yok.
</p>
</div>
</div>
)}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-4 gap-4">
{data.map((row, idx) => {
const keyField = gridDto.gridOptions.keyFieldName
const rowId = row[keyField!]
return <CardItem key={rowId || idx} row={row} gridDto={gridDto} listFormCode={listFormCode} />
})}
</div>
{gridDto.gridOptions.pagerOptionDto?.visible && totalCount > pageSize && (
<div className={classNames('flex items-center justify-between border-t-1 gap-4 mt-4')}>
<div className="flex items-center gap-2">
<span className="text-xs text-gray-600 dark:text-gray-300">
Toplam {totalCount} kayıt
</span>
<Select
size="xs"
menuPlacement="top"
value={pageSizeOptions.find((o) => o.value === pageSize)}
options={pageSizeOptions}
onChange={(selected) => onPageSizeSelect(selected as Option)}
/>
</div>
<Pagination
currentPage={currentPage}
total={totalCount}
pageSize={pageSize}
onChange={onPageChange}
/>
</div>
)}
</>
)
}
export default Card