346 lines
9.2 KiB
TypeScript
346 lines
9.2 KiB
TypeScript
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
|