diff --git a/internal/display/table.go b/internal/display/table.go index 6a80f42..fa2773d 100644 --- a/internal/display/table.go +++ b/internal/display/table.go @@ -49,13 +49,28 @@ func RenderWeightsTable(weights []models.Weight, settings *models.Settings, limi avgWeight := totalWeight / float64(len(weights)) latestWeight := weights[0].Weight latestBMI := weights[0].BMI + startWeight := weights[len(weights)-1].Weight + + // Calculate change from start + delta := latestWeight - startWeight + var deltaStr string + if delta < 0 { + // Lost weight + deltaStr = fmt.Sprintf("Lost %s", FormatWeight(math.Abs(delta), settings.WeightUnit)) + } else if delta > 0 { + // Gained weight + deltaStr = fmt.Sprintf("Gained %s", FormatWeight(delta, settings.WeightUnit)) + } else { + deltaStr = "No change" + } // Build stats header (goes with ASCII art header) var header strings.Builder - header.WriteString(HeaderStyle.Render(fmt.Sprintf("Latest: %s | BMI: %s | Avg: %s", + header.WriteString(HeaderStyle.Render(fmt.Sprintf("Latest: %s | BMI: %s | Avg: %s | %s", FormatWeight(latestWeight, settings.WeightUnit), FormatBMI(latestBMI), - FormatWeight(avgWeight, settings.WeightUnit)))) + FormatWeight(avgWeight, settings.WeightUnit), + deltaStr))) header.WriteString("\n") header.WriteString(InfoStyle.Render(fmt.Sprintf("Min: %s | Max: %s | Entries: %d", FormatWeight(minWeight, settings.WeightUnit), diff --git a/tests/display_test.go b/tests/display_test.go index 783b04f..b47c292 100644 --- a/tests/display_test.go +++ b/tests/display_test.go @@ -1,9 +1,11 @@ package tests import ( + "strings" "testing" "github.com/tryonlinux/thicc/internal/display" + "github.com/tryonlinux/thicc/internal/models" ) func TestFormatWeight(t *testing.T) { @@ -60,3 +62,80 @@ func TestFormatDate(t *testing.T) { } } } + +func TestRenderWeightsTableDelta(t *testing.T) { + tests := []struct { + name string + weights []models.Weight + settings *models.Settings + expectedStr string + }{ + { + name: "weight loss shows 'Lost'", + weights: []models.Weight{ + {ID: 3, Date: "2024-01-15", Weight: 150.0, BMI: 22.0}, + {ID: 2, Date: "2024-01-08", Weight: 155.0, BMI: 22.5}, + {ID: 1, Date: "2024-01-01", Weight: 160.0, BMI: 23.0}, + }, + settings: &models.Settings{ + WeightUnit: "lbs", + HeightUnit: "in", + Height: 70, + GoalWeight: 145, + }, + expectedStr: "Lost 10.00 lbs", + }, + { + name: "weight gain shows 'Gained'", + weights: []models.Weight{ + {ID: 3, Date: "2024-01-15", Weight: 165.0, BMI: 23.5}, + {ID: 2, Date: "2024-01-08", Weight: 160.0, BMI: 23.0}, + {ID: 1, Date: "2024-01-01", Weight: 155.0, BMI: 22.5}, + }, + settings: &models.Settings{ + WeightUnit: "lbs", + HeightUnit: "in", + Height: 70, + GoalWeight: 150, + }, + expectedStr: "Gained 10.00 lbs", + }, + { + name: "no change shows 'No change'", + weights: []models.Weight{ + {ID: 2, Date: "2024-01-08", Weight: 160.0, BMI: 23.0}, + {ID: 1, Date: "2024-01-01", Weight: 160.0, BMI: 23.0}, + }, + settings: &models.Settings{ + WeightUnit: "lbs", + HeightUnit: "in", + Height: 70, + GoalWeight: 150, + }, + expectedStr: "No change", + }, + { + name: "metric units show correctly", + weights: []models.Weight{ + {ID: 2, Date: "2024-01-08", Weight: 70.0, BMI: 22.0}, + {ID: 1, Date: "2024-01-01", Weight: 75.0, BMI: 23.0}, + }, + settings: &models.Settings{ + WeightUnit: "kg", + HeightUnit: "cm", + Height: 180, + GoalWeight: 68, + }, + expectedStr: "Lost 5.00 kg", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := display.RenderWeightsTable(tt.weights, tt.settings, 20) + if !strings.Contains(result, tt.expectedStr) { + t.Errorf("RenderWeightsTable() output does not contain expected delta string '%s'", tt.expectedStr) + } + }) + } +}