diff --git a/apps/web/src/app/(dashboard)/agents/_components/weekly-routine-grid.tsx b/apps/web/src/app/(dashboard)/agents/_components/weekly-routine-grid.tsx index 060c2c0..5baab23 100644 --- a/apps/web/src/app/(dashboard)/agents/_components/weekly-routine-grid.tsx +++ b/apps/web/src/app/(dashboard)/agents/_components/weekly-routine-grid.tsx @@ -125,91 +125,112 @@ export const WeeklyRoutineGrid = () => { const isToday = dayIndex === today; return ( -
+ {/* Today label above card */} + {isToday ? ( +
+ + Today ·{" "} + {new Date().toLocaleDateString("en-US", { + month: "short", + day: "numeric", + })} + +
+ ) : ( +
)} - > - {/* Day header */} +
- {day} -
+ {/* Day header */} +
+ {day} +
- {/* Routine cards for this day */} -
- {routinesByDay[dayIndex]?.map((routine) => { - const colors = getColors(routine.color); + {/* Routine cards for this day */} +
+ {routinesByDay[dayIndex]?.map((routine) => { + const colors = getColors(routine.color); - return ( - - -
-

- {routine.title} -

-

- {formatTime( - routine.schedule.hour, - routine.schedule.minute, - )} -

-
-
- -
-

- {routine.title} -

- {routine.description && ( -

- {routine.description} + +

+

+ {routine.title}

- )} -
-
- Schedule - - {formatScheduleDays(routine.schedule.daysOfWeek)} - -
-
- Time - - {formatTime( - routine.schedule.hour, - routine.schedule.minute, - )} - -
-
- Priority - - {formatPriority(routine.priority)} - +

+ {formatTime( + routine.schedule.hour, + routine.schedule.minute, + )} +

+
+ + +
+

+ {routine.title} +

+ {routine.description && ( +

+ {routine.description} +

+ )} +
+
+ Schedule + + {formatScheduleDays( + routine.schedule.daysOfWeek, + )} + +
+
+ Time + + {formatTime( + routine.schedule.hour, + routine.schedule.minute, + )} + +
+
+ Priority + + {formatPriority(routine.priority)} + +
-
- - - ); - })} + + + ); + })} +
); diff --git a/packages/backend/convex/routines.ts b/packages/backend/convex/routines.ts index cac894e..8351810 100644 --- a/packages/backend/convex/routines.ts +++ b/packages/backend/convex/routines.ts @@ -116,6 +116,24 @@ export const trigger = mutation({ const now = Date.now(); + // Deduplicate: skip if an active task with the same title already exists + const existingTasks = await ctx.db + .query("tasks") + .withIndex("by_createdAt") + .collect(); + const activeStatuses = ["inbox", "assigned", "in_progress", "review"]; + const duplicate = existingTasks.find( + (t) => t.title === routine.title && activeStatuses.includes(t.status), + ); + if (duplicate) { + // Already an active task for this routine — skip creation + await ctx.db.patch(args.routineId, { + lastTriggeredAt: now, + updatedAt: now, + }); + return duplicate._id; + } + // Create task from routine template const taskId = await ctx.db.insert("tasks", { title: routine.title,