sozsoft-platform/ui/src/views/form/FormNew.tsx
2026-07-14 23:25:04 +03:00

346 lines
9.2 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 { Container, Loading } from '@/components/shared'
import { useLocalization } from '@/utils/hooks/useLocalization'
import type { DataType } from 'devextreme/common'
import type { SimpleItem } from 'devextreme/ui/form'
import { lazy, useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import { useParams, useSearchParams } from 'react-router-dom'
import FormButtons from './FormButtons'
import FormDevExpress from './FormDevExpress'
import { FormProps } from './types'
import { useGridData } from './useFormData'
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
import { Badge } from '@/components/ui'
import { APP_NAME } from '@/constants/app.constant'
import { FieldCustomValueTypeEnum } from '@/proxy/form/models'
import { getList, getNextSequenceValue } from '@/services/form.service'
import { autoNumber } from '../list/Utils'
const FormView = lazy(() => import('./FormView'))
export const FormNewContent = (
props: FormProps = {
isSubForm: false,
},
) => {
const mode = 'new'
const { isSubForm, level, sParams } = props
const params = useParams()
const listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
const [searchParams] = useSearchParams()
const { translate } = useLocalization()
const MenuIcon = useCurrentMenuIcon('w-5 h-5')
const initializedListFormCodeRef = useRef<string>()
const {
setFormData,
loading,
handleSubmit,
gridDto,
dataSource,
commandColumnData,
formData,
formItems,
refForm,
permissionResults,
} = useGridData({
mode,
listFormCode,
level,
isSubForm,
onSubmitAction: (props?.onActionView),
})
const [newParams, setNewParams] = useState<URLSearchParams>(new URLSearchParams())
useEffect(() => {
setNewParams(
new URLSearchParams({
...Object.fromEntries(searchParams),
...Object.fromEntries(sParams ?? []),
}),
)
}, [searchParams, sParams])
useEffect(() => {
initializedListFormCodeRef.current = undefined
}, [listFormCode])
useEffect(() => {
if (!formItems?.length || !gridDto?.columnFormats) {
return
}
if (initializedListFormCodeRef.current === listFormCode) {
return
}
initializedListFormCodeRef.current = listFormCode
let isActive = true
const initializeFormData = async () => {
const initialFormData = await createInitialFormData()
if (isActive) {
setFormData(initialFormData)
}
}
initializeFormData()
return () => {
isActive = false
}
}, [listFormCode, formItems?.length, gridDto?.columnFormats])
// newParams değiştiğinde sadece newParams'tan gelen alanları güncelle
useEffect(() => {
if (!formItems || !formData || !gridDto?.columnFormats) {
return
}
const updatedData = { ...formData }
let hasChanges = false
for (const colFormat of gridDto.columnFormats) {
if (!colFormat.fieldName || !newParams.has(colFormat.fieldName)) {
continue
}
const dType = colFormat.dataType as DataType
let newValue: any
switch (dType) {
case 'date':
case 'datetime':
newValue = new Date(newParams.get(colFormat.fieldName)!)
break
case 'number':
newValue = Number(newParams.get(colFormat.fieldName))
break
case 'boolean':
if (newParams.get(colFormat.fieldName) === 'true') {
newValue = true
} else if (newParams.get(colFormat.fieldName) === 'false') {
newValue = false
}
break
case 'object':
try {
newValue = JSON.parse(newParams.get(colFormat.fieldName) as string)
} catch {
newValue = updatedData[colFormat.fieldName]
}
break
default:
newValue = newParams.get(colFormat.fieldName)
break
}
if (updatedData[colFormat.fieldName] !== newValue) {
updatedData[colFormat.fieldName] = newValue
hasChanges = true
}
}
if (hasChanges) {
setFormData(updatedData)
}
}, [newParams, gridDto?.columnFormats])
// newParams'tan gelen alanları readonly yap
useEffect(() => {
if (!formItems || !gridDto?.columnFormats || !newParams) {
return
}
for (const colFormat of gridDto.columnFormats) {
if (!colFormat.fieldName || !newParams.has(colFormat.fieldName)) {
continue
}
// Eğer URL'den değer geliyorsa, bu editörü readonly yapıyoruz
formItems.forEach((form) => {
form?.items?.forEach((item: SimpleItem) => {
if (item.dataField === colFormat.fieldName) {
item.editorOptions = { ...item.editorOptions, readOnly: true }
}
})
})
}
}, [formItems, newParams, gridDto?.columnFormats])
async function createInitialFormData() {
const data: any = {}
if (!formItems?.length) {
return data
}
// Default tüm alanlar undefined olsun
for (const formGroupItem of formItems) {
if (formGroupItem.items) {
//SimpleItem
for (const formItem of formGroupItem.items) {
const f = formItem as SimpleItem
data[f.dataField!] = undefined
}
}
}
if (!gridDto?.columnFormats) {
return data
}
// Grid'den gelen columnFormat'ları kullanarak default değerleri set et
for (const colFormat of gridDto?.columnFormats || []) {
if (!colFormat.fieldName) {
continue
}
if (colFormat.defaultValue !== null && colFormat.defaultValue !== undefined) {
if (
typeof colFormat.defaultValue === 'string' &&
colFormat.defaultValue === '@AUTONUMBER'
) {
data[colFormat.fieldName] = autoNumber()
continue
}
if (colFormat.defaultValueType === FieldCustomValueTypeEnum.Sequence) {
try {
const response = await getNextSequenceValue(String(colFormat.defaultValue))
data[colFormat.fieldName] = response.data
} catch (error) {
console.error('Sequence default value alınamadı:', {
fieldName: colFormat.fieldName,
defaultValue: colFormat.defaultValue,
error,
})
}
continue
}
data[colFormat.fieldName] = colFormat.defaultValue
}
}
return data
}
if (!listFormCode) {
return <></>
}
if (loading) {
return <Loading type="default" loading={loading}></Loading>
}
if (!formData) {
return <>{translate('::App.NoResults')}</>
}
return (
<Container>
{!isSubForm && (
<Helmet
titleTemplate={`%s | ${APP_NAME}`}
title={translate('::' + gridDto?.gridOptions.title)}
defaultTitle={APP_NAME}
></Helmet>
)}
<div
className={`flex items-center pb-2 px-2 ${isSubForm ? 'justify-end' : 'justify-between'}`}
>
<div className="flex items-center gap-2">
{MenuIcon}
{!isSubForm && (
<>
<h4 className="text-slate-700 text-sm font-medium leading-none">
{translate('::' + gridDto?.gridOptions?.title)}
</h4>
<Badge content={mode} />
</>
)}
</div>
{permissionResults && (
<FormButtons
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={props?.onActionView}
/>
)}
</div>
<div className="px-2">
<FormDevExpress
mode={mode}
refForm={refForm}
formData={formData}
formItems={formItems}
setFormData={setFormData}
listFormCode={listFormCode}
/>
</div>
</Container>
)
}
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(() => {
let isActive = true
const resolveFormType = async () => {
setLoading(true)
try {
const response = await getList({ listFormCode })
if (isActive) {
setListFormType(response?.data?.gridOptions?.listFormType)
}
} finally {
if (isActive) {
setLoading(false)
}
}
}
if (listFormCode && !props.isSubForm) {
resolveFormType()
} else {
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