mirror of
https://github.com/marcusDenslow/terminalShop.git
synced 2026-10-25 02:52:20 +02:00
fix: use fixed-height order cards and correct viewport height
Simplify order list cards to 2 content lines (matching reference) so itemHeight is always 4. Remove extra margin/buffer from viewport height calc since account is a viewport page with no margins. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,12 +11,11 @@ import (
|
||||
// updateAccountViewport initializes or resizes the detail viewport for the account page.
|
||||
// Follows the reference pattern: each page owns its own viewport(s).
|
||||
func (m Model) updateAccountViewport() Model {
|
||||
// Match the reference: only subtract header + footer, no extra margins
|
||||
// (account is a viewport page — views.go renders it without margin padding)
|
||||
headerHeight := lipgloss.Height(m.BuildHeader())
|
||||
footerHeight := 1
|
||||
marginTop := 1
|
||||
marginBottom := 1
|
||||
bufferSpace := 1
|
||||
verticalMarginHeight := headerHeight + footerHeight + marginTop + marginBottom + bufferSpace
|
||||
footerHeight := lipgloss.Height(m.BuildFooter())
|
||||
verticalMarginHeight := headerHeight + footerHeight
|
||||
|
||||
availableHeight := m.heightContainer - verticalMarginHeight
|
||||
|
||||
@@ -102,25 +101,20 @@ func (m Model) scrollToAccountDetailItem() Model {
|
||||
|
||||
switch {
|
||||
case m.account.orderViewState == 1:
|
||||
// "Order History" + MarginBottom(2) + "\n\n" = ~5 header lines
|
||||
headerOffset = 5
|
||||
if m.heightContainer >= 25 {
|
||||
// border(2) + vPadding(2) + content(~4) + gap(1) = 9
|
||||
itemHeight = 9
|
||||
} else {
|
||||
// border(2) + content(~4) + gap(1) = 7
|
||||
itemHeight = 7
|
||||
}
|
||||
// No title in list mode, cards joined with JoinVertical (no gaps)
|
||||
// Card: border(2) + content(2) + PaddingLeft only = 4 lines
|
||||
headerOffset = 0
|
||||
itemHeight = 4
|
||||
itemCount = len(m.Orders)
|
||||
selectedIndex = m.account.orderCursor
|
||||
case m.account.addressListFocused:
|
||||
headerOffset = 5
|
||||
itemHeight = 6
|
||||
headerOffset = 3
|
||||
itemHeight = 5
|
||||
itemCount = len(m.SavedAddresses)
|
||||
selectedIndex = m.account.addressCursor
|
||||
case m.account.cardListFocused:
|
||||
headerOffset = 5
|
||||
itemHeight = 5
|
||||
headerOffset = 3
|
||||
itemHeight = 4
|
||||
itemCount = len(m.SavedCards)
|
||||
selectedIndex = m.account.cardCursor
|
||||
default:
|
||||
|
||||
@@ -10,49 +10,49 @@ import (
|
||||
)
|
||||
|
||||
func (m Model) OrdersView(width int) string {
|
||||
titleStyle := m.theme.TextAccent().Bold(true).MarginBottom(2)
|
||||
titleStyle := m.theme.TextAccent().Bold(true).MarginBottom(1)
|
||||
contentStyle := m.theme.TextBody().Width(width)
|
||||
|
||||
if !m.OrdersLoaded {
|
||||
return titleStyle.Render("Order History") + "\n\n" + contentStyle.Render("Loading orders...")
|
||||
return titleStyle.Render("Order History") + "\n" + contentStyle.Render("Loading orders...")
|
||||
}
|
||||
if len(m.Orders) == 0 {
|
||||
return titleStyle.Render("Order History") + "\n\n" + contentStyle.Render("No orders yet")
|
||||
return titleStyle.Render("Order History") + "\n" + contentStyle.Render("No orders yet")
|
||||
}
|
||||
if m.account.orderViewState == 2 {
|
||||
return m.buildOrderDetailView(m.Orders[m.account.orderCursor], width)
|
||||
}
|
||||
|
||||
boxWidth := width - 4
|
||||
boxPadding := 0
|
||||
if m.heightContainer >= 25 {
|
||||
boxPadding = 1
|
||||
}
|
||||
boxWidth := width - 2
|
||||
|
||||
lines := titleStyle.Render("Order History") + "\n\n"
|
||||
// Build cards and join vertically — no manual "\n" gaps means fixed spacing
|
||||
var cards []string
|
||||
for i, order := range m.Orders {
|
||||
isSelected := m.account.orderViewState == 1 && i == m.account.orderCursor
|
||||
lines += m.buildOrderCard(order, boxWidth, isSelected, boxPadding)
|
||||
if i < len(m.Orders)-1 {
|
||||
lines += "\n"
|
||||
}
|
||||
cards = append(cards, m.buildOrderCard(order, boxWidth, isSelected))
|
||||
}
|
||||
cardList := lipgloss.JoinVertical(lipgloss.Left, cards...)
|
||||
|
||||
// In preview mode (viewState 0), show title + hint
|
||||
if m.account.orderViewState == 0 {
|
||||
hintStyle := m.theme.TextDim()
|
||||
lines += "\n" + hintStyle.Render("enter: browse orders")
|
||||
return titleStyle.Render("Order History") + "\n" +
|
||||
cardList + "\n" +
|
||||
hintStyle.Render("enter: browse orders")
|
||||
}
|
||||
return lines
|
||||
|
||||
// In list browsing mode (viewState 1), just show cards — no title
|
||||
// (the left panel menu already shows "order history" as selected)
|
||||
return cardList
|
||||
}
|
||||
|
||||
// buildOrderCard renders a single order as a bordered box for the order list.
|
||||
// Shows order number, date, status, total, and the first 2 items as a preview.
|
||||
func (m Model) buildOrderCard(order models.Order, boxWidth int, isSelected bool, boxPadding int) string {
|
||||
// Order header line: "Order #123" left, "Jan 02 2026 PAID" right
|
||||
// buildOrderCard renders a single order as a bordered box with fixed height.
|
||||
// Shows order number + total on line 1, date + status on line 2.
|
||||
// Item details are shown in the detail view (viewState 2).
|
||||
func (m Model) buildOrderCard(order models.Order, boxWidth int, isSelected bool) string {
|
||||
nameStyle := m.theme.TextAccent().Bold(true)
|
||||
|
||||
// When selected, item preview text uses accent color instead of dim
|
||||
// so the whole card "lights up" — much more visible than border color alone
|
||||
// When selected, secondary text uses accent color so the whole card "lights up"
|
||||
dimStyle := m.theme.TextDim()
|
||||
if isSelected {
|
||||
dimStyle = m.theme.TextAccent()
|
||||
@@ -60,49 +60,30 @@ func (m Model) buildOrderCard(order models.Order, boxWidth int, isSelected bool,
|
||||
|
||||
statusStyle := m.theme.TextHighlight().Bold(true)
|
||||
|
||||
// Line 1: "Order #N" left, "$X.XX" right
|
||||
orderLabel := nameStyle.Render(fmt.Sprintf("Order #%d", order.ID))
|
||||
total := nameStyle.Render(fmt.Sprintf("$%.2f", float64(order.Total)/100.0))
|
||||
date := dimStyle.Render(order.CreatedAt.Format("Jan 02 2006"))
|
||||
status := statusStyle.Render(strings.ToUpper(string(order.Status)))
|
||||
|
||||
rightSide := date + " " + status + " " + total
|
||||
rightWidth := lipgloss.Width(rightSide)
|
||||
innerWidth := boxWidth - 4 // account for border + padding
|
||||
leftWidth := lipgloss.Width(orderLabel)
|
||||
spacing := boxWidth - leftWidth - rightWidth - 4 // 4 for padding
|
||||
rightWidth := lipgloss.Width(total)
|
||||
spacing := innerWidth - leftWidth - rightWidth
|
||||
if spacing < 1 {
|
||||
spacing = 1
|
||||
}
|
||||
line1 := orderLabel + lipgloss.NewStyle().Width(spacing).Render("") + total
|
||||
|
||||
line1 := orderLabel + lipgloss.NewStyle().Width(spacing).Render("") + rightSide
|
||||
// Line 2: date + status
|
||||
date := dimStyle.Render(order.CreatedAt.Format("Jan 02 2006"))
|
||||
status := statusStyle.Render(strings.ToUpper(string(order.Status)))
|
||||
line2 := date + " " + status
|
||||
|
||||
// Item preview lines (show first 2 items)
|
||||
var lines []string
|
||||
lines = append(lines, line1)
|
||||
boxContent := line1 + "\n" + line2
|
||||
|
||||
previewCount := 2
|
||||
if len(order.Items) < previewCount {
|
||||
previewCount = len(order.Items)
|
||||
}
|
||||
for i := 0; i < previewCount; i++ {
|
||||
item := order.Items[i]
|
||||
itemLine := dimStyle.Render(fmt.Sprintf("%dx %s - $%.2f", item.Quantity, item.Name, float64(item.Price)/100.0))
|
||||
lines = append(lines, itemLine)
|
||||
}
|
||||
if len(order.Items) > 2 {
|
||||
extra := len(order.Items) - 2
|
||||
moreText := "item"
|
||||
if extra > 1 {
|
||||
moreText = "items"
|
||||
}
|
||||
lines = append(lines, dimStyle.Render(fmt.Sprintf("+ %d more %s", extra, moreText)))
|
||||
}
|
||||
|
||||
boxContent := strings.Join(lines, "\n")
|
||||
|
||||
// Create bordered box — both use NormalBorder, differentiated by color only
|
||||
// Fixed-height box: NormalBorder + PaddingLeft only (no vertical padding)
|
||||
base := lipgloss.NewStyle().
|
||||
Border(lipgloss.NormalBorder()).
|
||||
Padding(boxPadding, 2).
|
||||
PaddingLeft(1).
|
||||
Width(boxWidth)
|
||||
|
||||
var itemBox lipgloss.Style
|
||||
@@ -116,7 +97,7 @@ func (m Model) buildOrderCard(order models.Order, boxWidth int, isSelected bool,
|
||||
}
|
||||
|
||||
// buildOrderDetailView renders the full detail view for a single order
|
||||
func (m Model) buildOrderDetailView(order models.Order, width int) string {
|
||||
func (m Model) buildOrderDetailView(order models.Order, _ int) string {
|
||||
titleStyle := m.theme.TextAccent().Bold(true).MarginBottom(1)
|
||||
|
||||
labelStyle := m.theme.TextHighlight().Bold(true)
|
||||
|
||||
Reference in New Issue
Block a user