Uh oh!
There was an error while loading. Please reload this page.
feat(scheduled-tasks): pause/resume, mutation toasts, submit guards, empty state - #5044
Conversation
…empty state - Toasts on every job mutation (create/update/delete/exclude/pause/resume) so failures are never silent - TaskModal stays open until the save persists; submit disabled in-flight to block double-submit - Pause/Resume recurring tasks via the context menu; paused occurrences render dimmed so they stay resumable - First-run empty state with a create CTA when the workspace has no tasks
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview The create/edit modal now awaits async saves: it stays open on failure, blocks dismiss and double-submit while in flight, and shows in-progress labels on the primary action. Create/update mutations use Schedule mutations surface success and error toasts (create, update, delete, exclude occurrence, pause, resume). General settings aligns Theme, Timezone, and Snap-to-grid dropdown triggers to a shared 240px width. Reviewed by Cursor Bugbot for commit a7624ee. Configure here. |
Uh oh!
There was an error while loading. Please reload this page.
…its persistence The edit TaskModal's onSubmit called updateTask without returning its promise, so the await resolved immediately — the modal closed before the save finished, failed edits didn't stay open, and a rejected mutateAsync went unhandled. Return the promise so the await tracks the real mutation (matching the create path).
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit ac2b846. Configure here.
Greptile SummaryThis PR adds a control and observability layer to the scheduled-tasks module: mutation toasts on every job operation (create/update/delete/pause/resume/exclude), a submit guard that keeps the modal open on failure, pause/resume of recurring tasks via the context menu, and dimmed rendering for paused calendar occurrences.
Confidence Score: 5/5The PR is safe to merge — all mutation paths now surface errors via toast and the modal correctly guards against premature close and double-submit. The submit guard uses a well-reasoned stale-closure pattern that correctly allows programmatic success-close to pass through while blocking all user-initiated dismissals during flight. The mutateAsync to onError to catch chain produces exactly one toast on failure and leaves the modal open with the draft intact. The pause/resume feature is correctly gated to recurring pending tasks only, and paused occurrences continue to expand in the calendar with a disabled flag. The schedule-events logic change is covered by three new unit tests. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant TM as TaskModal
participant HS as handleSubmit
participant HK as useScheduledTasks
participant SQ as schedules.ts
participant API as API
U->>TM: Click Schedule or Save
TM->>HS: handleSubmit()
HS->>HK: createTask or updateTask
HK->>SQ: mutateAsync
SQ->>API: HTTP request
alt Success
API-->>SQ: 200 OK
SQ->>SQ: onSuccess toast.success
SQ-->>HS: resolves
HS->>TM: close via stale closure
TM-->>U: Modal closes
else Failure
API-->>SQ: Error
SQ->>SQ: onError toast.error
SQ-->>HS: catch returns false
HS-->>TM: stays open
TM-->>U: Modal open with toast
end
Reviews (10): Last reviewed commit: "fix(scheduled-tasks): gate submit on a s..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Greptile SummaryThis PR adds a control layer to the scheduled-tasks module: toast feedback on every job mutation, an async submit guard in the create/edit modal (stays open until the task persists, closes only on success), Pause/Resume for recurring tasks via the existing
Confidence Score: 4/5The change is well-scoped and the core Pause/Resume and toast wiring is correct; the only rough edge is the missing The submit guard is the riskiest new surface:
Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant TM as TaskModal
participant UST as useScheduledTasks
participant SQ as schedules.ts (React Query)
participant API as API
U->>TM: clicks Schedule / Save
TM->>TM: setSubmitting(true)
TM->>UST: onSubmit(draft) → createTask / updateTask
UST->>SQ: mutateAsync(body)
SQ->>API: POST /schedules or PATCH /schedules/:id
API-->>SQ: 200 OK
SQ->>SQ: onSuccess → toast.success(...)
SQ-->>UST: Promise resolves
UST-->>TM: Promise resolves
TM->>TM: close() → onOpenChange(false)
Note right of TM: setSubmitting(false) never called on success path
alt API error
API-->>SQ: 4xx / 5xx
SQ->>SQ: onError → toast.error(...)
SQ-->>UST: Promise rejects
UST-->>TM: throws
TM->>TM: catch → setSubmitting(false)
Note right of TM: Modal stays open with draft intact
end
U->>TM: right-clicks task chip
TM->>UST: pauseTask(scheduleId) / resumeTask(scheduleId)
UST->>SQ: disableSchedule.mutate / resumeSchedule.mutate
UST->>UST: setSelectedTask(null) immediately
SQ->>API: PATCH /schedules/:id (disable/reactivate)
API-->>SQ: 200 OK
SQ->>SQ: onSuccess → toast.success(...)
SQ->>SQ: onSettled → invalidateQueries(list + details)
Reviews (2): Last reviewed commit: "refactor(scheduled-tasks): explicit retu..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
…guard - Seed the created job into the workspace-list cache on success so the new task renders instantly and the first-run empty state never flashes between the success toast and the list refetch; onSettled still reconciles authoritatively. - Reset the modal's submitting flag in a finally so the submit button can never stick disabled if the modal is kept open.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Remove the empty-state prompt and its supporting hasTasks flag; with the empty state gone, also revert the create optimistic-insert (its only purpose was avoiding the empty-state flash) back to plain toast + list invalidation.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Cancel, the header X, Escape, and overlay click all route through one guarded onOpenChange that no-ops while submitting, and the footer Cancel is disabled (cancelDisabled) — so an in-progress create/edit can't be abandoned mid-save and lose its draft. submitting moves up to TaskModal so the guard can read it.
Theme/Snap-to-grid (ChipSelect) hugged their content (~90px) while Timezone (ChipCombobox) was pinned to 260px, so the three read as a ragged column. Give all three a shared 240px trigger via fullWidth + a common width wrapper so they align as one column; menus match their triggers. No behavioral change — timezone keeps search, options and handlers are untouched.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 79d40f7. Configure here.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Delete bypasses the modal's dismiss guard (it closes via closeTask, not onOpenChange), so a click mid-save could run a delete against the same task as the in-flight update. Disable it while submitting, matching Cancel.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c5d659d. Configure here.
Move the Delete-lock rationale to a TSDoc block on secondaryActions, and restructure handleSubmit to a boolean persist result so the failure path is self-evident — removing the inline comments and the empty catch block.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
… double-submit The submitting state flag only reflects after a re-render, so two same-tick invocations (Enter racing the click) could both pass a state-based guard and fire two mutations. A submittingRef flips synchronously, so the second invocation is rejected before it can submit again; the state still drives the button/cancel UI.
waleedlatif1
commented
Jun 14, 2026
@greptile review |
waleedlatif1
commented
Jun 14, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit a7624ee. Configure here.
Summary
disable/reactivateendpoints. Paused occurrences render dimmed so a suspended task stays visible and resumable instead of disappearing.Type of Change
Testing
tailwind.config.ts), biome clean,check:api-validationandcheck:react-querypassreactivateendpoint requires a cron)Checklist