From e7aee6b9d0c2be22530f7813bf677c0c8bff99e4 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Mon, 29 Jun 2026 09:31:37 +0000 Subject: feat: reschedule tasks from widget bottom sheet Tapping a doot task shows a date picker. On confirm, POSTs to /api/widget/reschedule, updates due_date in native_tasks, refreshes widget. Reschedule button only shows for source="doot" tasks. Co-Authored-By: Claude Sonnet 4.6 --- internal/handlers/widget.go | 31 +++++++++++++++++++++++++++++++ internal/store/native_tasks.go | 8 ++++++++ 2 files changed, 39 insertions(+) (limited to 'internal') diff --git a/internal/handlers/widget.go b/internal/handlers/widget.go index 360ccc5..ee13dc4 100644 --- a/internal/handlers/widget.go +++ b/internal/handlers/widget.go @@ -101,6 +101,37 @@ type widgetCompleteRequest struct { Source string `json:"source"` } +type widgetRescheduleRequest struct { + ID string `json:"id"` + Source string `json:"source"` + Date string `json:"date"` // YYYY-MM-DD +} + +// HandleWidgetReschedule updates the due date of a native task. +func (h *Handler) HandleWidgetReschedule(w http.ResponseWriter, r *http.Request) { + var req widgetRescheduleRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + if req.Source != "doot" { + http.Error(w, "only doot tasks can be rescheduled via widget", http.StatusBadRequest) + return + } + parsed, err := time.Parse("2006-01-02", req.Date) + if err != nil { + http.Error(w, "invalid date", http.StatusBadRequest) + return + } + tz := config.GetDisplayTimezone() + dueDate := time.Date(parsed.Year(), parsed.Month(), parsed.Day(), 0, 0, 0, 0, tz) + if err := h.store.RescheduleNativeTask(req.ID, dueDate); err != nil { + http.Error(w, "failed to reschedule", http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) +} + // HandleWidgetComplete proxies a task completion to the source API or native store. func (h *Handler) HandleWidgetComplete(w http.ResponseWriter, r *http.Request) { var req widgetCompleteRequest diff --git a/internal/store/native_tasks.go b/internal/store/native_tasks.go index 3ec043b..ca19377 100644 --- a/internal/store/native_tasks.go +++ b/internal/store/native_tasks.go @@ -80,6 +80,14 @@ func (s *Store) CompleteNativeTask(id string) error { return err } +// RescheduleNativeTask sets a new due date on a task. +func (s *Store) RescheduleNativeTask(id string, dueDate time.Time) error { + _, err := s.db.Exec(` + UPDATE native_tasks SET due_date = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? + `, dueDate, id) + return err +} + // UncompleteNativeTask marks a task as not completed. func (s *Store) UncompleteNativeTask(id string) error { _, err := s.db.Exec(` -- cgit v1.2.3