feat: improve CLI output with relative dates, rich feedback, and recurring task info
Add relative date formatting (today, tomorrow, in 3d, etc.) for list and detail views. Add structured feedback helpers for add/complete/delete operations showing display IDs and parsed modifiers. Change Complete() to return spawned recurring instance so callers can display recurrence info. Add AppendTask to working set for immediate display ID assignment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -188,20 +188,21 @@ func CreateRecurringTask(description string, mod *Modifier) (*Task, error) {
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
// SpawnNextInstance creates a new task instance from completed recurring task
|
||||
func SpawnNextInstance(completedInstance *Task) error {
|
||||
// SpawnNextInstance creates a new task instance from completed recurring task.
|
||||
// Returns the newly created instance, or nil if recurrence has expired.
|
||||
func SpawnNextInstance(completedInstance *Task) (*Task, error) {
|
||||
if completedInstance.ParentUUID == nil {
|
||||
return fmt.Errorf("task is not a recurring instance")
|
||||
return nil, fmt.Errorf("task is not a recurring instance")
|
||||
}
|
||||
|
||||
// Load template
|
||||
template, err := GetTask(*completedInstance.ParentUUID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load template: %w", err)
|
||||
return nil, fmt.Errorf("failed to load template: %w", err)
|
||||
}
|
||||
|
||||
if template.RecurrenceDuration == nil {
|
||||
return fmt.Errorf("template has no recurrence duration")
|
||||
return nil, fmt.Errorf("template has no recurrence duration")
|
||||
}
|
||||
|
||||
// Calculate next due date
|
||||
@@ -212,7 +213,7 @@ func SpawnNextInstance(completedInstance *Task) error {
|
||||
} else if completedInstance.Due != nil {
|
||||
baseDate = *completedInstance.Due
|
||||
} else {
|
||||
return fmt.Errorf("recurring instance has no due or end date")
|
||||
return nil, fmt.Errorf("recurring instance has no due or end date")
|
||||
}
|
||||
|
||||
next := CalculateNextDue(baseDate, *template.RecurrenceDuration)
|
||||
@@ -221,7 +222,7 @@ func SpawnNextInstance(completedInstance *Task) error {
|
||||
// Check if we're past 'until' date
|
||||
if template.Until != nil && nextDue != nil && nextDue.After(*template.Until) {
|
||||
// Don't spawn, recurrence has expired
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Create new instance
|
||||
@@ -243,20 +244,20 @@ func SpawnNextInstance(completedInstance *Task) error {
|
||||
}
|
||||
|
||||
if err := newInstance.Save(); err != nil {
|
||||
return fmt.Errorf("failed to save new instance: %w", err)
|
||||
return nil, fmt.Errorf("failed to save new instance: %w", err)
|
||||
}
|
||||
|
||||
// Copy tags from template
|
||||
templateTags, err := template.GetTags()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get template tags: %w", err)
|
||||
return nil, fmt.Errorf("failed to get template tags: %w", err)
|
||||
}
|
||||
|
||||
for _, tag := range templateTags {
|
||||
if err := newInstance.AddTag(tag); err != nil {
|
||||
return fmt.Errorf("failed to add tag: %w", err)
|
||||
return nil, fmt.Errorf("failed to add tag: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return newInstance, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user