erp-platform/ui/src/views/list/SchedulerView.tsx

263 lines
9.3 KiB
TypeScript
Raw Normal View History

2025-12-02 18:15:09 +00:00
import Container from '@/components/shared/Container'
import { DX_CLASSNAMES } from '@/constants/app.constant'
import { GridDto } from '@/proxy/form/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
import Scheduler, { Editing, Resource, SchedulerRef, View } from 'devextreme-react/scheduler'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import { getList } from '@/services/form.service'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { addCss, addJs } from './Utils'
import { layoutTypes } from '../admin/listForm/edit/types'
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { usePWA } from '@/utils/hooks/usePWA'
import CustomStore from 'devextreme/data/custom_store'
import { Loading } from '@/components/shared'
interface SchedulerViewProps {
listFormCode: string
searchParams?: URLSearchParams
isSubForm?: boolean
level?: number
refreshData?: () => Promise<void>
gridDto?: GridDto
}
const SchedulerView = (props: SchedulerViewProps) => {
const { listFormCode, searchParams, isSubForm, level, gridDto: extGridDto } = props
const { translate } = useLocalization()
const isPwaMode = usePWA()
const schedulerRef = useRef<SchedulerRef>()
const refListFormCode = useRef('')
const widgetGroupRef = useRef<HTMLDivElement>(null)
const [schedulerDataSource, setSchedulerDataSource] = useState<CustomStore<any, any>>()
const [gridDto, setGridDto] = useState<GridDto>()
const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
const [currentView, setCurrentView] = useState<string>('week')
const layout = layoutTypes.scheduler || 'scheduler'
useEffect(() => {
const initializeScheduler = async () => {
const response = await getList({ listFormCode })
setGridDto(response.data)
}
if (extGridDto === undefined) {
initializeScheduler()
} else {
setGridDto(extGridDto)
}
setCurrentView(extGridDto?.gridOptions.schedulerOptionDto?.defaultView || 'week')
}, [listFormCode, extGridDto])
useEffect(() => {
if (schedulerRef?.current) {
const instance = schedulerRef?.current?.instance()
if (instance) {
instance.option('dataSource', undefined)
}
}
if (refListFormCode.current !== listFormCode) {
// Reset state if needed
}
}, [listFormCode])
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef: schedulerRef })
useEffect(() => {
if (!gridDto) {
return
}
// Set js and css
const grdOpt = gridDto.gridOptions
if (grdOpt.customJsSources.length) {
for (const js of grdOpt.customJsSources) {
addJs(js)
}
}
if (grdOpt.customStyleSources.length) {
for (const css of grdOpt.customStyleSources) {
addCss(css)
}
}
}, [gridDto])
useEffect(() => {
if (!gridDto) return
const dataSource = createSelectDataSource(
gridDto.gridOptions,
listFormCode,
searchParams,
layout,
undefined,
)
setSchedulerDataSource(dataSource)
}, [gridDto, searchParams, createSelectDataSource])
useEffect(() => {
refListFormCode.current = listFormCode
}, [listFormCode])
// WidgetGroup yüksekliğini hesapla
useEffect(() => {
const calculateWidgetHeight = () => {
if (widgetGroupRef.current) {
const height = widgetGroupRef.current.offsetHeight
setWidgetGroupHeight(height)
}
}
calculateWidgetHeight()
const resizeObserver = new ResizeObserver(calculateWidgetHeight)
if (widgetGroupRef.current) {
resizeObserver.observe(widgetGroupRef.current)
}
return () => {
resizeObserver.disconnect()
}
}, [gridDto?.widgets])
const settingButtonClick = useCallback(() => {
window.open(
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(':listFormCode', listFormCode),
isPwaMode ? '_self' : '_blank',
)
}, [listFormCode, isPwaMode])
const onCurrentViewChange = useCallback((value: string) => {
setCurrentView(value)
}, [])
const onAppointmentFormOpening = useCallback((e: any) => {
// Özelleştirme yapılabilir
}, [])
return (
<>
<div ref={widgetGroupRef}>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
</div>
<Container className={DX_CLASSNAMES}>
{!isSubForm && (
<Helmet
titleTemplate="%s | Erp Platform"
title={translate('::' + gridDto?.gridOptions.title)}
defaultTitle="Erp Platform"
>
</Helmet>
)}
{!gridDto && (
<div className="p-4">
<Loading loading>Loading scheduler configuration...</Loading>
</div>
)}
{gridDto && !schedulerDataSource && (
<div className="p-4">
<Loading loading>Loading data source...</Loading>
</div>
)}
{gridDto && schedulerDataSource && (
<>
<div className="p-1">
<Scheduler
ref={schedulerRef as any}
key={`Scheduler-${listFormCode}-${schedulerDataSource ? 'loaded' : 'loading'}`}
id={'Scheduler-' + listFormCode}
dataSource={schedulerDataSource}
textExpr={gridDto.gridOptions.schedulerOptionDto?.textExpr || 'text'}
startDateExpr={gridDto.gridOptions.schedulerOptionDto?.startDateExpr || 'startDate'}
endDateExpr={gridDto.gridOptions.schedulerOptionDto?.endDateExpr || 'endDate'}
allDayExpr={gridDto.gridOptions.schedulerOptionDto?.allDayExpr}
recurrenceRuleExpr={gridDto.gridOptions.schedulerOptionDto?.recurrenceRuleExpr}
recurrenceExceptionExpr={
gridDto.gridOptions.schedulerOptionDto?.recurrenceExceptionExpr
}
startDayHour={gridDto.gridOptions.schedulerOptionDto?.startDayHour || 8}
endDayHour={gridDto.gridOptions.schedulerOptionDto?.endDayHour || 18}
currentView={currentView}
onCurrentViewChange={onCurrentViewChange}
onAppointmentFormOpening={onAppointmentFormOpening}
height={
gridDto.gridOptions.height > 0
? gridDto.gridOptions.height
: gridDto.gridOptions.fullHeight
? `calc(100vh - ${170 + widgetGroupHeight}px)`
: undefined
}
showAllDayPanel={gridDto.gridOptions.schedulerOptionDto?.showAllDayPanel ?? true}
crossScrollingEnabled={
gridDto.gridOptions.schedulerOptionDto?.crossScrollingEnabled ?? false
}
cellDuration={gridDto.gridOptions.schedulerOptionDto?.cellDuration || 30}
firstDayOfWeek={
(gridDto.gridOptions.schedulerOptionDto?.firstDayOfWeek as
| 0
| 1
| 2
| 3
| 4
| 5
| 6) || 1
}
adaptivityEnabled={true}
>
<Editing
allowAdding={gridDto.gridOptions.editingOptionDto?.allowAdding ?? false}
allowUpdating={gridDto.gridOptions.editingOptionDto?.allowUpdating ?? false}
allowDeleting={gridDto.gridOptions.editingOptionDto?.allowDeleting ?? false}
allowResizing={gridDto.gridOptions.schedulerOptionDto?.allowResizing ?? false}
allowDragging={gridDto.gridOptions.schedulerOptionDto?.allowDragging ?? false}
/>
2025-12-02 19:58:31 +00:00
<View type="day" name={translate('::ListForms.SchedulerOptions.Day')} />
<View type="week" name={translate('::ListForms.SchedulerOptions.Week')} />
<View type="workWeek" name={translate('::ListForms.SchedulerOptions.WorkWeek')} />
<View type="month" name={translate('::ListForms.SchedulerOptions.Month')} />
2025-12-02 18:15:09 +00:00
<View
type="timelineDay"
2025-12-02 19:58:31 +00:00
name={translate('::ListForms.SchedulerOptions.TimelineDay')}
2025-12-02 18:15:09 +00:00
maxAppointmentsPerCell="unlimited"
/>
<View
type="timelineWeek"
2025-12-02 19:58:31 +00:00
name={translate('::ListForms.SchedulerOptions.TimelineWeek')}
2025-12-02 18:15:09 +00:00
maxAppointmentsPerCell="unlimited"
/>
<View
type="timelineMonth"
2025-12-02 19:58:31 +00:00
name={translate('::ListForms.SchedulerOptions.TimelineMonth')}
2025-12-02 18:15:09 +00:00
maxAppointmentsPerCell="unlimited"
/>
2025-12-02 19:58:31 +00:00
<View type="agenda" name={translate('::ListForms.SchedulerOptions.Agenda')} />
2025-12-02 18:15:09 +00:00
{gridDto.gridOptions.schedulerOptionDto?.resources?.map((resource, index) => (
<Resource
key={index}
fieldExpr={resource.fieldExpr}
dataSource={resource.dataSource}
label={resource.label}
useColorAsDefault={resource.useColorAsDefault}
/>
))}
</Scheduler>
</div>
</>
)}
</Container>
</>
)
}
export default SchedulerView