2026-08-06 22:54:50 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* FormView / FormEdit / FormNew ekranlarının ortak sayfa iskeleti.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Üç bileşen de aynı düzeni (Helmet + başlık + FormButtons + FormDevExpress +
|
|
|
|
|
|
* SubForms + NotePanel) satır satır kopyalıyordu. Tek noktadan yönetilir.
|
|
|
|
|
|
*/
|
|
|
|
|
|
import type { ReactNode, RefObject } from 'react'
|
|
|
|
|
|
import { useState } from 'react'
|
|
|
|
|
|
import { Container, Loading } from '@/components/shared'
|
|
|
|
|
|
import { Badge } from '@/components/ui'
|
|
|
|
|
|
import type { GridDto } from '@/proxy/form/models'
|
|
|
|
|
|
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
|
|
|
|
|
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
|
|
|
|
import { usePermission } from '@/utils/hooks/usePermission'
|
|
|
|
|
|
import type { FormRef } from 'devextreme-react/form'
|
|
|
|
|
|
import type { GroupItem } from 'devextreme/ui/form'
|
2026-08-13 08:41:48 +00:00
|
|
|
|
import PageTitle from '@/components/shared/PageTitle'
|
2026-08-06 22:54:50 +00:00
|
|
|
|
import FormDevExpress from '../FormDevExpress'
|
|
|
|
|
|
import SubForms from '../SubForms'
|
|
|
|
|
|
import { NotePanel } from '../notes/NotePanel'
|
|
|
|
|
|
import type { RowMode } from '../types'
|
|
|
|
|
|
|
|
|
|
|
|
type FormPageShellProps = {
|
|
|
|
|
|
mode: RowMode
|
|
|
|
|
|
listFormCode: string
|
|
|
|
|
|
isSubForm?: boolean
|
|
|
|
|
|
level?: number
|
|
|
|
|
|
loading: boolean
|
|
|
|
|
|
gridDto?: GridDto
|
|
|
|
|
|
formData: any
|
|
|
|
|
|
formItems: GroupItem[]
|
2026-08-13 08:41:48 +00:00
|
|
|
|
refForm: RefObject<FormRef | null>
|
2026-08-06 22:54:50 +00:00
|
|
|
|
setFormData: (data: any) => void
|
|
|
|
|
|
/** Başlığın sağındaki aksiyon butonları (FormButtons). */
|
|
|
|
|
|
actions?: ReactNode
|
|
|
|
|
|
/** Not paneli kimliği; verilmezse panel gösterilmez. */
|
|
|
|
|
|
noteEntityId?: string
|
|
|
|
|
|
/** Alt form sekmelerini yenileme geri çağrısı. */
|
|
|
|
|
|
refreshData?: () => Promise<void>
|
|
|
|
|
|
/** FormNew'de alt form gösterilmez. */
|
|
|
|
|
|
showSubForms?: boolean
|
|
|
|
|
|
/** Form gövdesinin sarmalayıcı sınıfı (FormView farklı dolgu kullanır). */
|
|
|
|
|
|
contentClassName?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const FormPageShell = ({
|
|
|
|
|
|
mode,
|
|
|
|
|
|
listFormCode,
|
|
|
|
|
|
isSubForm,
|
|
|
|
|
|
level,
|
|
|
|
|
|
loading,
|
|
|
|
|
|
gridDto,
|
|
|
|
|
|
formData,
|
|
|
|
|
|
formItems,
|
|
|
|
|
|
refForm,
|
|
|
|
|
|
setFormData,
|
|
|
|
|
|
actions,
|
|
|
|
|
|
noteEntityId,
|
|
|
|
|
|
refreshData,
|
|
|
|
|
|
showSubForms = true,
|
|
|
|
|
|
contentClassName = 'px-2',
|
|
|
|
|
|
}: FormPageShellProps) => {
|
|
|
|
|
|
const { translate } = useLocalization()
|
|
|
|
|
|
const { checkPermission } = usePermission()
|
|
|
|
|
|
const MenuIcon = useCurrentMenuIcon('w-5 h-5')
|
|
|
|
|
|
const [isNotePanelVisible, setIsNotePanelVisible] = useState(false)
|
|
|
|
|
|
|
|
|
|
|
|
const showNotePanel = Boolean(
|
|
|
|
|
|
listFormCode &&
|
|
|
|
|
|
noteEntityId &&
|
|
|
|
|
|
!isSubForm &&
|
|
|
|
|
|
gridDto?.gridOptions?.showNote &&
|
|
|
|
|
|
checkPermission(gridDto?.gridOptions.permissionDto.n),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (!listFormCode) {
|
|
|
|
|
|
return null
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
return <Loading type="default" loading />
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!formData) {
|
|
|
|
|
|
return <>{translate('::App.NoResults')}</>
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const title = translate('::' + gridDto?.gridOptions.title)
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Container
|
|
|
|
|
|
className={`${
|
|
|
|
|
|
isNotePanelVisible && !isSubForm ? 'lg:mr-[375px]' : ''
|
|
|
|
|
|
} transition-all duration-300`}
|
|
|
|
|
|
>
|
|
|
|
|
|
{!isSubForm && (
|
2026-08-13 08:41:48 +00:00
|
|
|
|
<PageTitle title={title} />
|
2026-08-06 22:54:50 +00:00
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
<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">{title}</h4>●
|
|
|
|
|
|
<Badge content={mode} />
|
|
|
|
|
|
</>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{actions}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className={contentClassName}>
|
|
|
|
|
|
<FormDevExpress
|
|
|
|
|
|
mode={mode}
|
|
|
|
|
|
refForm={refForm}
|
|
|
|
|
|
formData={formData}
|
|
|
|
|
|
formItems={formItems}
|
|
|
|
|
|
setFormData={setFormData}
|
|
|
|
|
|
listFormCode={listFormCode}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{showSubForms && gridDto && (
|
|
|
|
|
|
<SubForms
|
|
|
|
|
|
gridDto={gridDto}
|
|
|
|
|
|
formData={formData}
|
|
|
|
|
|
level={level ?? 0}
|
|
|
|
|
|
refreshData={refreshData}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Container>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Not paneli yalnızca ana formda gösterilir. */}
|
|
|
|
|
|
{showNotePanel && (
|
|
|
|
|
|
<NotePanel
|
|
|
|
|
|
entityName={listFormCode}
|
|
|
|
|
|
entityId={noteEntityId!}
|
|
|
|
|
|
isVisible={isNotePanelVisible}
|
|
|
|
|
|
onToggle={() => setIsNotePanelVisible((visible) => !visible)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|