diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-13 08:38:39 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-13 08:38:39 -1000 |
| commit | 043f48c12eb4dfc410e8724b430166000d7cb905 (patch) | |
| tree | 2d67af6a531bc1ad76bcf54641d1f49b36ab094b /internal/models/atom.go | |
| parent | 06c7485a7d05de86f9898e388161e8d932d5f3e6 (diff) | |
Implement unified Atom model for multi-source abstraction
- Create internal/models/atom.go with Atom struct and enums
- Add mapper functions for Task, Card, Note, and Meal types
- Normalize priority scales (1-4) and assign brand colors
- Update Phase 2 plan with Atom architecture as Step 1
- Document architectural decision in SESSION_STATE.md
This abstraction enables consistent handling, sorting, and rendering
of items from Trello, Todoist, Obsidian, and PlanToEat sources.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/models/atom.go')
| -rw-r--r-- | internal/models/atom.go | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/internal/models/atom.go b/internal/models/atom.go new file mode 100644 index 0000000..47695d9 --- /dev/null +++ b/internal/models/atom.go @@ -0,0 +1,135 @@ +package models + +import "time" + +type AtomSource string + +const ( + SourceTrello AtomSource = "trello" + SourceTodoist AtomSource = "todoist" + SourceObsidian AtomSource = "obsidian" + SourceMeal AtomSource = "plantoeat" +) + +type AtomType string + +const ( + TypeTask AtomType = "task" + TypeNote AtomType = "note" + TypeMeal AtomType = "meal" +) + +// Atom represents a unified unit of work or information +type Atom struct { + ID string + Title string + Description string + Source AtomSource + Type AtomType + + // Metadata + URL string + DueDate *time.Time + CreatedAt time.Time + + Priority int // Normalized: 1 (Low) to 4 (Urgent) + + // UI Helpers (to be populated by mappers) + SourceIcon string // e.g., "trello-icon.svg" or emoji + ColorClass string // e.g., "border-blue-500" + + // Original Data (for write operations) + Raw interface{} +} + +// TaskToAtom converts a Todoist Task to an Atom +func TaskToAtom(t Task) Atom { + // Todoist priority: 1 (normal) to 4 (urgent) + // Keep as-is since it already matches our 1-4 scale + priority := t.Priority + if priority < 1 { + priority = 1 + } + if priority > 4 { + priority = 4 + } + + return Atom{ + ID: t.ID, + Title: t.Content, + Description: t.Description, + Source: SourceTodoist, + Type: TypeTask, + URL: t.URL, + DueDate: t.DueDate, + CreatedAt: t.CreatedAt, + Priority: priority, + SourceIcon: "✓", // Checkmark emoji for tasks + ColorClass: "border-red-500", + Raw: t, + } +} + +// CardToAtom converts a Trello Card to an Atom +func CardToAtom(c Card) Atom { + // Trello doesn't have explicit priority, default to medium (2) + // Can be enhanced later with label-based priority detection + priority := 2 + + return Atom{ + ID: c.ID, + Title: c.Name, + Description: c.ListName, // Use list name as description + Source: SourceTrello, + Type: TypeTask, + URL: c.URL, + DueDate: c.DueDate, + CreatedAt: time.Time{}, // Trello ID contains timestamp, can be parsed later + Priority: priority, + SourceIcon: "📋", // Clipboard emoji for boards + ColorClass: "border-blue-500", + Raw: c, + } +} + +// NoteToAtom converts an Obsidian Note to an Atom +func NoteToAtom(n Note) Atom { + // Notes don't have priority, default to low (1) + priority := 1 + + return Atom{ + ID: n.Path, // Use path as unique ID + Title: n.Title, + Description: n.Content, + Source: SourceObsidian, + Type: TypeNote, + URL: "", // Obsidian notes don't have URLs + DueDate: nil, // Notes typically don't have due dates + CreatedAt: n.Modified, // Use modified time as created time + Priority: priority, + SourceIcon: "📝", // Memo emoji for notes + ColorClass: "border-purple-500", + Raw: n, + } +} + +// MealToAtom converts a PlanToEat Meal to an Atom +func MealToAtom(m Meal) Atom { + // Meals don't have priority, default to low (1) + priority := 1 + + return Atom{ + ID: m.ID, + Title: m.RecipeName, + Description: m.MealType, // breakfast, lunch, dinner + Source: SourceMeal, + Type: TypeMeal, + URL: m.RecipeURL, + DueDate: &m.Date, // Meal date is effectively the "due date" + CreatedAt: time.Time{}, + Priority: priority, + SourceIcon: "🍽️", // Fork and knife emoji for meals + ColorClass: "border-green-500", + Raw: m, + } +} |
