summaryrefslogtreecommitdiff
path: root/internal/store/labels.go
blob: 216b171d928d5b4fc026f604e34978f202bfa683 (plain)
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
package store

import (
	"encoding/json"

	"task-dashboard/internal/models"
)

// SetTaskLabels replaces a task's label set entirely (not an add/remove
// single-label API), matching UpdateNativeTask's replace-whole-value style.
// Returns ErrNativeTaskNotFound if id doesn't match any row.
func (s *Store) SetTaskLabels(id string, labels []string) error {
	labelsJSON, _ := json.Marshal(labels)
	result, err := s.db.Exec(`
		UPDATE native_tasks SET labels = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?
	`, string(labelsJSON), id)
	if err != nil {
		return err
	}
	return checkRowsAffected(result)
}

// GetLabelColors returns every label that has been assigned a color.
func (s *Store) GetLabelColors() ([]models.LabelColor, error) {
	rows, err := s.db.Query(`SELECT name, color, budget_tracked FROM labels ORDER BY name ASC`)
	if err != nil {
		return nil, err
	}
	defer func() { _ = rows.Close() }()

	var colors []models.LabelColor
	for rows.Next() {
		var c models.LabelColor
		if err := rows.Scan(&c.Name, &c.Color, &c.BudgetTracked); err != nil {
			return nil, err
		}
		colors = append(colors, c)
	}
	return colors, rows.Err()
}

// SetLabelColor assigns (or reassigns) a label's display color, preserving
// any existing budget_tracked flag -- a plain INSERT OR REPLACE would
// delete-and-reinsert the row, silently resetting budget_tracked to 0.
func (s *Store) SetLabelColor(name, color string) error {
	_, err := s.db.Exec(`
		INSERT INTO labels (name, color, budget_tracked) VALUES (?, ?, 0)
		ON CONFLICT(name) DO UPDATE SET color = excluded.color
	`, name, color)
	return err
}

// SetLabelBudgetTracked marks a label as opted in (or out) of budget
// tracking, preserving any existing color the same way SetLabelColor
// preserves budget_tracked.
func (s *Store) SetLabelBudgetTracked(name string, tracked bool) error {
	_, err := s.db.Exec(`
		INSERT INTO labels (name, color, budget_tracked) VALUES (?, '', ?)
		ON CONFLICT(name) DO UPDATE SET budget_tracked = excluded.budget_tracked
	`, name, tracked)
	return err
}

// GetBudgetTrackedLabelNames returns the set of label names opted into budget tracking.
func (s *Store) GetBudgetTrackedLabelNames() (map[string]bool, error) {
	rows, err := s.db.Query(`SELECT name FROM labels WHERE budget_tracked = 1`)
	if err != nil {
		return nil, err
	}
	defer func() { _ = rows.Close() }()

	names := make(map[string]bool)
	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {
			return nil, err
		}
		names[name] = true
	}
	return names, rows.Err()
}