Skip to content

Commit fcd30e5

Browse files
tryonlinuxclaude
andauthored
feat: Add start-to-current weight delta in stats display (#3)
Display weight change from first entry to latest in the stats header. Shows "Lost X lbs/kg", "Gained X lbs/kg", or "No change" based on delta. Includes comprehensive test coverage for all scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 88057b4 commit fcd30e5

2 files changed

Lines changed: 96 additions & 2 deletions

File tree

internal/display/table.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,28 @@ func RenderWeightsTable(weights []models.Weight, settings *models.Settings, limi
4949
avgWeight := totalWeight / float64(len(weights))
5050
latestWeight := weights[0].Weight
5151
latestBMI := weights[0].BMI
52+
startWeight := weights[len(weights)-1].Weight
53+
54+
// Calculate change from start
55+
delta := latestWeight - startWeight
56+
var deltaStr string
57+
if delta < 0 {
58+
// Lost weight
59+
deltaStr = fmt.Sprintf("Lost %s", FormatWeight(math.Abs(delta), settings.WeightUnit))
60+
} else if delta > 0 {
61+
// Gained weight
62+
deltaStr = fmt.Sprintf("Gained %s", FormatWeight(delta, settings.WeightUnit))
63+
} else {
64+
deltaStr = "No change"
65+
}
5266

5367
// Build stats header (goes with ASCII art header)
5468
var header strings.Builder
55-
header.WriteString(HeaderStyle.Render(fmt.Sprintf("Latest: %s | BMI: %s | Avg: %s",
69+
header.WriteString(HeaderStyle.Render(fmt.Sprintf("Latest: %s | BMI: %s | Avg: %s | %s",
5670
FormatWeight(latestWeight, settings.WeightUnit),
5771
FormatBMI(latestBMI),
58-
FormatWeight(avgWeight, settings.WeightUnit))))
72+
FormatWeight(avgWeight, settings.WeightUnit),
73+
deltaStr)))
5974
header.WriteString("\n")
6075
header.WriteString(InfoStyle.Render(fmt.Sprintf("Min: %s | Max: %s | Entries: %d",
6176
FormatWeight(minWeight, settings.WeightUnit),

tests/display_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package tests
22

33
import (
4+
"strings"
45
"testing"
56

67
"github.com/tryonlinux/thicc/internal/display"
8+
"github.com/tryonlinux/thicc/internal/models"
79
)
810

911
func TestFormatWeight(t *testing.T) {
@@ -60,3 +62,80 @@ func TestFormatDate(t *testing.T) {
6062
}
6163
}
6264
}
65+
66+
func TestRenderWeightsTableDelta(t *testing.T) {
67+
tests := []struct {
68+
name string
69+
weights []models.Weight
70+
settings *models.Settings
71+
expectedStr string
72+
}{
73+
{
74+
name: "weight loss shows 'Lost'",
75+
weights: []models.Weight{
76+
{ID: 3, Date: "2024-01-15", Weight: 150.0, BMI: 22.0},
77+
{ID: 2, Date: "2024-01-08", Weight: 155.0, BMI: 22.5},
78+
{ID: 1, Date: "2024-01-01", Weight: 160.0, BMI: 23.0},
79+
},
80+
settings: &models.Settings{
81+
WeightUnit: "lbs",
82+
HeightUnit: "in",
83+
Height: 70,
84+
GoalWeight: 145,
85+
},
86+
expectedStr: "Lost 10.00 lbs",
87+
},
88+
{
89+
name: "weight gain shows 'Gained'",
90+
weights: []models.Weight{
91+
{ID: 3, Date: "2024-01-15", Weight: 165.0, BMI: 23.5},
92+
{ID: 2, Date: "2024-01-08", Weight: 160.0, BMI: 23.0},
93+
{ID: 1, Date: "2024-01-01", Weight: 155.0, BMI: 22.5},
94+
},
95+
settings: &models.Settings{
96+
WeightUnit: "lbs",
97+
HeightUnit: "in",
98+
Height: 70,
99+
GoalWeight: 150,
100+
},
101+
expectedStr: "Gained 10.00 lbs",
102+
},
103+
{
104+
name: "no change shows 'No change'",
105+
weights: []models.Weight{
106+
{ID: 2, Date: "2024-01-08", Weight: 160.0, BMI: 23.0},
107+
{ID: 1, Date: "2024-01-01", Weight: 160.0, BMI: 23.0},
108+
},
109+
settings: &models.Settings{
110+
WeightUnit: "lbs",
111+
HeightUnit: "in",
112+
Height: 70,
113+
GoalWeight: 150,
114+
},
115+
expectedStr: "No change",
116+
},
117+
{
118+
name: "metric units show correctly",
119+
weights: []models.Weight{
120+
{ID: 2, Date: "2024-01-08", Weight: 70.0, BMI: 22.0},
121+
{ID: 1, Date: "2024-01-01", Weight: 75.0, BMI: 23.0},
122+
},
123+
settings: &models.Settings{
124+
WeightUnit: "kg",
125+
HeightUnit: "cm",
126+
Height: 180,
127+
GoalWeight: 68,
128+
},
129+
expectedStr: "Lost 5.00 kg",
130+
},
131+
}
132+
133+
for _, tt := range tests {
134+
t.Run(tt.name, func(t *testing.T) {
135+
result := display.RenderWeightsTable(tt.weights, tt.settings, 20)
136+
if !strings.Contains(result, tt.expectedStr) {
137+
t.Errorf("RenderWeightsTable() output does not contain expected delta string '%s'", tt.expectedStr)
138+
}
139+
})
140+
}
141+
}

0 commit comments

Comments
 (0)