Skip to content

Commit 95ab73d

Browse files
committed
feat: add cost column to policy status category table
1 parent 478c78c commit 95ab73d

5 files changed

Lines changed: 21 additions & 3 deletions

File tree

‎internal/app/statusbar/policystatus/policystatus.go‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ func (m *Model) stateKey(s domain.PolicySummary, cats []domain.PolicyCategorySta
109109
s.TotalBytesPerHour, len(cats))
110110

111111
for _, c := range cats {
112-
key += fmt.Sprintf("|%s:%d:%d:%d:%.0f:%.0f:%s:%s",
112+
key += fmt.Sprintf("|%s:%d:%d:%d:%.0f:%.0f:%.2f:%s:%s",
113113
c.Category, c.PendingCount, c.ApprovedCount, c.DismissedCount,
114-
c.EstimatedVolumePerHour, c.EstimatedBytesPerHour,
114+
c.EstimatedVolumePerHour, c.EstimatedBytesPerHour, c.EstimatedCostPerHour,
115115
c.RiskLevel, c.Benefit)
116116
}
117117

@@ -218,7 +218,7 @@ func (m *Model) renderCategoryTable(width int) string {
218218
}
219219

220220
tbl := table.New(m.theme, table.WithMaxValueWidth(30))
221-
tbl.Headers("Category", "Pending", "Risk", "Benefit", "Waste", "Impact")
221+
tbl.Headers("Category", "Pending", "Risk", "Benefit", "Waste", "Cost", "Impact")
222222
tbl.SetWidth(width)
223223

224224
for _, c := range m.categories {
@@ -228,6 +228,7 @@ func (m *Model) renderCategoryTable(width int) string {
228228
m.renderRisk(c.RiskLevel),
229229
formatBenefitLabel(c.Benefit),
230230
m.formatWaste(c),
231+
formatCategoryCost(c),
231232
formatCategoryImpact(c),
232233
)
233234
}
@@ -289,6 +290,17 @@ func wastePercent(s domain.PolicySummary) int {
289290
return 0
290291
}
291292

293+
// formatCategoryCost returns estimated monthly cost reduction for a category.
294+
func formatCategoryCost(c domain.PolicyCategoryStatus) string {
295+
if c.EstimatedCostPerHour > 0 {
296+
monthly := c.EstimatedCostPerHour * 730
297+
if monthly >= 1 {
298+
return "~" + formatCost(monthly) + "/mo"
299+
}
300+
}
301+
return "—"
302+
}
303+
292304
// formatCategoryImpact returns the best available impact string for a category.
293305
// Cascades: volume → bytes → dash.
294306
func formatCategoryImpact(c domain.PolicyCategoryStatus) string {

‎internal/domain/policy_category_status.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type PolicyCategoryStatus struct {
1919
DismissedCount int64
2020
EstimatedVolumePerHour float64
2121
EstimatedBytesPerHour float64
22+
EstimatedCostPerHour float64
2223
RiskLevel RiskLevel
2324
Benefit string
2425
}

‎internal/sqlite/gen/log_event_policies.sql.go‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎internal/sqlite/log_event_policies.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func (l *logEventPoliciesImpl) ListCategoryStatuses(ctx context.Context) ([]doma
4343
DismissedCount: row.DismissedCount,
4444
EstimatedVolumePerHour: derefFloat(row.EstimatedVolumePerHour),
4545
EstimatedBytesPerHour: derefFloat(row.EstimatedBytesPerHour),
46+
EstimatedCostPerHour: derefFloat(row.EstimatedCostPerHour),
4647
RiskLevel: domain.RiskLevel(row.RiskLevel),
4748
Benefit: row.Benefits,
4849
}

‎internal/sqlite/queries/log_event_policies.sql‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ SELECT
99
CAST(COALESCE(SUM(CASE WHEN status = 'DISMISSED' THEN 1 ELSE 0 END), 0) AS INTEGER) AS dismissed_count,
1010
SUM(CASE WHEN status = 'PENDING' THEN estimated_volume_reduction_per_hour ELSE 0 END) AS estimated_volume_per_hour,
1111
SUM(CASE WHEN status = 'PENDING' THEN estimated_bytes_reduction_per_hour ELSE 0 END) AS estimated_bytes_per_hour,
12+
SUM(CASE WHEN status = 'PENDING' THEN estimated_cost_reduction_per_hour_usd ELSE 0 END) AS estimated_cost_per_hour,
1213
CASE MAX(CASE risk_level
1314
WHEN 'high' THEN 3
1415
WHEN 'medium' THEN 2

0 commit comments

Comments
 (0)