mirror of
https://github.com/marcusDenslow/terminalShop.git
synced 2026-10-25 02:52:20 +02:00
feat(models): derive order state from status + tracking
This commit is contained in:
25
cog.toml
Normal file
25
cog.toml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from_latest_tag = false
|
||||||
|
ignore_merge_commits = false
|
||||||
|
ignore_fixup_commits = false
|
||||||
|
disable_changelog = false
|
||||||
|
disable_bump_commit = false
|
||||||
|
generate_mono_repository_global_tag = true
|
||||||
|
generate_mono_repository_package_tags = true
|
||||||
|
branch_whitelist = []
|
||||||
|
pre = "alpha.*"
|
||||||
|
skip_ci = "[skip ci]"
|
||||||
|
skip_untracked = false
|
||||||
|
pre_bump_hooks = []
|
||||||
|
post_bump_hooks = []
|
||||||
|
pre_package_bump_hooks = []
|
||||||
|
post_package_bump_hooks = []
|
||||||
|
|
||||||
|
[git_hooks]
|
||||||
|
|
||||||
|
[commit_types]
|
||||||
|
|
||||||
|
[changelog]
|
||||||
|
path = "CHANGELOG.md"
|
||||||
|
authors = []
|
||||||
|
|
||||||
|
[bump_profiles]
|
||||||
76
pkg/models/order_display.go
Normal file
76
pkg/models/order_display.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// DisplayKind is a ui agnostic color/severity token.
|
||||||
|
// The TUI (or any other renderer) maps this to a concrete style
|
||||||
|
// the model stays free of UI deps.
|
||||||
|
type DisplayKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DisplayKindNeutral DisplayKind = "neutral" // pending, default
|
||||||
|
DisplayKindAccent DisplayKind = "accent" // paid, awaiting fulfillment
|
||||||
|
DisplayKindBrand DisplayKind = "brand" // shipped / in transit
|
||||||
|
DisplayKindSuccess DisplayKind = "success" // delivered
|
||||||
|
DisplayKindError DisplayKind = "error" // cancelled, failed, refunded
|
||||||
|
DisplayKindWarning DisplayKind = "warning" // refund pending, delivery issue
|
||||||
|
)
|
||||||
|
|
||||||
|
func (order *Order) DisplayState() string {
|
||||||
|
switch order.Status {
|
||||||
|
case OrderStatusPending:
|
||||||
|
return "Awaiting payment"
|
||||||
|
case OrderStatusPaid:
|
||||||
|
if order.TrackingNumber == "" {
|
||||||
|
return "Paid * awaiting label"
|
||||||
|
}
|
||||||
|
// !IMPORTANT
|
||||||
|
// Reachable only if UpdateTracking auto-promote is removed later
|
||||||
|
if order.TrackingStatus == TrackingStatusPreTransit {
|
||||||
|
return "Paid * ready to ship"
|
||||||
|
}
|
||||||
|
return "Paid"
|
||||||
|
case OrderStatusShipped:
|
||||||
|
switch order.TrackingStatus {
|
||||||
|
case TrackingStatusTransit:
|
||||||
|
return "Shipped * in transit"
|
||||||
|
case TrackingStatusFailure:
|
||||||
|
return "Shipped * delivery issue"
|
||||||
|
case TrackingStatusReturned:
|
||||||
|
return "Shipped * returned to sender"
|
||||||
|
case TrackingStatusDelivered:
|
||||||
|
// Webhook hasn't promoted Status yet, trust tracking
|
||||||
|
return "Delivered"
|
||||||
|
}
|
||||||
|
return "Shipped"
|
||||||
|
case OrderStatusDelivered:
|
||||||
|
return "Delivered"
|
||||||
|
case OrderStatusCancelled:
|
||||||
|
return "Cancelled"
|
||||||
|
case OrderStatusRefunded:
|
||||||
|
return "Refunded"
|
||||||
|
case OrderStatusFailed:
|
||||||
|
return "Payment failed"
|
||||||
|
}
|
||||||
|
return string(order.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (order *Order) DisplayKind() DisplayKind {
|
||||||
|
switch order.Status {
|
||||||
|
case OrderStatusPending:
|
||||||
|
return DisplayKindNeutral
|
||||||
|
case OrderStatusPaid:
|
||||||
|
return DisplayKindAccent
|
||||||
|
case OrderStatusShipped:
|
||||||
|
switch order.TrackingStatus {
|
||||||
|
case TrackingStatusFailure, TrackingStatusReturned:
|
||||||
|
return DisplayKindWarning
|
||||||
|
case TrackingStatusDelivered:
|
||||||
|
return DisplayKindSuccess
|
||||||
|
}
|
||||||
|
return DisplayKindBrand
|
||||||
|
case OrderStatusDelivered:
|
||||||
|
return DisplayKindSuccess
|
||||||
|
case OrderStatusCancelled, OrderStatusRefunded, OrderStatusFailed:
|
||||||
|
return DisplayKindError
|
||||||
|
}
|
||||||
|
return DisplayKindNeutral
|
||||||
|
}
|
||||||
36
pkg/models/order_display_test.go
Normal file
36
pkg/models/order_display_test.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestOrderDisplayState(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
order Order
|
||||||
|
want string
|
||||||
|
kind DisplayKind
|
||||||
|
}{
|
||||||
|
{"pending", Order{Status: OrderStatusPending}, "Awaiting payment", DisplayKindNeutral},
|
||||||
|
{"paid no tracking", Order{Status: OrderStatusPaid}, "Paid * awaiting label", DisplayKindAccent},
|
||||||
|
{"paid with tracking, no event", Order{Status: OrderStatusPaid, TrackingNumber: "12999"}, "Paid", DisplayKindAccent},
|
||||||
|
{"Paid pre-transit", Order{Status: OrderStatusPaid, TrackingNumber: "12999", TrackingStatus: TrackingStatusPreTransit}, "Paid * ready to ship", DisplayKindAccent},
|
||||||
|
{"shipped no tracking event", Order{Status: OrderStatusShipped}, "Shipped", DisplayKindBrand},
|
||||||
|
{"shipped in transit", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusTransit}, "Shipped * in transit", DisplayKindBrand},
|
||||||
|
{"shipped failure", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusFailure}, "Shipped * delivery issue", DisplayKindWarning},
|
||||||
|
{"shipped returned", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusReturned}, "Shipped * returned to sender", DisplayKindWarning},
|
||||||
|
{"shipped tracking-delivered (webhook lag)", Order{Status: OrderStatusShipped, TrackingStatus: TrackingStatusDelivered}, "Delivered", DisplayKindSuccess},
|
||||||
|
{"delivered", Order{Status: OrderStatusDelivered}, "Delivered", DisplayKindSuccess},
|
||||||
|
{"cancelled", Order{Status: OrderStatusCancelled}, "Cancelled", DisplayKindError},
|
||||||
|
{"refunded", Order{Status: OrderStatusRefunded}, "Refunded", DisplayKindError},
|
||||||
|
{"failed", Order{Status: OrderStatusFailed}, "Payment failed", DisplayKindError},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if got := tc.order.DisplayState(); got != tc.want {
|
||||||
|
t.Errorf("DisplayState() = %q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
if got := tc.order.DisplayKind(); got != tc.kind {
|
||||||
|
t.Errorf("DisplayKind() = %q, want %q", got, tc.kind)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,9 +74,9 @@ func (m Model) buildOrderCard(order models.Order, boxWidth int, isSelected bool)
|
|||||||
}
|
}
|
||||||
line1 := orderLabel + lipgloss.NewStyle().Width(spacing).Render("") + total
|
line1 := orderLabel + lipgloss.NewStyle().Width(spacing).Render("") + total
|
||||||
|
|
||||||
// Line 2: date + status
|
// Line 2: date + derived status
|
||||||
date := dimStyle.Render(order.CreatedAt.Format("Jan 02 2006"))
|
date := dimStyle.Render(order.CreatedAt.Format("Jan 02 2006"))
|
||||||
status := m.statusStyle(order.Status).Bold(true).Render(strings.ToUpper(string(order.Status)))
|
status := m.displayStyle(order.DisplayKind()).Bold(true).Render(order.DisplayState())
|
||||||
line2 := date + " " + status
|
line2 := date + " " + status
|
||||||
|
|
||||||
boxContent := line1 + "\n" + line2
|
boxContent := line1 + "\n" + line2
|
||||||
@@ -102,7 +102,7 @@ func (m Model) buildOrderDetailView(order models.Order, _ int) string {
|
|||||||
|
|
||||||
// Status and date
|
// Status and date
|
||||||
b.WriteString(labelStyle.Render("Status: "))
|
b.WriteString(labelStyle.Render("Status: "))
|
||||||
b.WriteString(m.statusStyle(order.Status).Render(strings.ToUpper(string(order.Status))))
|
b.WriteString(m.displayStyle(order.DisplayKind()).Render(order.DisplayState()))
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(labelStyle.Render("Date: "))
|
b.WriteString(labelStyle.Render("Date: "))
|
||||||
b.WriteString(valueStyle.Render(order.CreatedAt.Format("Jan 02 2006 3:04 PM")))
|
b.WriteString(valueStyle.Render(order.CreatedAt.Format("Jan 02 2006 3:04 PM")))
|
||||||
@@ -183,15 +183,23 @@ func (m Model) buildOrderDetailView(order models.Order, _ int) string {
|
|||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) statusStyle(s models.OrderStatus) lipgloss.Style {
|
// displayStyle maps a model-layer DisplayKind token to a themed lipgloss style.
|
||||||
switch s {
|
// Keeps pkg/models free of UI deps.
|
||||||
case models.OrderStatusDelivered:
|
func (m Model) displayStyle(k models.DisplayKind) lipgloss.Style {
|
||||||
|
switch k {
|
||||||
|
case models.DisplayKindSuccess:
|
||||||
return m.theme.TextSuccess()
|
return m.theme.TextSuccess()
|
||||||
case models.OrderStatusShipped:
|
case models.DisplayKindBrand:
|
||||||
return m.theme.TextBrand()
|
return m.theme.TextBrand()
|
||||||
case models.OrderStatusFailed, models.OrderStatusCancelled, models.OrderStatusRefunded:
|
case models.DisplayKindAccent:
|
||||||
|
return m.theme.TextAccent()
|
||||||
|
case models.DisplayKindError:
|
||||||
return m.theme.TextError()
|
return m.theme.TextError()
|
||||||
|
case models.DisplayKindWarning:
|
||||||
|
// !TODO add refunds and change this
|
||||||
|
// No warning color in theme yet, reuse loading pink as visual flag
|
||||||
|
// for now
|
||||||
|
return m.theme.TextLoading()
|
||||||
}
|
}
|
||||||
return m.theme.TextHighlight()
|
return m.theme.TextHighlight()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user