ERP-node/frontend/lib/registry/components/v2-timeline-scheduler/utils/conflictDetection.ts

59 lines
1.6 KiB
TypeScript

"use client";
import { ScheduleItem } from "../types";
/**
* 같은 리소스에서 시간이 겹치는 스케줄을 감지
* @returns 충돌이 있는 스케줄 ID Set
*/
export function detectConflicts(schedules: ScheduleItem[]): Set<string> {
const conflictIds = new Set<string>();
// 리소스별로 그룹화
const byResource = new Map<string, ScheduleItem[]>();
for (const schedule of schedules) {
if (!byResource.has(schedule.resourceId)) {
byResource.set(schedule.resourceId, []);
}
byResource.get(schedule.resourceId)!.push(schedule);
}
// 리소스별 충돌 검사
for (const [, resourceSchedules] of byResource) {
if (resourceSchedules.length < 2) continue;
// 시작일 기준 정렬
const sorted = [...resourceSchedules].sort(
(a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime()
);
for (let i = 0; i < sorted.length; i++) {
const aEnd = new Date(sorted[i].endDate).getTime();
for (let j = i + 1; j < sorted.length; j++) {
const bStart = new Date(sorted[j].startDate).getTime();
// 정렬되어 있으므로 aStart <= bStart
// 겹치는 조건: aEnd > bStart
if (aEnd > bStart) {
conflictIds.add(sorted[i].id);
conflictIds.add(sorted[j].id);
} else {
break;
}
}
}
}
return conflictIds;
}
/**
* 날짜를 일수만큼 이동
*/
export function addDaysToDateString(dateStr: string, days: number): string {
const date = new Date(dateStr);
date.setDate(date.getDate() + days);
return date.toISOString().split("T")[0];
}