sozsoft-platform/ui/src/views/form/FormNew.tsx
2026-10-06 10:19:26 +03:00

215 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Loading } from '@/components/shared'
import { lazy, useEffect, useMemo, useRef, useState } from 'react'
import { useParams, useSearchParams } from 'react-router-dom'
import type { DataType } from 'devextreme/common'
import type { SimpleItem } from 'devextreme/ui/form'
import FormButtons from './FormButtons'
import { FormProps } from './types'
import { useGridData } from './useFormData'
import { getList } from '@/services/form.service'
import { applyNewRowDefaults, castValueByDataType } from '../list/shared/editingForm'
import { FormPageShell } from './shared/FormPageShell'
const FormView = lazy(() => import('./FormView'))
export const FormNewContent = (props: FormProps = { isSubForm: false }) => {
const mode = 'new'
const { isSubForm, level, sParams, onActionView } = props
const params = useParams()
const listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
const [searchParams] = useSearchParams()
const initializedListFormCodeRef = useRef<string | undefined>(undefined)
const {
setFormData,
loading,
handleSubmit,
gridDto,
dataSource,
commandColumnData,
formData,
formItems,
refForm,
permissionResults,
fieldOrder,
previewFieldOrder,
saveFieldOrder,
canStoreFieldOrder,
} = useGridData({
mode,
listFormCode,
level,
isSubForm,
onSubmitAction: onActionView,
})
// URL parametreleri + üst formdan gelen parametreler.
const newParams = useMemo(
() =>
new URLSearchParams({
...Object.fromEntries(searchParams),
...Object.fromEntries(sParams ?? []),
}),
[searchParams, sParams],
)
useEffect(() => {
initializedListFormCodeRef.current = undefined
}, [listFormCode])
/** Form ilk açıldığında varsayılan değerleri kurar. */
useEffect(() => {
if (!formItems?.length || !gridDto?.columnFormats) return
if (initializedListFormCodeRef.current === listFormCode) return
initializedListFormCodeRef.current = listFormCode
let isActive = true
// Tanımlı tüm alanlar önce boşaltılır, ardından kolon varsayılanları uygulanır.
const initialData: Record<string, any> = {}
formItems.forEach((group) =>
(group.items as SimpleItem[] | undefined)?.forEach((item) => {
if (item.dataField) initialData[item.dataField] = undefined
}),
)
applyNewRowDefaults(gridDto, initialData).then((data) => {
if (isActive) setFormData(data)
})
return () => {
isActive = false
}
}, [listFormCode, formItems?.length, gridDto?.columnFormats])
/** URL parametrelerinden gelen alanları forma yazar. */
useEffect(() => {
if (!formItems?.length || !formData || !gridDto?.columnFormats) return
const updatedData = { ...formData }
let hasChanges = false
for (const colFormat of gridDto.columnFormats) {
const fieldName = colFormat.fieldName
if (!fieldName || !newParams.has(fieldName)) continue
const nextValue = castValueByDataType(
newParams.get(fieldName),
colFormat.dataType as DataType,
)
if (updatedData[fieldName] !== nextValue) {
updatedData[fieldName] = nextValue
hasChanges = true
}
}
if (hasChanges) setFormData(updatedData)
}, [newParams, formData, gridDto?.columnFormats])
/** URL'den gelen alanlar kullanıcı tarafından değiştirilemez. */
useEffect(() => {
if (!formItems?.length || !gridDto?.columnFormats) return
const lockedFields = new Set(
gridDto.columnFormats
.map((colFormat) => colFormat.fieldName)
.filter((fieldName): fieldName is string => !!fieldName && newParams.has(fieldName)),
)
if (!lockedFields.size) return
formItems.forEach((group) =>
(group.items as SimpleItem[] | undefined)?.forEach((item) => {
if (item.dataField && lockedFields.has(item.dataField)) {
item.editorOptions = { ...item.editorOptions, readOnly: true }
}
}),
)
}, [formItems, newParams, gridDto?.columnFormats])
return (
<FormPageShell
mode={mode}
listFormCode={listFormCode}
isSubForm={isSubForm}
level={level}
loading={loading}
gridDto={gridDto}
formData={formData}
formItems={formItems}
refForm={refForm}
setFormData={setFormData}
showSubForms={false}
actions={
permissionResults && (
<FormButtons
fieldOrder={
canStoreFieldOrder
? { value: fieldOrder, preview: previewFieldOrder, save: saveFieldOrder }
: undefined
}
isSubForm={isSubForm}
mode={mode}
listFormCode={listFormCode}
id={formData?.Id}
gridDto={gridDto!}
commandColumnData={commandColumnData!}
dataSource={dataSource!}
permissions={permissionResults}
handleSubmit={handleSubmit}
refreshData={() => {}}
getSelectedRowKeys={() => []}
getSelectedRowsData={() => [formData]}
getFilter={() => []}
onActionView={onActionView}
/>
)
}
/>
)
}
/**
* `listFormType === 'Form'` olan liste formlarında "yeni kayıt" ekranı yerine
* doğrudan görüntüleme ekranı açılır (tekil kayıtlı formlar).
*/
const FormNew = (props: FormProps = { isSubForm: false }) => {
const params = useParams()
const listFormCode = props.listFormCode ?? params.listFormCode ?? ''
const [listFormType, setListFormType] = useState<string>()
const [loading, setLoading] = useState(true)
useEffect(() => {
if (!listFormCode || props.isSubForm) {
setLoading(false)
return
}
let isActive = true
setLoading(true)
getList({ listFormCode })
.then((response: any) => {
if (isActive) setListFormType(response?.data?.gridOptions?.listFormType)
})
.catch((error: unknown) => console.error('ListForm tipi alınamadı:', error))
.finally(() => {
if (isActive) setLoading(false)
})
return () => {
isActive = false
}
}, [listFormCode, props.isSubForm])
if (loading) {
return <Loading loading type="default" />
}
if (!props.isSubForm && listFormType === 'Form') {
return <FormView {...props} listFormCode={listFormCode} />
}
return <FormNewContent {...props} listFormCode={listFormCode} />
}
export default FormNew