1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# Timeline Feature Design
## Objective
Create a unified timeline view showing Tasks, Meals, Trello Cards, and Google Calendar Events, sorted chronologically.
## Data Sources
1. **Tasks (Todoist):** From DB `tasks` table. Filter: `due_date` is not null.
2. **Meals (PlanToEat):** From DB `meals` table. Filter: `date` is not null.
3. **Cards (Trello):** From DB `cards` table. Filter: `due_date` is not null.
4. **Google Calendar Events:** From `GoogleCalendarClient` (Live API).
## Backend Logic
### 1. Data Models (`internal/models/timeline.go`)
We need a polymorphic structure to hold different item types.
```go
type TimelineItemType string
const (
ItemTypeTask TimelineItemType = "task"
ItemTypeMeal TimelineItemType = "meal"
ItemTypeCard TimelineItemType = "card"
ItemTypeEvent TimelineItemType = "event"
)
type TimelineItem struct {
ID string `json:"id"`
Type TimelineItemType `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Time time.Time `json:"time"`
AllDay bool `json:"all_day"`
URL string `json:"url"`
Meta map[string]any `json:"meta"` // Extra data like ProjectName, RecipeURL, etc.
}
```
### 2. Store Extensions (`internal/store/`)
Add methods to fetch items by date range.
* `GetTasksByDateRange(start, end time.Time) ([]models.Task, error)`
* `GetMealsByDateRange(start, end time.Time) ([]models.Meal, error)`
* `GetCardsByDateRange(start, end time.Time) ([]models.Card, error)`
### 3. Logic Layer (`internal/handlers/timeline_logic.go`)
* **Function:** `BuildTimeline(store Store, calendarClient *api.GoogleCalendarClient, start, end time.Time) ([]TimelineItem, error)`
* **Aggregation:**
1. Fetch from Store (Tasks, Meals, Cards).
2. Fetch from Calendar API.
3. Convert all to `TimelineItem`.
4. **Meal Time Defaults:**
* Breakfast: 08:00
* Lunch: 12:00
* Dinner: 19:00
* Other: 12:00
5. Sort by `Time`.
### 4. HTTP Handler (`internal/handlers/timeline.go`)
* **Route:** `GET /timeline`
* **Params:** `start` (default: today), `days` (default: 7)
* **Response:** Render `timeline-tab.html` partial.
## UI Design (`web/templates/partials/timeline-tab.html`)
* **Structure:**
* Container
* Loop through Days
* Date Header (e.g., "Mon, Jan 2")
* List of Items
* Time Column (e.g., "14:00")
* Content Column (Icon + Title + Subtitle)
* **Styling:**
* Use existing CSS variables.
* Distinct icons/colors for Tasks vs Meals vs Events.
## Files to Modify
1. `internal/models/timeline.go` (New)
2. `internal/store/store.go` (Interface update)
3. `internal/store/sqlite.go` (Implementation update)
4. `internal/handlers/timeline_logic.go` (New)
5. `internal/handlers/timeline.go` (New)
6. `web/templates/partials/timeline-tab.html` (New)
7. `cmd/dashboard/main.go` (Route registration)
|