From e97a1bc259d3aa91956ec73a522421cdb621ae57 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Thu, 22 Jan 2026 15:28:06 -1000 Subject: Add Google Calendar integration - Add GoogleCalendarClient for fetching upcoming events - Add GoogleCalendarAPI interface and CalendarEvent model - Add config for GOOGLE_CREDENTIALS_FILE and GOOGLE_CALENDAR_ID - Display events in Planning tab with date/time formatting - Update handlers and tests to support optional calendar client Config env vars: - GOOGLE_CREDENTIALS_FILE: Path to service account JSON - GOOGLE_CALENDAR_ID: Calendar ID (defaults to "primary") Co-Authored-By: Claude Opus 4.5 --- internal/handlers/handlers.go | 44 ++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'internal/handlers/handlers.go') diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 19415c7..1cb978d 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -22,16 +22,17 @@ import ( // Handler holds dependencies for HTTP handlers type Handler struct { - store *store.Store - todoistClient api.TodoistAPI - trelloClient api.TrelloAPI - planToEatClient api.PlanToEatAPI - config *config.Config - templates *template.Template + store *store.Store + todoistClient api.TodoistAPI + trelloClient api.TrelloAPI + planToEatClient api.PlanToEatAPI + googleCalendarClient api.GoogleCalendarAPI + config *config.Config + templates *template.Template } // New creates a new Handler instance -func New(s *store.Store, todoist api.TodoistAPI, trello api.TrelloAPI, planToEat api.PlanToEatAPI, cfg *config.Config) *Handler { +func New(s *store.Store, todoist api.TodoistAPI, trello api.TrelloAPI, planToEat api.PlanToEatAPI, googleCalendar api.GoogleCalendarAPI, cfg *config.Config) *Handler { // Parse templates including partials tmpl, err := template.ParseGlob(filepath.Join(cfg.TemplateDir, "*.html")) if err != nil { @@ -45,12 +46,13 @@ func New(s *store.Store, todoist api.TodoistAPI, trello api.TrelloAPI, planToEat } return &Handler{ - store: s, - todoistClient: todoist, - trelloClient: trello, - planToEatClient: planToEat, - config: cfg, - templates: tmpl, + store: s, + todoistClient: todoist, + trelloClient: trello, + planToEatClient: planToEat, + googleCalendarClient: googleCalendar, + config: cfg, + templates: tmpl, } } @@ -279,6 +281,22 @@ func (h *Handler) aggregateData(ctx context.Context, forceRefresh bool) (*models }() } + // Fetch Google Calendar events (if configured) + if h.googleCalendarClient != nil { + wg.Add(1) + go func() { + defer wg.Done() + events, err := h.googleCalendarClient.GetUpcomingEvents(ctx, 10) + mu.Lock() + defer mu.Unlock() + if err != nil { + data.Errors = append(data.Errors, "Google Calendar: "+err.Error()) + } else { + data.Events = events + } + }() + } + wg.Wait() // Filter Trello cards into tasks based on heuristic -- cgit v1.2.3