summaryrefslogtreecommitdiff
path: root/internal/handlers/timeline_logic.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-25 17:05:49 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-25 17:09:41 -1000
commitdedda31d064ddcb4f857f2db851c5a8c1e19deba (patch)
tree2f76f41806727afa54449cdac8672056a5f8615c /internal/handlers/timeline_logic.go
parentec8a9c0ea46dec7d26caa763e3adefcaf3fc7552 (diff)
Implement architectural refactors for feature requests #28, #30, #31, #33-38
Phase 1: Bugs as First-Class Atoms (#28) - Add resolved_at column to bugs table (migration 007) - Add GetUnresolvedBugs(), ResolveBug(), UnresolveBug() store methods - Include bugs in Tasks tab via BugToAtom() with completion toggle - Add unit tests for bug resolution Phase 2: Timeline as Default + Enhancements (#35, #37) - Change default tab from tasks to timeline - Add IsCompleted, DaySection, Source fields to TimelineItem - Group timeline items by today/tomorrow/later sections - Add completion checkboxes for tasks/cards, grey completed items - Collapse tomorrow/later sections by default Phase 3: Shopping Quick-Add (#33) - Add user_shopping_items table (migration 008) - Add SaveUserShoppingItem(), GetUserShoppingItems(), ToggleUserShoppingItem() - Add HandleShoppingQuickAdd() and HandleShoppingToggle() handlers - Add quick-add form to shopping tab Phase 4: Mobile Swipe Navigation (#38) - Add touch event handlers for swipe left/right tab switching - 50px threshold triggers tab change Phase 5: Consistent Background Opacity (#30) - Add CSS variables for panel/card/input/modal backgrounds - Update templates to use consistent opacity classes Phase 6: Tab Reorganization (#37) - Reorganize tabs: Timeline, Shopping, Conditions as main tabs - Move Tasks, Planning, Meals under Details dropdown Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers/timeline_logic.go')
-rw-r--r--internal/handlers/timeline_logic.go36
1 files changed, 27 insertions, 9 deletions
diff --git a/internal/handlers/timeline_logic.go b/internal/handlers/timeline_logic.go
index 1aba780..c51262a 100644
--- a/internal/handlers/timeline_logic.go
+++ b/internal/handlers/timeline_logic.go
@@ -13,6 +13,7 @@ import (
// BuildTimeline aggregates and normalizes data into a timeline structure
func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.GoogleCalendarAPI, start, end time.Time) ([]models.TimelineItem, error) {
var items []models.TimelineItem
+ now := time.Now()
// 1. Fetch Tasks
tasks, err := s.GetTasksByDateRange(start, end)
@@ -23,7 +24,7 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl
if task.DueDate == nil {
continue
}
- items = append(items, models.TimelineItem{
+ item := models.TimelineItem{
ID: task.ID,
Type: models.TimelineItemTypeTask,
Title: task.Content,
@@ -31,7 +32,11 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl
Description: task.Description,
URL: task.URL,
OriginalItem: task,
- })
+ IsCompleted: task.Completed,
+ Source: "todoist",
+ }
+ item.ComputeDaySection(now)
+ items = append(items, item)
}
// 2. Fetch Meals
@@ -53,14 +58,18 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl
mealTime = time.Date(mealTime.Year(), mealTime.Month(), mealTime.Day(), 12, 0, 0, 0, mealTime.Location())
}
- items = append(items, models.TimelineItem{
+ item := models.TimelineItem{
ID: meal.ID,
Type: models.TimelineItemTypeMeal,
Title: meal.RecipeName,
Time: mealTime,
URL: meal.RecipeURL,
OriginalItem: meal,
- })
+ IsCompleted: false, // Meals don't have completion status
+ Source: "plantoeat",
+ }
+ item.ComputeDaySection(now)
+ items = append(items, item)
}
// 3. Fetch Cards
@@ -72,14 +81,18 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl
if card.DueDate == nil {
continue
}
- items = append(items, models.TimelineItem{
+ item := models.TimelineItem{
ID: card.ID,
Type: models.TimelineItemTypeCard,
Title: card.Name,
Time: *card.DueDate,
URL: card.URL,
OriginalItem: card,
- })
+ IsCompleted: false, // Cards in timeline are not completed (closed cards filtered out)
+ Source: "trello",
+ }
+ item.ComputeDaySection(now)
+ items = append(items, item)
}
// 4. Fetch Events
@@ -87,16 +100,21 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl
events, err := calendarClient.GetEventsByDateRange(ctx, start, end)
if err == nil {
for _, event := range events {
- items = append(items, models.TimelineItem{
+ endTime := event.End
+ item := models.TimelineItem{
ID: event.ID,
Type: models.TimelineItemTypeEvent,
Title: event.Summary,
Time: event.Start,
- EndTime: &event.End,
+ EndTime: &endTime,
Description: event.Description,
URL: event.HTMLLink,
OriginalItem: event,
- })
+ IsCompleted: false, // Events don't have completion status
+ Source: "calendar",
+ }
+ item.ComputeDaySection(now)
+ items = append(items, item)
}
}
}