import { Notification, toast } from '@/components/ui' import { getList } from '@/services/form.service' import { useLocalization } from '@/utils/hooks/useLocalization' import { usePermission } from '@/utils/hooks/usePermission' import { Form as FormDx } from 'devextreme-react/form' import { captionize } from 'devextreme/core/utils/inflector' import CustomStore from 'devextreme/data/custom_store' import { GroupItem } from 'devextreme/ui/form' import { useEffect, useRef, useState } from 'react' import { useNavigate, useSearchParams } from 'react-router-dom' import { GridColumnData } from '../list/GridColumnData' import { addCss, addJs } from '../list/Utils' import { PermissionResults, RowMode, SimpleItemWithColData } from './types' import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models' import { getAccessDeniedPath } from '@/utils/routing' import { ROUTES_ENUM } from '@/routes/route.constant' import { useLookupDataSource } from './useLookupDataSource' import { layoutTypes } from '../admin/listForm/edit/types' import { useListFormCustomDataSource } from '../list/useListFormCustomDataSource' import { useListFormColumns } from '../list/useListFormColumns' const useGridData = (props: { mode: RowMode listFormCode: string id?: string level?: number isSubForm?: boolean onSubmitAction?: () => void }) => { const { mode, listFormCode, id, isSubForm } = props const [gridReady, setGridReady] = useState(false) const [loading, setLoading] = useState(false) const [filter, setFilter] = useState([]) const [gridDto, setGridDto] = useState() const [dataSource, setDataSource] = useState>() const [commandColumnData, setCommandColumnData] = useState() const [formDataOld, setFormDataOld] = useState() const [formData, setFormData] = useState() const [formItems, setFormItems] = useState([]) const [permissionResults, setPermissionResults] = useState() const refForm = useRef(null) const [searchParams] = useSearchParams() const navigate = useNavigate() const { translate } = useLocalization() const { checkPermission } = usePermission() const { getBandedColumns } = useListFormColumns({ gridDto, listFormCode, isSubForm, gridRef: undefined, }) const { createSelectDataSource } = useListFormCustomDataSource({} as any) const { getLookupDataSource } = useLookupDataSource({ listFormCode, isSubForm }) const fetchData = async () => { setLoading(true) try { const response: any = await dataSource?.load({ filter, skip: 0, take: 1, }) if (response?.data?.length) { setFormData(response.data[0]) setFormDataOld({ ...response.data[0] }) } else { setFormData(undefined) setFormDataOld(undefined) } } catch (error: any) { toast.push(, { placement: 'top-end', }) } finally { setLoading(false) } } const handleSubmit = async (e: any) => { e.preventDefault() if (!dataSource) { return } const validationResult = refForm.current?.instance.validate() if (!validationResult?.isValid) { return } setLoading(true) try { const formValues = { ...formData } if (mode === 'new') { const result = await dataSource.insert(formValues) if (result.data) { if (!isSubForm) { navigate(result.data) } else if (props.onSubmitAction) { props.onSubmitAction() } toast.push( {translate('::ListForms.FormBilgileriKaydedildi')} , { placement: 'top-end', }, ) } else { throw new Error(translate('::ListForms.FormBilgileriKaydedilemedi')) } } else if (mode === 'edit') { let data: any = {} if (gridDto?.gridOptions.editingOptionDto?.sendOnlyChangedFormValuesUpdate) { Object.keys(formValues).forEach((key) => { if (formValues[key] !== formDataOld[key]) { data[key] = formValues[key] } }) } else { data = { ...formValues } } if (gridDto?.gridOptions.keyFieldName) { delete data[gridDto?.gridOptions.keyFieldName] } var result = await dataSource.update(id, data) if (result.data > 0) { if (!isSubForm) { navigate( ROUTES_ENUM.protected.admin.formView .replace(':listFormCode', listFormCode) .replace(':id', id!), ) } else if (props.onSubmitAction) { props.onSubmitAction() } toast.push( {translate('::ListForms.FormBilgileriKaydedildi')} , { placement: 'top-end', }, ) } else { throw new Error(translate('::ListForms.FormBilgileriKaydedilemedi')) } } } catch (error: any) { toast.push(, { placement: 'top-end', }) } finally { setLoading(false) } } useEffect(() => { setGridReady(false) const initializeGrid = async () => { const response = await getList({ listFormCode }) setGridDto(response.data) } initializeGrid() }, [listFormCode]) useEffect(() => { setGridReady(false) if (!gridDto) { return } setPermissionResults({ 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), }) // Set js and css const grdOpt = gridDto.gridOptions grdOpt.customJsSources.forEach(addJs) grdOpt.customStyleSources.forEach(addCss) // Set columns const cols = getBandedColumns() setCommandColumnData(cols?.find((a) => a.type == 'buttons')) // Set data source const dataSource: CustomStore = createSelectDataSource( gridDto.gridOptions, listFormCode, searchParams, layoutTypes.grid, cols, ) setDataSource(dataSource) const items = gridDto?.gridOptions.editingFormDto ?.sort((a: any, b: any) => { return a.order >= b.order ? 1 : -1 }) .map((e: any) => { return { itemType: e.itemType, colCount: e.colCount, colSpan: e.colSpan, caption: e.caption, items: e.items ?.sort((a: any, b: any) => { return 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: gridDto.columnFormats.find((x: any) => x.fieldName === i.dataField)?.canRead ?? false, canUpdate: gridDto.columnFormats.find((x: any) => x.fieldName === i.dataField)?.canUpdate ?? false, canCreate: gridDto.columnFormats.find((x: any) => x.fieldName === i.dataField)?.canCreate ?? false, canExport: gridDto.columnFormats.find((x: any) => x.fieldName === i.dataField)?.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: getLookupDataSource(colData?.editorOptions, colData, formData), valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(), displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(), } : {}), }, colData, tagBoxOptions: i.tagBoxOptions, gridBoxOptions: i.gridBoxOptions, editorScript: i.editorScript, } if (i.dataField.indexOf(':') >= 0) { item.label = { text: captionize(i.dataField.split(':')[1]) } } if ((mode == 'edit' && !item.canUpdate) || (mode == 'new' && !item.canCreate)) { item.editorOptions = { ...item.editorOptions, readOnly: true, } } return item }) .filter((a: any) => { if (mode === 'view') { return a.canRead } else if (mode === 'new') { return a.canCreate || a.canRead } else if (mode === 'edit') { return a.canUpdate || a.canRead } else { return false } }), } as GroupItem }) setFormItems(items) setGridReady(true) }, [gridDto]) // formData değiştiğinde sadece lookup datasource'ları güncelle useEffect(() => { if (!gridDto || !formItems.length) { return } // View mode'da formData olsa da olmasa da cascading alanlar için dataSource oluşturulmalı const updatedItems = formItems.map((groupItem) => ({ ...groupItem, items: (groupItem.items as SimpleItemWithColData[])?.map((item) => { const colData = gridDto.columnFormats.find((x) => x.fieldName === item.dataField) if (colData?.lookupDto?.dataSourceType) { return { ...item, editorOptions: { ...item.editorOptions, // formData null bile olsa getLookupDataSource çağrılmalı (null parametrelerle API çağrısı yapılacak) dataSource: getLookupDataSource(colData?.editorOptions, colData, formData || null), valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(), displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(), }, } } return item }), })) setFormItems(updatedItems) }, [formData, gridDto]) useEffect(() => { if (!gridReady) { return } if (mode !== 'new') { setFilter([gridDto?.gridOptions.keyFieldName ?? 'Id', '=', id]) } }, [id, gridReady]) useEffect(() => { if (filter?.length) { fetchData() } }, [filter]) // Auth check useEffect(() => { if (!permissionResults) return const noCreate = mode === 'new' && !permissionResults.c const noUpdate = mode === 'edit' && !permissionResults.u const noRead = mode === 'view' && !permissionResults.r if (noCreate || noUpdate || noRead) { navigate(getAccessDeniedPath(location.pathname), { replace: true, state: { from: location } }) } }, [permissionResults]) return { loading, gridDto, dataSource, commandColumnData, filter, formItems, formData, refForm, permissionResults, fetchData, setFormData, handleSubmit, } } export { useGridData }