feat: 타임라인 스케줄러 컴포넌트 리소스 처리 개선
- 리소스가 없을 경우 스케줄의 resourceId를 기반으로 자동으로 리소스를 생성하는 기능을 추가하였습니다. - 리소스별 스케줄 그룹화를 위해 effectiveResources를 도입하여 코드의 가독성을 향상시켰습니다. - 스케줄 데이터가 없을 경우 사용자에게 적절한 메시지를 표시하도록 수정하였습니다. - useTimelineData 훅에서 불필요한 검색 조건을 제거하여 성능을 개선하였습니다.
This commit is contained in:
parent
4447911892
commit
4e7aa0c3b9
|
|
@ -85,11 +85,31 @@ export function TimelineSchedulerComponent({
|
|||
const cellWidthConfig = config.cellWidth || defaultTimelineSchedulerConfig.cellWidth!;
|
||||
const cellWidth = cellWidthConfig[zoomLevel] || 60;
|
||||
|
||||
// 리소스가 없으면 스케줄의 resourceId로 자동 생성
|
||||
const effectiveResources = useMemo(() => {
|
||||
if (resources.length > 0) {
|
||||
return resources;
|
||||
}
|
||||
|
||||
// 스케줄에서 고유한 resourceId 추출하여 자동 리소스 생성
|
||||
const uniqueResourceIds = new Set<string>();
|
||||
schedules.forEach((schedule) => {
|
||||
if (schedule.resourceId) {
|
||||
uniqueResourceIds.add(schedule.resourceId);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(uniqueResourceIds).map((id) => ({
|
||||
id,
|
||||
name: id, // resourceId를 이름으로 사용
|
||||
}));
|
||||
}, [resources, schedules]);
|
||||
|
||||
// 리소스별 스케줄 그룹화
|
||||
const schedulesByResource = useMemo(() => {
|
||||
const grouped = new Map<string, ScheduleItem[]>();
|
||||
|
||||
resources.forEach((resource) => {
|
||||
effectiveResources.forEach((resource) => {
|
||||
grouped.set(resource.id, []);
|
||||
});
|
||||
|
||||
|
|
@ -99,7 +119,7 @@ export function TimelineSchedulerComponent({
|
|||
list.push(schedule);
|
||||
} else {
|
||||
// 리소스가 없는 스케줄은 첫 번째 리소스에 할당
|
||||
const firstResource = resources[0];
|
||||
const firstResource = effectiveResources[0];
|
||||
if (firstResource) {
|
||||
const firstList = grouped.get(firstResource.id);
|
||||
if (firstList) {
|
||||
|
|
@ -110,7 +130,7 @@ export function TimelineSchedulerComponent({
|
|||
});
|
||||
|
||||
return grouped;
|
||||
}, [schedules, resources]);
|
||||
}, [schedules, effectiveResources]);
|
||||
|
||||
// 줌 레벨 변경
|
||||
const handleZoomIn = useCallback(() => {
|
||||
|
|
@ -132,12 +152,12 @@ export function TimelineSchedulerComponent({
|
|||
// 스케줄 클릭 핸들러
|
||||
const handleScheduleClick = useCallback(
|
||||
(schedule: ScheduleItem) => {
|
||||
const resource = resources.find((r) => r.id === schedule.resourceId);
|
||||
const resource = effectiveResources.find((r) => r.id === schedule.resourceId);
|
||||
if (resource && onScheduleClick) {
|
||||
onScheduleClick({ schedule, resource });
|
||||
}
|
||||
},
|
||||
[resources, onScheduleClick]
|
||||
[effectiveResources, onScheduleClick]
|
||||
);
|
||||
|
||||
// 빈 셀 클릭 핸들러
|
||||
|
|
@ -195,13 +215,13 @@ export function TimelineSchedulerComponent({
|
|||
|
||||
// 추가 버튼 클릭
|
||||
const handleAddClick = useCallback(() => {
|
||||
if (onAddSchedule && resources.length > 0) {
|
||||
if (onAddSchedule && effectiveResources.length > 0) {
|
||||
onAddSchedule(
|
||||
resources[0].id,
|
||||
effectiveResources[0].id,
|
||||
new Date().toISOString().split("T")[0]
|
||||
);
|
||||
}
|
||||
}, [onAddSchedule, resources]);
|
||||
}, [onAddSchedule, effectiveResources]);
|
||||
|
||||
// 디자인 모드 플레이스홀더
|
||||
if (isDesignMode) {
|
||||
|
|
@ -250,8 +270,8 @@ export function TimelineSchedulerComponent({
|
|||
);
|
||||
}
|
||||
|
||||
// 리소스 없음
|
||||
if (resources.length === 0) {
|
||||
// 리소스 없음 (스케줄도 없는 경우에만 표시)
|
||||
if (effectiveResources.length === 0) {
|
||||
return (
|
||||
<div
|
||||
className="w-full flex items-center justify-center bg-muted/10 rounded-lg"
|
||||
|
|
@ -259,8 +279,8 @@ export function TimelineSchedulerComponent({
|
|||
>
|
||||
<div className="text-center text-muted-foreground">
|
||||
<Calendar className="h-8 w-8 mx-auto mb-2" />
|
||||
<p className="text-sm font-medium">리소스가 없습니다</p>
|
||||
<p className="text-xs mt-1">리소스 테이블을 설정하세요</p>
|
||||
<p className="text-sm font-medium">스케줄 데이터가 없습니다</p>
|
||||
<p className="text-xs mt-1">스케줄 테이블에 데이터를 추가하세요</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -385,7 +405,7 @@ export function TimelineSchedulerComponent({
|
|||
|
||||
{/* 리소스 행들 */}
|
||||
<div>
|
||||
{resources.map((resource) => (
|
||||
{effectiveResources.map((resource) => (
|
||||
<ResourceRow
|
||||
key={resource.id}
|
||||
resource={resource}
|
||||
|
|
|
|||
|
|
@ -94,17 +94,6 @@ export function useTimelineData(
|
|||
page: 1,
|
||||
size: 10000,
|
||||
autoFilter: true,
|
||||
search: {
|
||||
// 표시 범위 내의 스케줄만 조회
|
||||
[fieldMapping.startDate]: {
|
||||
value: toDateString(viewEndDate),
|
||||
operator: "lte",
|
||||
},
|
||||
[fieldMapping.endDate]: {
|
||||
value: toDateString(viewStartDate),
|
||||
operator: "gte",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue