59 lines
1.6 KiB
TypeScript
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];
|
|
}
|