sozsoft-platform/ui/src/views/form/shared/FormPageShell.tsx
2026-08-13 11:41:48 +03:00

148 lines
4.1 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.

/**
* 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'
import PageTitle from '@/components/shared/PageTitle'
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[]
refForm: RefObject<FormRef | null>
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 && (
<PageTitle title={title} />
)}
<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)}
/>
)}
</>
)
}