Skip to content

feat: Google Calendar sync backend - #24

Merged
thomasluizon merged 8 commits into
mainfrom
feature/google-calendar-sync
Mar 23, 2026
Merged

thomasluizon merged 8 commits into
mainfrom
feature/google-calendar-sync

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

Summary

  • Store Google OAuth tokens on User entity during login
  • GET /api/calendar/events - fetch events from Google Calendar for user selection
  • POST /api/calendar/import - create habits from selected events with RRULE parsing
  • Google token refresh service for expired access tokens
  • DB migration for GoogleAccessToken/GoogleRefreshToken columns

Config Required

  • Google:ClientId and Google:ClientSecret env vars for token refresh
  • Google Calendar API enabled in Google Cloud Console
  • calendar.readonly scope added to Supabase Google provider

Test plan

  • Login with Google, verify tokens stored on User
  • GET /api/calendar/events returns event list
  • POST /api/calendar/import creates habits with correct frequency/days/reminders

🤖 Generated with Claude Code

thomasluizon and others added 8 commits March 22, 2026 21:44
New POST /api/habits/{id}/skip endpoint that advances a recurring
habit's due date to the next scheduled occurrence without creating
a HabitLog entry. Reuses existing AdvanceDueDate domain method.

Validates: habit exists, owned by user, is recurring, due today or
overdue, not already completed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace ReminderMinutesBefore (int) with ReminderTimes (List<int>)
  stored as jsonb, supporting multiple reminder times per habit
- Update SentReminder to track MinutesBefore for per-reminder
  deduplication with unique index (HabitId, Date, MinutesBefore)
- Update ReminderSchedulerService to iterate over all reminder times
  with human-readable notification text (minutes/hours/days)
- Fix CreateSubHabitCommand to accept days, frequency, and dueTime
  overrides so AI chat sub-habits get correct active days
- Update all DTOs, commands, queries, and AI chat integration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrates existing ReminderMinutesBefore values to ReminderTimes jsonb
array before dropping the old column. Adds MinutesBefore to
SentReminders with updated unique index.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous migration had a stale model snapshot that didn't include
the value converter/comparer metadata for ReminderTimes, causing
PendingModelChangesWarning in CI. Regenerated from scratch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add GoogleAccessToken/GoogleRefreshToken to User entity
- Store Google tokens during OAuth login flow
- Add GET /api/calendar/events (preview events for selection)
- Add POST /api/calendar/import (create habits from selected events)
- RRULE parsing: DAILY, WEEKLY, MONTHLY, YEARLY, BYDAY, INTERVAL
- Google token refresh service with OAuth2 token endpoint
- Map event reminders to Orbit reminderTimes array
- DB migration for Google token columns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add HasImportedCalendar to User entity, set after successful import
- Add HasGoogleConnection (computed from token presence) to profile response
- DB migration for HasImportedCalendar column

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@thomasluizon
thomasluizon merged commit 25b63ad into main Mar 23, 2026
2 checks passed
@thomasluizon
thomasluizon deleted the feature/google-calendar-sync branch March 23, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant