From 8bbaa440dacaf49f152ccb057a21d82d948ed1a3 Mon Sep 17 00:00:00 2001 From: marcusDenslow Date: Thu, 28 May 2026 10:25:11 +0200 Subject: [PATCH] feat(sca): map stripe error codes to user-facing copy in tui --- pkg/tui/confirmation.go | 24 +++++++++++++++++++++++- pkg/tui/views.go | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/tui/confirmation.go b/pkg/tui/confirmation.go index 1ba431d..a0f106c 100644 --- a/pkg/tui/confirmation.go +++ b/pkg/tui/confirmation.go @@ -3,6 +3,7 @@ package tui import ( "fmt" "strings" + "terminalShop/pkg/models" "charm.land/bubbles/v2/viewport" @@ -192,7 +193,7 @@ func (m Model) ReviewUpdate(msg tea.Msg) (Model, tea.Cmd) { m.CheckingOut = false if msg.Err != nil { m = m.SwitchPage(paymentPage) - m.error = &VisibleError{message: fmt.Sprintf("checkout failed: %v", msg.Err)} + m.error = &VisibleError{message: friendlyCheckoutError(msg.Err)} m.review.cardJustAdded = false m.payment.view = 0 m.payment.form = nil @@ -234,3 +235,24 @@ func (m Model) ReviewUpdate(msg tea.Msg) (Model, tea.Cmd) { } return m, nil } + +func friendlyCheckoutError(raw error) string { + s := raw.Error() + switch { + case strings.Contains(s, "AUTHENTICATION_REQUIRED"): + return "your bank wants to verify this charge, authentication step coming soon." + case strings.Contains(s, "AUTHENTICATION_NOT_SUPPORTED"): + return "this card doesn't support online authentication. Try another card" + case strings.Contains(s, "CARD_EXPIRED"): + return "card expired. Add a new card and try again" + case strings.Contains(s, "CARD_CVC_FAILED"): + return "card cvc incorrect. Check the back of the card and try again" + case strings.Contains(s, "CARD_INSUFFICIENT_FUNDS"): + return "insufficient funds on this card" + case strings.Contains(s, "CARD_PROCESSING_ERROR"): + return "card processing error. Try again in a moment" + case strings.Contains(s, "CARD_DECLINED"): + return "card declined" + } + return "checkout failed, try again." +} diff --git a/pkg/tui/views.go b/pkg/tui/views.go index 8aff00b..a68f512 100644 --- a/pkg/tui/views.go +++ b/pkg/tui/views.go @@ -82,6 +82,10 @@ func (m Model) renderString() string { content = loadingStyle.Render("Loading products from API...") } else if m.error != nil { errorStyle := m.theme.PanelError().Padding(0, 1).MarginBottom(1) + // soft-wrap long messages instead of clipping. + if m.widthContent > 4 { + errorStyle = errorStyle.Width(m.widthContent - 4) + } errorBanner := errorStyle.Render(m.error.message) content = errorBanner + "\n" + m.buildPageContent(availableContentHeight) } else if m.notice != nil {