types.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5package planning
 6
 7import (
 8	"crypto/sha256"
 9	"fmt"
10	"strings"
11	"time"
12)
13
14// TaskStatus represents the status of a task
15type TaskStatus int
16
17const (
18	StatusPending TaskStatus = iota
19	StatusInProgress
20	StatusCompleted
21	StatusFailed
22)
23
24// String returns the emoji representation of the task status
25func (s TaskStatus) String() string {
26	switch s {
27	case StatusPending:
28		return "☐"
29	case StatusInProgress:
30		return "⟳"
31	case StatusCompleted:
32		return "☑"
33	case StatusFailed:
34		return "☒"
35	default:
36		return "☐"
37	}
38}
39
40// ParseStatus converts a string status to TaskStatus enum
41func ParseStatus(status string) TaskStatus {
42	switch strings.ToLower(status) {
43	case "pending":
44		return StatusPending
45	case "in_progress":
46		return StatusInProgress
47	case "completed":
48		return StatusCompleted
49	case "failed":
50		return StatusFailed
51	default:
52		return StatusPending
53	}
54}
55
56// Goal represents the overarching goal
57type Goal struct {
58	Text      string    `json:"text"`
59	UpdatedAt time.Time `json:"updated_at"`
60}
61
62// Task represents a single task
63type Task struct {
64	ID          string     `json:"id"`
65	Title       string     `json:"title"`
66	Description string     `json:"description"`
67	Status      TaskStatus `json:"status"`
68	CreatedAt   time.Time  `json:"created_at"`
69	UpdatedAt   time.Time  `json:"updated_at"`
70}
71
72// NewTask creates a new task with a deterministic ID
73func NewTask(title, description string) *Task {
74	// Generate deterministic ID based on title and description
75	id := generateTaskID(title, description)
76
77	return &Task{
78		ID:          id,
79		Title:       title,
80		Description: description,
81		Status:      StatusPending,
82		CreatedAt:   time.Now(),
83		UpdatedAt:   time.Now(),
84	}
85}
86
87// UpdateStatus updates the task status and timestamp
88func (t *Task) UpdateStatus(status TaskStatus) {
89	t.Status = status
90	t.UpdatedAt = time.Now()
91}
92
93// generateTaskID creates a deterministic 8-character ID based on task content
94func generateTaskID(title, description string) string {
95	content := fmt.Sprintf("%s:%s", title, description)
96	hash := sha256.Sum256([]byte(content))
97	return fmt.Sprintf("%x", hash[:4]) // 8 hex characters
98}