▍ humdrum codex / dots v1.0.0
1.5 KB raw
 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()
}