From 043f48c12eb4dfc410e8724b430166000d7cb905 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Tue, 13 Jan 2026 08:38:39 -1000 Subject: 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 --- internal/models/atom.go | 135 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 internal/models/atom.go (limited to 'internal') 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, + } +} -- cgit v1.2.3