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
|
package render
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
"github.com/humdrum-tiv/dots-cli/internal/api"
"github.com/humdrum-tiv/dots-cli/internal/day"
)
// Grid renders the day as rows of colored dots with a legend.
// Logged = ● in type color; planned-only = ○ in type color; empty = dim ·.
// currentIndex (−1 to disable) gets an underline marker.
func Grid(d *api.DayData, currentIndex int) string {
blocksPerDay := 1440 / d.BlockSize
perRow := blocksPerDay / 6 // 6 rows → 4h per row at any blockSize
colorOf := make(map[string]string, len(d.Types))
for _, t := range d.Types {
colorOf[t.ID] = t.Color
}
var b strings.Builder
for row := 0; row < 6; row++ {
start := row * perRow
b.WriteString(fmt.Sprintf("%-6s", day.SlotLabel(start, d.BlockSize)))
for i := start; i < start+perRow; i++ {
style := lipgloss.NewStyle()
var glyph string
if id, ok := d.Blocks[i]; ok {
style = style.Foreground(lipgloss.Color(colorOf[id]))
glyph = "●"
} else if id, ok := d.PlanBlocks[i]; ok {
style = style.Foreground(lipgloss.Color(colorOf[id]))
glyph = "○"
} else {
style = style.Foreground(lipgloss.Color("240"))
glyph = "·"
}
if i == currentIndex {
style = style.Underline(true)
}
b.WriteString(style.Render(glyph) + " ")
}
b.WriteString("\n")
}
b.WriteString("\n")
for _, t := range d.Types {
sw := lipgloss.NewStyle().Foreground(lipgloss.Color(t.Color)).Render("●")
b.WriteString(fmt.Sprintf("%s %s ", sw, t.Name))
}
b.WriteString("\n")
return b.String()
}
|