revert and update: reverted shippo logic and changed error msg in TUI

a while back i made shippo skip "validate" addresses that didnt
specifically fail the validation process. this meant that addresses
outside the us worked as long as they didnt specifically return false.
this is now reverted to test actual validaion.

also changed some error messages in the TUI so that the entire message
type is not also printed, just the message
This commit is contained in:
2026-02-28 22:26:01 +01:00
parent 18c7a93e0b
commit 92d5c46e19
4 changed files with 33 additions and 30 deletions

View File

@@ -121,13 +121,12 @@ func (c *Client) ValidateAddress(addr Address) (*Address, error) {
return nil, fmt.Errorf("failed to parse response: %w", err)
}
// TODO: Re-add !result.Test bypass before production if needed.
// Removed test mode bypass so we can verify Shippo validation in development.
//
// Shippo returns empty validation_results (no is_valid field) for international
// addresses. We only reject when is_valid is explicitly false.
if result.ValidationResults != nil && result.ValidationResults.IsValid != nil && !*result.ValidationResults.IsValid {
return nil, fmt.Errorf("address is invalid")
// Only accept addresses that Shippo explicitly validates as valid.
// International addressees where Shippo cannot validate are rejected.
// Address validation for addresses in other countries need to be added on a per-country API basis.
// Going to add Bring validation for Norway next
if result.ValidationResults == nil || result.ValidationResults.IsValid == nil || !*result.ValidationResults.IsValid {
return nil, fmt.Errorf("invalid address")
}
// Return the normalized address from Shippo

View File

@@ -238,11 +238,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case AddressSavedMsg:
if msg.Err != nil {
log.Printf("address validation failed: %v", msg.Err)
if m.ShippingForm != nil {
m.ShippingForm.submitting = false
m.ShippingForm.form = m.buildShippingForm(m.ShippingForm)
}
m.ErrorMsg = fmt.Sprintf("Invalid address: %v", msg.Err)
m.ErrorMsg = "Invalid address. Currently only US addresses are supported."
return m, m.ShippingForm.form.Init()
}
m.ShippingInfo = &msg.Address
@@ -432,11 +433,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case AddressSavedMsg:
if msg.Err != nil {
log.Printf("address validation failed: %v", msg.Err)
if m.ShippingForm != nil {
m.ShippingForm.submitting = false
m.ShippingForm.form = m.buildShippingForm(m.ShippingForm)
}
m.ErrorMsg = fmt.Sprintf("Invalid address: %v", msg.Err)
m.ErrorMsg = "Invalid address. Currently only US addresses are supported."
if m.ShippingForm != nil {
return m, m.ShippingForm.form.Init()
}

View File

@@ -9,8 +9,8 @@ import (
"github.com/charmbracelet/lipgloss"
)
// scandinavianCountries defines the available countries with their dial codes.
var scandinavianCountries = []struct {
// countries defines the available countries with their dial codes.
var countries = []struct {
Name string
Code string
DialCode string
@@ -20,6 +20,7 @@ var scandinavianCountries = []struct {
{Name: "Iceland", Code: "IS", DialCode: "+354"},
{Name: "Norway", Code: "NO", DialCode: "+47"},
{Name: "Sweden", Code: "SE", DialCode: "+46"},
{Name: "USA", Code: "US", DialCode: "+1"},
}
// countryDialCodes maps country ISO codes to their dialing prefixes.
@@ -29,6 +30,7 @@ var countryDialCodes = map[string]string{
"IS": "+354",
"NO": "+47",
"SE": "+46",
"US": "+1",
}
// ShippingFormState holds the shipping form state.
@@ -49,14 +51,14 @@ type ShippingFormState struct {
// ShippingFormCompleteMsg is sent when the shipping form is completed
type ShippingFormCompleteMsg struct {
Name string
Street1 string
Street2 string
City string
State string
Country string
Zip string
Phone string
Name string
Street1 string
Street2 string
City string
State string
Country string
Zip string
Phone string
}
// ShippingFormErrorMsg is sent when form validation fails at submission time
@@ -68,8 +70,8 @@ type ShippingFormErrorMsg struct {
// No field-level validators so Tab/Enter move freely between fields.
// Validation happens at submission time instead.
func (m Model) buildShippingForm(state *ShippingFormState) *huh.Form {
countryOptions := make([]huh.Option[string], 0, len(scandinavianCountries))
for _, c := range scandinavianCountries {
countryOptions := make([]huh.Option[string], 0, len(countries))
for _, c := range countries {
label := fmt.Sprintf("%s (%s)", c.Name, c.DialCode)
countryOptions = append(countryOptions, huh.NewOption(label, c.Code))
}
@@ -218,14 +220,14 @@ func (m Model) UpdateShippingForm(msg tea.Msg, state *ShippingFormState) tea.Cmd
phone := formatPhoneWithDialCode(state.Phone, state.Country)
return func() tea.Msg {
return ShippingFormCompleteMsg{
Name: state.Name,
Street1: state.Street1,
Street2: state.Street2,
City: state.City,
State: state.State,
Country: state.Country,
Zip: state.Zip,
Phone: phone,
Name: state.Name,
Street1: state.Street1,
Street2: state.Street2,
City: state.City,
State: state.State,
Country: state.Country,
Zip: state.Zip,
Phone: phone,
}
}
}

View File

@@ -81,7 +81,7 @@ func MustBeLen(length int, name string) ErrorHandler {
return nil
}
if len(str) != length {
return fmt.Errorf("Expected %s to be length %d but got %d", name, length, len(str))
return fmt.Errorf("expected %s to be length %d but got %d", name, length, len(str))
}
return nil
}