2025-09-21 15:11:12 +00:00
|
|
|
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
2025-09-21 20:05:13 +00:00
|
|
|
|
import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models'
|
2025-09-21 15:11:12 +00:00
|
|
|
|
import { captionize } from 'devextreme/core/utils/inflector'
|
2025-09-21 14:42:24 +00:00
|
|
|
|
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
|
2025-09-22 09:11:15 +00:00
|
|
|
|
import { Button, Pagination, Select } from '@/components/ui'
|
2025-09-21 14:42:24 +00:00
|
|
|
|
import classNames from 'classnames'
|
|
|
|
|
|
import { getList } from '@/services/form.service'
|
2025-09-22 09:11:15 +00:00
|
|
|
|
import { FaInbox, FaSearch } from 'react-icons/fa'
|
2025-09-21 15:11:12 +00:00
|
|
|
|
import FormDevExpress from '../form/FormDevExpress'
|
2025-09-21 20:05:13 +00:00
|
|
|
|
import { GroupItem } from 'devextreme/ui/form'
|
2025-09-21 15:11:12 +00:00
|
|
|
|
import { Form as FormDx } from 'devextreme-react/form'
|
|
|
|
|
|
import FormButtons from '../form/FormButtons'
|
|
|
|
|
|
import { useNavigate } from 'react-router-dom'
|
|
|
|
|
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
|
|
|
|
|
import CustomStore from 'devextreme/data/custom_store'
|
2025-09-21 20:05:13 +00:00
|
|
|
|
import { PermissionResults, SimpleItemWithColData } from '../form/types'
|
2025-09-21 15:11:12 +00:00
|
|
|
|
import { usePermission } from '@/utils/hooks/usePermission'
|
|
|
|
|
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
2025-09-21 21:32:05 +00:00
|
|
|
|
import { useLookupDataSource } from '../form/useLookupDataSource'
|
2025-09-22 09:11:15 +00:00
|
|
|
|
import { Container, Loading } from '@/components/shared'
|
|
|
|
|
|
import WidgetGroup from '@/components/common/WidgetGroup'
|
|
|
|
|
|
import { GridExtraFilterState } from './Utils'
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
|
|
|
|
|
interface CardProps {
|
|
|
|
|
|
listFormCode: string
|
|
|
|
|
|
searchParams?: URLSearchParams
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type Option = {
|
|
|
|
|
|
value: number
|
|
|
|
|
|
label: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const CardItem = ({
|
2025-09-21 15:11:12 +00:00
|
|
|
|
isSubForm,
|
2025-09-21 14:42:24 +00:00
|
|
|
|
row,
|
|
|
|
|
|
gridDto,
|
|
|
|
|
|
listFormCode,
|
2025-09-21 15:11:12 +00:00
|
|
|
|
dataSource,
|
|
|
|
|
|
refreshData,
|
2025-09-22 09:11:15 +00:00
|
|
|
|
getCachedLookupDataSource,
|
2025-09-21 14:42:24 +00:00
|
|
|
|
}: {
|
2025-09-21 15:11:12 +00:00
|
|
|
|
isSubForm?: boolean
|
2025-09-21 14:42:24 +00:00
|
|
|
|
row: any
|
|
|
|
|
|
gridDto: GridDto
|
|
|
|
|
|
listFormCode: string
|
2025-09-21 15:11:12 +00:00
|
|
|
|
dataSource: CustomStore
|
|
|
|
|
|
refreshData: () => void
|
2025-09-21 21:32:05 +00:00
|
|
|
|
getCachedLookupDataSource: (editorOptions: any, colData: any) => any
|
2025-09-21 14:42:24 +00:00
|
|
|
|
}) => {
|
2025-09-21 15:11:12 +00:00
|
|
|
|
const [formData, setFormData] = useState(row)
|
|
|
|
|
|
const refForm = useRef<FormDx>(null)
|
|
|
|
|
|
const navigate = useNavigate()
|
|
|
|
|
|
const { checkPermission } = usePermission()
|
|
|
|
|
|
const { translate } = useLocalization()
|
|
|
|
|
|
|
2025-09-21 14:42:24 +00:00
|
|
|
|
const keyField = gridDto.gridOptions.keyFieldName
|
|
|
|
|
|
const rowId = row[keyField!]
|
|
|
|
|
|
|
2025-09-21 21:32:05 +00:00
|
|
|
|
// Form Items
|
2025-09-21 15:11:12 +00:00
|
|
|
|
const formItems: GroupItem[] = useMemo(() => {
|
|
|
|
|
|
if (!gridDto) return []
|
|
|
|
|
|
|
2025-09-21 21:32:05 +00:00
|
|
|
|
return gridDto.gridOptions.editingFormDto
|
|
|
|
|
|
?.sort((a, b) => (a.order >= b.order ? 1 : -1))
|
|
|
|
|
|
.map((e) => {
|
2025-09-21 20:05:13 +00:00
|
|
|
|
return {
|
|
|
|
|
|
itemType: e.itemType,
|
|
|
|
|
|
colCount: e.colCount,
|
|
|
|
|
|
colSpan: e.colSpan,
|
|
|
|
|
|
caption: e.caption,
|
|
|
|
|
|
items: e.items
|
2025-09-21 21:32:05 +00:00
|
|
|
|
?.sort((a, b) => (a.order >= b.order ? 1 : -1))
|
2025-09-21 20:05:13 +00:00
|
|
|
|
.map((i: EditingFormItemDto) => {
|
|
|
|
|
|
let editorOptions = {}
|
2025-09-21 21:32:05 +00:00
|
|
|
|
const colData = gridDto.columnFormats.find((x) => x.fieldName === i.dataField)
|
|
|
|
|
|
|
2025-09-21 20:05:13 +00:00
|
|
|
|
try {
|
|
|
|
|
|
editorOptions = i.editorOptions && JSON.parse(i.editorOptions)
|
|
|
|
|
|
} catch {}
|
2025-09-21 21:32:05 +00:00
|
|
|
|
|
2025-09-21 20:05:13 +00:00
|
|
|
|
const item: SimpleItemWithColData = {
|
2025-09-21 21:32:05 +00:00
|
|
|
|
canRead: colData?.canRead ?? false,
|
|
|
|
|
|
canUpdate: colData?.canUpdate ?? false,
|
|
|
|
|
|
canCreate: colData?.canCreate ?? false,
|
|
|
|
|
|
canExport: colData?.canExport ?? false,
|
2025-09-21 20:05:13 +00:00
|
|
|
|
dataField: i.dataField,
|
|
|
|
|
|
name: i.dataField,
|
|
|
|
|
|
editorType2: i.editorType2,
|
|
|
|
|
|
editorType:
|
|
|
|
|
|
i.editorType2 == PlatformEditorTypes.dxGridBox ? 'dxDropDownBox' : i.editorType2,
|
|
|
|
|
|
colSpan: i.colSpan,
|
|
|
|
|
|
isRequired: i.isRequired,
|
2025-09-21 21:32:05 +00:00
|
|
|
|
editorOptions: {
|
|
|
|
|
|
...editorOptions,
|
|
|
|
|
|
...(colData?.lookupDto?.dataSourceType
|
|
|
|
|
|
? {
|
|
|
|
|
|
dataSource: getCachedLookupDataSource(colData?.editorOptions, colData),
|
|
|
|
|
|
valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(),
|
|
|
|
|
|
displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(),
|
|
|
|
|
|
}
|
|
|
|
|
|
: {}),
|
|
|
|
|
|
},
|
|
|
|
|
|
colData,
|
2025-09-21 20:05:13 +00:00
|
|
|
|
tagBoxOptions: i.tagBoxOptions,
|
|
|
|
|
|
gridBoxOptions: i.gridBoxOptions,
|
|
|
|
|
|
}
|
|
|
|
|
|
if (i.dataField.indexOf(':') >= 0) {
|
|
|
|
|
|
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
|
|
|
|
|
}
|
|
|
|
|
|
item.editorOptions = {
|
|
|
|
|
|
...item.editorOptions,
|
|
|
|
|
|
readOnly: true,
|
|
|
|
|
|
}
|
|
|
|
|
|
return item
|
|
|
|
|
|
}),
|
|
|
|
|
|
} as GroupItem
|
|
|
|
|
|
})
|
2025-09-21 21:32:05 +00:00
|
|
|
|
}, [gridDto, getCachedLookupDataSource])
|
2025-09-21 15:11:12 +00:00
|
|
|
|
|
|
|
|
|
|
const permissionResults: PermissionResults = {
|
|
|
|
|
|
c:
|
|
|
|
|
|
gridDto?.gridOptions.editingOptionDto.allowAdding === true &&
|
|
|
|
|
|
checkPermission(gridDto?.gridOptions.permissionDto.c),
|
|
|
|
|
|
r: checkPermission(gridDto?.gridOptions.permissionDto.r),
|
|
|
|
|
|
u:
|
|
|
|
|
|
gridDto?.gridOptions.editingOptionDto.allowUpdating === true &&
|
|
|
|
|
|
checkPermission(gridDto?.gridOptions.permissionDto.u),
|
|
|
|
|
|
d:
|
|
|
|
|
|
gridDto?.gridOptions.editingOptionDto.allowDeleting === true &&
|
|
|
|
|
|
checkPermission(gridDto?.gridOptions.permissionDto.d),
|
|
|
|
|
|
e: checkPermission(gridDto?.gridOptions.permissionDto.e),
|
|
|
|
|
|
i: checkPermission(gridDto?.gridOptions.permissionDto.i),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const onActionEdit = () => {
|
|
|
|
|
|
navigate(
|
|
|
|
|
|
ROUTES_ENUM.protected.admin.formEdit
|
|
|
|
|
|
.replace(':listFormCode', listFormCode)
|
|
|
|
|
|
.replace(':id', rowId!),
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const onActionNew = () => {
|
|
|
|
|
|
navigate(ROUTES_ENUM.protected.admin.formNew.replace(':listFormCode', listFormCode))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-21 14:42:24 +00:00
|
|
|
|
return (
|
2025-09-21 15:11:12 +00:00
|
|
|
|
<div className="bg-white dark:bg-neutral-800 border dark:border-neutral-700 flex flex-col groupp p-2">
|
|
|
|
|
|
<div className={`flex items-center mb-2 ${isSubForm ? 'justify-center' : 'justify-between'}`}>
|
|
|
|
|
|
{!isSubForm && <h3>{translate('::' + gridDto?.gridOptions.title)}</h3>}
|
|
|
|
|
|
{permissionResults && (
|
|
|
|
|
|
<FormButtons
|
|
|
|
|
|
isSubForm={true}
|
|
|
|
|
|
mode="view"
|
|
|
|
|
|
listFormCode={listFormCode}
|
|
|
|
|
|
id={rowId}
|
|
|
|
|
|
gridDto={gridDto}
|
|
|
|
|
|
commandColumnData={{ buttons: [] }}
|
|
|
|
|
|
dataSource={dataSource}
|
|
|
|
|
|
permissions={permissionResults}
|
|
|
|
|
|
handleSubmit={() => ({})}
|
|
|
|
|
|
refreshData={refreshData}
|
|
|
|
|
|
getSelectedRowKeys={() => [rowId]}
|
|
|
|
|
|
getSelectedRowsData={() => [row]}
|
|
|
|
|
|
getFilter={() => null}
|
|
|
|
|
|
onActionEdit={onActionEdit}
|
|
|
|
|
|
onActionNew={onActionNew}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
2025-09-21 14:42:24 +00:00
|
|
|
|
<div className="flex-grow">
|
2025-09-21 15:11:12 +00:00
|
|
|
|
<FormDevExpress
|
|
|
|
|
|
mode="view"
|
|
|
|
|
|
refForm={refForm}
|
|
|
|
|
|
formData={formData}
|
|
|
|
|
|
formItems={formItems}
|
|
|
|
|
|
setFormData={setFormData}
|
2025-09-21 20:05:13 +00:00
|
|
|
|
listFormCode={listFormCode}
|
2025-09-21 15:11:12 +00:00
|
|
|
|
/>
|
2025-09-21 14:42:24 +00:00
|
|
|
|
</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[]>([])
|
2025-09-22 09:11:15 +00:00
|
|
|
|
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
|
|
|
|
|
|
const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])
|
|
|
|
|
|
const [layoutCount, setLayoutCount] = useState(4)
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
2025-09-21 21:32:05 +00:00
|
|
|
|
const { getLookupDataSource } = useLookupDataSource({ listFormCode })
|
|
|
|
|
|
const lookupCache = useRef<Map<string, any>>(new Map())
|
|
|
|
|
|
|
|
|
|
|
|
const getCachedLookupDataSource = useCallback(
|
|
|
|
|
|
(editorOptions: any, colData: any) => {
|
|
|
|
|
|
const key = colData?.fieldName
|
|
|
|
|
|
if (!key) return null
|
|
|
|
|
|
|
|
|
|
|
|
if (!lookupCache.current.has(key)) {
|
|
|
|
|
|
lookupCache.current.set(key, getLookupDataSource(editorOptions, colData))
|
|
|
|
|
|
}
|
|
|
|
|
|
return lookupCache.current.get(key)
|
|
|
|
|
|
},
|
2025-09-22 09:11:15 +00:00
|
|
|
|
[getLookupDataSource],
|
2025-09-21 21:32:05 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2025-09-21 14:42:24 +00:00
|
|
|
|
const onPageSizeSelect = ({ value }: Option) => {
|
|
|
|
|
|
setPageSize(value)
|
|
|
|
|
|
setCurrentPage(1)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const onPageChange = (page: number) => {
|
|
|
|
|
|
setCurrentPage(page)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-21 15:11:12 +00:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
getList({ listFormCode }).then((res: any) => setGridDto(res.data))
|
|
|
|
|
|
}, [listFormCode])
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
2025-09-21 15:11:12 +00:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (gridDto) {
|
2025-09-22 09:11:15 +00:00
|
|
|
|
const dataSource = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams)
|
|
|
|
|
|
setGridDataSource(dataSource)
|
2025-09-21 15:11:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
}, [gridDto, listFormCode, searchParams, createSelectDataSource])
|
|
|
|
|
|
|
|
|
|
|
|
const loadData = useCallback(() => {
|
2025-09-22 09:11:15 +00:00
|
|
|
|
if (!gridDataSource) return
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
|
|
|
|
|
const loadOptions = {
|
|
|
|
|
|
skip: (currentPage - 1) * pageSize,
|
|
|
|
|
|
take: pageSize,
|
|
|
|
|
|
requireTotalCount: true,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-22 09:11:15 +00:00
|
|
|
|
gridDataSource.load(loadOptions).then((res: any) => {
|
2025-09-21 14:42:24 +00:00
|
|
|
|
setData(res.data)
|
|
|
|
|
|
setTotalCount(res.totalCount || 0)
|
|
|
|
|
|
})
|
2025-09-22 09:11:15 +00:00
|
|
|
|
}, [gridDataSource, currentPage, pageSize])
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-09-22 09:11:15 +00:00
|
|
|
|
if (gridDataSource) {
|
2025-09-21 15:11:12 +00:00
|
|
|
|
loadData()
|
|
|
|
|
|
}
|
2025-09-22 09:11:15 +00:00
|
|
|
|
}, [gridDataSource, loadData])
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (!gridDto) return
|
|
|
|
|
|
|
|
|
|
|
|
const pagerOptions = gridDto.gridOptions.pagerOptionDto
|
2025-09-22 09:11:15 +00:00
|
|
|
|
const allowedSizes = pagerOptions?.allowedPageSizes
|
|
|
|
|
|
?.split(',')
|
|
|
|
|
|
.map((s) => Number(s.trim()))
|
|
|
|
|
|
.filter((n) => !isNaN(n) && n > 0) || [10, 20, 50, 100]
|
2025-09-21 14:42:24 +00:00
|
|
|
|
|
|
|
|
|
|
setPageSizeOptions(allowedSizes.map((size) => ({ value: size, label: `${size} page` })))
|
|
|
|
|
|
}, [gridDto, listFormCode, searchParams])
|
|
|
|
|
|
|
2025-09-22 09:11:15 +00:00
|
|
|
|
// Data güncellendiğinde sayfanın en üstüne kaydır
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (data.length > 0) {
|
|
|
|
|
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [data])
|
|
|
|
|
|
|
2025-09-21 14:42:24 +00:00
|
|
|
|
if (!gridDto) return null
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
2025-09-22 09:11:15 +00:00
|
|
|
|
<WidgetGroup widgetGroups={gridDto.widgets || []} />
|
|
|
|
|
|
|
|
|
|
|
|
<Container>
|
|
|
|
|
|
<div className="bg-white border border-solid border-1 dark:bg-neutral-800 dark:border-neutral-700 flex justify-end items-center">
|
|
|
|
|
|
<div className="relative py-1 px-2 flex gap-1">
|
|
|
|
|
|
<FaSearch className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm" />
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="Search..."
|
|
|
|
|
|
className="p-1 pl-6 pr-2 border border-1 outline-none text-xs text-gray-700 dark:text-gray-200 placeholder-gray-400 rounded"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
size="xs"
|
|
|
|
|
|
variant={layoutCount === 3 ? 'solid' : 'default'}
|
|
|
|
|
|
className="text-sm"
|
|
|
|
|
|
onClick={() => setLayoutCount(3)}
|
|
|
|
|
|
>
|
|
|
|
|
|
3
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
size="xs"
|
|
|
|
|
|
variant={layoutCount === 4 ? 'solid' : 'default'}
|
|
|
|
|
|
className="text-sm"
|
|
|
|
|
|
onClick={() => setLayoutCount(4)}
|
|
|
|
|
|
>
|
|
|
|
|
|
4
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
size="xs"
|
|
|
|
|
|
variant={layoutCount === 5 ? 'solid' : 'default'}
|
|
|
|
|
|
className="text-sm"
|
|
|
|
|
|
onClick={() => setLayoutCount(5)}
|
|
|
|
|
|
>
|
|
|
|
|
|
5
|
|
|
|
|
|
</Button>
|
2025-09-21 14:42:24 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-09-22 09:11:15 +00:00
|
|
|
|
<div className={`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-${layoutCount} gap-4`}>
|
|
|
|
|
|
{gridDataSource &&
|
|
|
|
|
|
data.map((row, idx) => {
|
|
|
|
|
|
const keyField = gridDto.gridOptions.keyFieldName
|
|
|
|
|
|
const rowId = row[keyField!]
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<CardItem
|
|
|
|
|
|
isSubForm={true}
|
|
|
|
|
|
key={rowId || idx}
|
|
|
|
|
|
row={row}
|
|
|
|
|
|
gridDto={gridDto}
|
|
|
|
|
|
listFormCode={listFormCode}
|
|
|
|
|
|
dataSource={gridDataSource}
|
|
|
|
|
|
refreshData={loadData}
|
|
|
|
|
|
getCachedLookupDataSource={getCachedLookupDataSource}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)
|
|
|
|
|
|
})}
|
|
|
|
|
|
</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}
|
2025-09-21 14:42:24 +00:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-09-22 09:11:15 +00:00
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{data.length === 0 && (
|
|
|
|
|
|
<Loading loading={!data.length} />
|
|
|
|
|
|
// <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>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Container>
|
2025-09-21 14:42:24 +00:00
|
|
|
|
</>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-21 15:11:12 +00:00
|
|
|
|
export default Card
|