fix: rolling tasks now properly avoid overlapping existing tasks

Collision detection rewritten to check duration-based overlap instead
of exact startTime match. Rolling tasks find the next truly free slot.

v1.72.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
mARTin 2026-03-25 02:12:05 +01:00
parent e1190a8fe6
commit 39934d23bf
2 changed files with 26 additions and 17 deletions

View File

@ -1,6 +1,6 @@
{
"name": "my-weekly-todo-list",
"version": "1.72.1",
"version": "1.72.2",
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
"main": "index.js",
"scripts": {

View File

@ -4082,31 +4082,40 @@ export default function WeeklyView() {
for (const task of overdue) {
const targetSlot = task.startTime || "09:00"; // Default to 9am if no time
const taskDuration = task.duration || effectiveCellDuration;
// Collision detection
// Collision detection — checks task duration overlap, not just exact slot match
const isBlocked = (date: Date, slot: string, tasksToCheck: Task[]) => {
// Check other tasks in the updated list
const taskConflict = tasksToCheck.find(
(t) =>
t.id !== task.id &&
t.scheduledDate &&
formatDateToISO(new Date(t.scheduledDate)) ===
formatDateToISO(date) &&
t.startTime === slot,
);
const dateStr = formatDateToISO(date);
const [h, m] = slot.split(":").map(Number);
const slotStart = h * 60 + m;
const slotEnd = slotStart + taskDuration;
// Check other tasks (duration-aware overlap)
const taskConflict = tasksToCheck.some((t) => {
if (t.id === task.id || !t.startTime || t.completed) return false;
if (t.parentTaskId) return false;
const tDateStr = t.scheduledDate
? (typeof t.scheduledDate === "string" ? t.scheduledDate.substring(0, 10) : formatDateToISO(new Date(t.scheduledDate)))
: null;
if (tDateStr !== dateStr) return false;
const [th, tm] = t.startTime.split(":").map(Number);
const tStart = th * 60 + tm;
const tEnd = tStart + (t.duration || effectiveCellDuration);
return slotStart < tEnd && slotEnd > tStart;
});
if (taskConflict) return true;
// Check calendar events
const [h, m] = slot.split(":").map(Number);
const slotStart = new Date(date);
slotStart.setHours(h, m, 0, 0);
const slotEnd = new Date(slotStart);
slotEnd.setMinutes(slotEnd.getMinutes() + effectiveCellDuration);
const slotStartDate = new Date(date);
slotStartDate.setHours(h, m, 0, 0);
const slotEndDate = new Date(slotStartDate);
slotEndDate.setMinutes(slotEndDate.getMinutes() + taskDuration);
return dailyEvents.some((event) => {
const eventStart = new Date(event.startTime);
const eventEnd = new Date(event.endTime);
return slotStart < eventEnd && slotEnd > eventStart;
return slotStartDate < eventEnd && slotEndDate > eventStart;
});
};