Compare commits

...

1 Commits

Author SHA1 Message Date
8bbaa440da feat(sca): map stripe error codes to user-facing copy in tui 2026-05-28 10:25:11 +02:00
2 changed files with 27 additions and 1 deletions

View File

@@ -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."
}

View File

@@ -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 {