feat(go): M6.4 — Go-native /payments page (grouped-by-person ledger)
All checks were successful
Deploy to K8s / deploy (push) Successful in 6s

- Extract AssemblePayments(ctx) from ServePayments in api/handler.go,
  mirroring the AssembleAdults/AssembleJuniors pattern
- Add PaymentsPageData view-model wrapper in render.go
- Rewire html_handler.go ServePayments to call AssemblePayments and
  render with PaymentsPageData
- Replace payments.tmpl placeholder with real grouped-by-person ledger:
  alphabetical member blocks, txn-table (Date/Amount/Purpose/Message),
  newest-first rows, Unmatched/Unknown bucket
- Append ledger CSS classes to app.css (.ledger-container, .member-block,
  .txn-table, .txn-date/amount/purpose/message, tr:hover)
- Add TestPaymentsPage markup test

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-08 12:29:32 +02:00
parent 7f87e63b7c
commit cb8a09b571
7 changed files with 368 additions and 6 deletions

View File

@@ -76,13 +76,22 @@ func (h *Handler) AssembleJuniors(ctx context.Context) (JuniorsResponse, error)
// ServePayments handles GET /api/payments.
func (h *Handler) ServePayments(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
txns, err := h.Sources.LoadTransactions(ctx)
resp, err := h.AssemblePayments(r.Context())
if err != nil {
h.writeError(w, r, fmt.Errorf("load transactions: %w", err))
h.writeError(w, r, err)
return
}
writeJSON(w, buildPaymentsResponse(txns, h.allMemberNames(ctx)))
writeJSON(w, resp)
}
// AssemblePayments loads transactions and builds the payments view model.
// Shared between the JSON API route and the HTML handler.
func (h *Handler) AssemblePayments(ctx context.Context) (PaymentsResponse, error) {
txns, err := h.Sources.LoadTransactions(ctx)
if err != nil {
return PaymentsResponse{}, fmt.Errorf("load transactions: %w", err)
}
return buildPaymentsResponse(txns, h.allMemberNames(ctx)), nil
}
func (h *Handler) loadAll(ctx context.Context, adults bool) (