diff --git a/pkg/tui/cart.go b/pkg/tui/cart.go index 06e0970..082b8f5 100644 --- a/pkg/tui/cart.go +++ b/pkg/tui/cart.go @@ -33,7 +33,8 @@ func (m Model) generateCartContent() string { Align(lipgloss.Center). Width(m.widthContent). Padding(2, 0) - return emptyStyle.Render("Your cart is empty\n\nPress s to go back to shop") + render := emptyStyle.Render("Your cart is empty\n\nPress s to go back to shop") + return render } cartItems := "" @@ -148,7 +149,8 @@ func (m Model) CartUpdate(msg tea.Msg) (Model, tea.Cmd) { cartItems := m.GetCartItemsSlice() if m.cart.cursor >= 0 && m.cart.cursor < len(cartItems) { cartItems[m.cart.cursor].Quantity++ - return m, m.syncCartItemCmd(cartItems[m.cart.cursor].CoffeeID, cartItems[m.cart.cursor].Quantity) + m, cmd := m.syncCartItemCmd(cartItems[m.cart.cursor].CoffeeID, cartItems[m.cart.cursor].Quantity) + return m, cmd } case "-", "_": cartItems := m.GetCartItemsSlice() @@ -165,7 +167,8 @@ func (m Model) CartUpdate(msg tea.Msg) (Model, tea.Cmd) { } newQty = 0 } - return m, m.syncCartItemCmd(coffeeID, newQty) + m, cmd := m.syncCartItemCmd(coffeeID, newQty) + return m, cmd } case "p", "enter": if !m.IsCartEmpty() { diff --git a/pkg/tui/model.go b/pkg/tui/model.go index e01adfc..698bab8 100644 --- a/pkg/tui/model.go +++ b/pkg/tui/model.go @@ -346,7 +346,7 @@ func (m Model) checkoutStep() int { // updateLayout recalculates all layout variables from the raw viewport dimensions. // This should be called whenever the terminal is resized. -func (m *Model) updateLayout(width, height int) { +func (m Model) updateLayout(width, height int) Model { m.viewportWidth = width m.viewportHeight = height switch { @@ -369,6 +369,7 @@ func (m *Model) updateLayout(width, height int) { } m.widthContent = m.widthContainer - 2 + return m } // ProductsMsg is sent when products are fetched from API @@ -646,15 +647,15 @@ func (m Model) checkoutWithSavedCard() tea.Cmd { } } -func (m *Model) syncCartItemCmd(coffeeID uint, quantity int) tea.Cmd { +func (m Model) syncCartItemCmd(coffeeID uint, quantity int) (Model, tea.Cmd) { if m.APIClient == nil || m.User == nil { - return nil + return m, nil } updateID := time.Now().UTC().UnixMilli() m.lastCartUpdateID = updateID - return func() tea.Msg { + return m, func() tea.Msg { cart, err := m.APIClient.SetCartItem(coffeeID, quantity) return CartSyncedMsg{ UpdateID: updateID, @@ -748,10 +749,10 @@ func (m Model) saveCardOnlyCmd(form PaymentFormCompleteMsg) tea.Cmd { // loadCartFromAPI populates the in-memory cart map from an API CartData response // It matches cart items to local Coffees by ID so the Coffee struct is populated -func (m *Model) loadCartFromAPI(cartData *api.CartData) { +func (m Model) loadCartFromAPI(cartData *api.CartData) Model { m.Cart = make(map[uint]*models.CartItem) if cartData == nil { - return + return m } for _, item := range cartData.Items { @@ -765,14 +766,15 @@ func (m *Model) loadCartFromAPI(cartData *api.CartData) { if m.cart.cursor >= len(m.Cart) { m.cart.cursor = 0 } + return m } // GetCartItemsSlice converts the cart map to a sorted slice for consistent iteration. func (m Model) GetCartItemsSlice() []*models.CartItem { // Get keys and sort them for stable ordering keys := make([]uint, 0, len(m.Cart)) - for key := range m.Cart { - keys = append(keys, key) + for cartKey := range m.Cart { + keys = append(keys, cartKey) } // Sort keys to ensure consistent order @@ -780,8 +782,8 @@ func (m Model) GetCartItemsSlice() []*models.CartItem { // Build items slice in sorted order items := make([]*models.CartItem, 0, len(m.Cart)) - for _, key := range keys { - items = append(items, m.Cart[key]) + for _, cartKey := range keys { + items = append(items, m.Cart[cartKey]) } return items } @@ -890,7 +892,7 @@ func newModelWithRenderer(username string, renderer *lipgloss.Renderer) Model { APIClient: api.NewClient("http://localhost:8080", ""), FAQs: LoadFaqs(), } - m.updateLayout(120, 30) + m = m.updateLayout(120, 30) return m } diff --git a/pkg/tui/payment_form.go b/pkg/tui/payment_form.go index d96527e..6d388a5 100644 --- a/pkg/tui/payment_form.go +++ b/pkg/tui/payment_form.go @@ -370,7 +370,7 @@ func (m Model) renderPaymentHttpsView() string { return baseStyle.Render(" generating payment link...") } - qr, qrSize, err := qrfefe.Generate(0, *m.payment.collectURL) + qr, qrSize, err := qrfefe.Generate(*m.payment.collectURL) if err != nil || qrSize > m.widthContent { // QR too wide for the terminal — just show the URL. return baseStyle.Render("open in browser to add payment information:") + "\n\n" + diff --git a/pkg/tui/shop.go b/pkg/tui/shop.go index 52ec23f..33c6038 100644 --- a/pkg/tui/shop.go +++ b/pkg/tui/shop.go @@ -180,7 +180,8 @@ func (m Model) ShopUpdate(msg tea.Msg) (Model, tea.Cmd) { } else { m.Cart[coffeeID] = &models.CartItem{CoffeeID: coffeeID, Coffee: coffee, Quantity: 1} } - return m, m.syncCartItemCmd(coffeeID, m.Cart[coffeeID].Quantity) + m, cmd := m.syncCartItemCmd(coffeeID, m.Cart[coffeeID].Quantity) + return m, cmd case "-", "_": coffeeID := coffee.ID if item, exists := m.Cart[coffeeID]; exists { @@ -190,7 +191,8 @@ func (m Model) ShopUpdate(msg tea.Msg) (Model, tea.Cmd) { delete(m.Cart, coffeeID) newQty = 0 } - return m, m.syncCartItemCmd(coffeeID, newQty) + m, cmd := m.syncCartItemCmd(coffeeID, newQty) + return m, cmd } } } diff --git a/pkg/tui/update.go b/pkg/tui/update.go index 14a4cbd..33e8675 100644 --- a/pkg/tui/update.go +++ b/pkg/tui/update.go @@ -13,7 +13,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // Resize debounce tick, must fire before page dispatch if tick, ok := msg.(resizeTickMsg); ok { if tick.seq == m.resizeSeq { - m.updateLayout(m.pendingWidth, m.pendingHeight) + m = m.updateLayout(m.pendingWidth, m.pendingHeight) switch m.currentPage { case shopPage: m = m.updateShopViewports() @@ -97,7 +97,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.Username = u.Name } cart := &api.CartData{Items: msg.Data.Cart} - m.loadCartFromAPI(cart) + m = m.loadCartFromAPI(cart) m.SavedAddresses = msg.Data.Addresses m.SavedCards = msg.Data.Cards m.Orders = msg.Data.Orders @@ -112,7 +112,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, m.fetchCartCmd } if msg.UpdateID == m.lastCartUpdateID { - m.loadCartFromAPI(msg.Cart) + m = m.loadCartFromAPI(msg.Cart) } return m, nil case tokenRefreshTickMsg: