import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models' import { captionize } from 'devextreme/core/utils/inflector' import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource' import { Button, Pagination, Select } from '@/components/ui' import classNames from 'classnames' import { FaSearch } from 'react-icons/fa' import FormDevExpress from '../form/FormDevExpress' import { GroupItem } from 'devextreme/ui/form' import { Form as FormDx } from 'devextreme-react/form' import FormButtons from '../form/FormButtons' import { Link, useNavigate } from 'react-router-dom' import { ROUTES_ENUM } from '@/routes/route.constant' import CustomStore from 'devextreme/data/custom_store' import { PermissionResults, SimpleItemWithColData } from '../form/types' import { usePermission } from '@/utils/hooks/usePermission' import { useLocalization } from '@/utils/hooks/useLocalization' import { useLookupDataSource } from '../form/useLookupDataSource' import { Container, Loading } from '@/components/shared' import WidgetGroup from '@/components/common/WidgetGroup' import { GridExtraFilterState } from './Utils' import { useStoreActions, useStoreState } from '@/store/store' const CardItem = ({ isSubForm, row, gridDto, listFormCode, dataSource, refreshData, getCachedLookupDataSource, }: { isSubForm?: boolean row: any gridDto: GridDto listFormCode: string dataSource: CustomStore refreshData: () => void getCachedLookupDataSource: (editorOptions: any, colData: any) => any }) => { const [formData, setFormData] = useState(row) const refForm = useRef(null) const navigate = useNavigate() const { checkPermission } = usePermission() const { translate } = useLocalization() const keyField = gridDto.gridOptions.keyFieldName const rowId = row[keyField!] // Form Items const formItems: GroupItem[] = useMemo(() => { if (!gridDto) return [] return gridDto.gridOptions.editingFormDto ?.sort((a, b) => (a.order >= b.order ? 1 : -1)) .map((e) => { return { itemType: e.itemType, colCount: e.colCount, colSpan: e.colSpan, caption: e.caption, items: e.items ?.sort((a, b) => (a.order >= b.order ? 1 : -1)) .map((i: EditingFormItemDto) => { let editorOptions = {} const colData = gridDto.columnFormats.find((x) => x.fieldName === i.dataField) try { editorOptions = i.editorOptions && JSON.parse(i.editorOptions) } catch {} const item: SimpleItemWithColData = { canRead: colData?.canRead ?? false, canUpdate: colData?.canUpdate ?? false, canCreate: colData?.canCreate ?? false, canExport: colData?.canExport ?? false, dataField: i.dataField, name: i.dataField, editorType2: i.editorType2, editorType: i.editorType2 == PlatformEditorTypes.dxGridBox ? 'dxDropDownBox' : i.editorType2, colSpan: i.colSpan, isRequired: i.isRequired, editorOptions: { ...editorOptions, ...(colData?.lookupDto?.dataSourceType ? { dataSource: getCachedLookupDataSource(colData?.editorOptions, colData), valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(), displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(), } : {}), }, colData, tagBoxOptions: i.tagBoxOptions, gridBoxOptions: i.gridBoxOptions, script: i.script, } if (i.dataField.indexOf(':') >= 0) { item.label = { text: captionize(i.dataField.split(':')[1]) } } item.editorOptions = { ...item.editorOptions, readOnly: true, } return item }), } as GroupItem }) }, [gridDto, getCachedLookupDataSource]) 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)) } return (
{!isSubForm &&

{translate('::' + gridDto?.gridOptions.title)}

} {permissionResults && ( ({})} refreshData={refreshData} getSelectedRowKeys={() => [rowId]} getSelectedRowsData={() => [row]} getFilter={() => null} onActionEdit={onActionEdit} onActionNew={onActionNew} /> )}
) } interface CardProps { listFormCode: string searchParams?: URLSearchParams isSubForm?: boolean level?: number refreshData?: () => Promise gridDto?: GridDto } type Option = { value: number label: string } const Card = (props: CardProps) => { const { listFormCode, searchParams, gridDto } = props const { createSelectDataSource } = useListFormCustomDataSource({}) const [data, setData] = useState([]) const [totalCount, setTotalCount] = useState(0) const [currentPage, setCurrentPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [pageSizeOptions, setPageSizeOptions] = useState([]) const [gridDataSource, setGridDataSource] = useState>() const { getLookupDataSource } = useLookupDataSource({ listFormCode }) const [layoutCount, setLayoutCount] = useState(4) const [searchText, setSearchText] = useState('') const [prevValue, setPrevValue] = useState('') const [loading, setLoading] = useState(false) const [extraFilters, setExtraFilters] = useState([]) const { states } = useStoreState((state) => state.base.lists) const { setStates } = useStoreActions((a) => a.base.lists) // props.searchParams varsa onunla başlat const [urlSearchParams, setUrlSearchParams] = useState( searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(), ) const lookupCache = useRef>(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) }, [getLookupDataSource], ) const onPageSizeSelect = ({ value }: Option) => { setPageSize(value) setCurrentPage(1) } const onPageChange = (page: number) => { setCurrentPage(page) } const onFilter = useCallback( (value?: string) => { const text = value !== undefined ? value.trim() : searchText.trim() if (!gridDto?.columnFormats) return const newParams = new URLSearchParams(urlSearchParams.toString()) if (!text) { newParams.delete('filter') setUrlSearchParams(newParams) return } const merged = gridDto.columnFormats .filter( (col) => col.dataType === 'string' && col.visible && col.width && col.allowSearch && col.width > 0, ) .map((col) => [col.fieldName, 'contains', text]) let filter: any = null if (merged.length === 1) { filter = merged[0] } else if (merged.length > 1) { filter = merged.reduce((acc, f, idx) => { if (idx === 0) return f return [acc, 'or', f] }, null as any) } if (filter) { newParams.set('filter', JSON.stringify(filter)) } else { newParams.delete('filter') } setUrlSearchParams(newParams) }, [gridDto, urlSearchParams, searchText], ) useEffect(() => { if (gridDto) { const dataSource = createSelectDataSource(gridDto.gridOptions, listFormCode, urlSearchParams) setGridDataSource(dataSource) //listFormStates const listFormStates = states.find((a) => a.listFormCode === listFormCode) if (listFormStates) { setLayoutCount(listFormStates.cardLayoutColumn || 4) } else { setLayoutCount(gridDto.gridOptions.layoutDto.cardLayoutColumn || 4) } } }, [gridDto, listFormCode, urlSearchParams, createSelectDataSource]) const loadData = useCallback(() => { if (!gridDataSource) return setLoading(true) const loadOptions = { skip: (currentPage - 1) * pageSize, take: pageSize, requireTotalCount: true, } gridDataSource .load(loadOptions) .then((res: any) => { setData(res.data) setTotalCount(res.totalCount || 0) setLoading(false) }) .catch(() => { setLoading(false) }) }, [gridDataSource, currentPage, pageSize]) useEffect(() => { if (gridDataSource) { loadData() } }, [gridDataSource, loadData]) 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) || [10, 20, 50, 100] setPageSizeOptions(allowedSizes.map((size) => ({ value: size, label: `${size} page` }))) }, [gridDto, listFormCode, searchParams]) useEffect(() => { if (data.length > 0) { window.scrollTo({ top: 0, behavior: 'smooth' }) if (data.length < 6) { setLayoutCount(data.length) } } }, [data]) if (!gridDto) return null return ( <>
setSearchText(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { onFilter(e.currentTarget.value) setPrevValue(e.currentTarget.value.trim()) // Enter ile tetiklenirse güncelle } }} onBlur={(e) => { const newValue = e.currentTarget.value.trim() // 1. Değer değişmemişse => hiçbir şey yapma if (newValue === prevValue) return // 2. Yeni değer boş, ama eskiden değer vardı => filtre temizle // 3. Yeni değer dolu ve eskisinden farklı => filtre uygula onFilter(newValue) setPrevValue(newValue) }} 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" />
{loading ? ( ) : data.length === 0 ? (

Uygun kayıt bulunamadı

Farklı filtreler deneyin veya yeni bir kayıt ekleyin.

) : (
{gridDataSource && data.map((row, idx) => { const keyField = gridDto.gridOptions.keyFieldName const rowId = row[keyField!] return ( ) })}
)} {gridDto.gridOptions.pagerOptionDto?.visible && totalCount > pageSize && (
Toplam {totalCount} kayıt