Compare commits
2 Commits
feat/roast
...
docs/packa
| Author | SHA1 | Date | |
|---|---|---|---|
| ebbf66e76e | |||
| aa34043e9b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
docs/sca-psd2-compliance.md
|
docs/sca-psd2-compliance.md
|
||||||
accept-a-payment/
|
accept-a-payment/
|
||||||
|
codemap/
|
||||||
|
|
||||||
|
|
||||||
FULFILLMENT.md
|
FULFILLMENT.md
|
||||||
|
|||||||
3
api/doc.go
Normal file
3
api/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Command api is the HTTP backend: it boots the router, bolts on all the
|
||||||
|
// middleware, and answers the requests the TUI throws at it.
|
||||||
|
package main
|
||||||
3
api/handlers/doc.go
Normal file
3
api/handlers/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package handlers is where the real work happens, one function per endpoint:
|
||||||
|
// carts, orders, products, addresses, cards, webhooks, and the rest.
|
||||||
|
package handlers
|
||||||
4
api/middleware/doc.go
Normal file
4
api/middleware/doc.go
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Package middleware holds the stuff that runs on every request before a
|
||||||
|
// handler ever sees it: auth, CORS, logging, rate limiting, metrics, and a
|
||||||
|
// recovery net for panics.
|
||||||
|
package middleware
|
||||||
3
api/routes/doc.go
Normal file
3
api/routes/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package routes is the switchboard: it maps every URL to the handler that
|
||||||
|
// knows what to do with it.
|
||||||
|
package routes
|
||||||
3
cmd/reconcile-cards/doc.go
Normal file
3
cmd/reconcile-cards/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Command reconcile-cards hunts down saved cards that Stripe no longer knows
|
||||||
|
// about and detaches them. Run it with -dry-run first if you're nervous.
|
||||||
|
package main
|
||||||
3
pkg/api/doc.go
Normal file
3
pkg/api/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package api is the client side of the house: it talks to our HTTP backend
|
||||||
|
// so other Go code doesn't have to hand-roll requests.
|
||||||
|
package api
|
||||||
3
pkg/auth/doc.go
Normal file
3
pkg/auth/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package auth sorts out who you are: logging in with an SSH key and minting
|
||||||
|
// the JWT you carry around afterwards.
|
||||||
|
package auth
|
||||||
3
pkg/bring/doc.go
Normal file
3
pkg/bring/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package bring talks to Bring, the Norwegian postal service, for booking
|
||||||
|
// shipments and printing labels.
|
||||||
|
package bring
|
||||||
3
pkg/config/doc.go
Normal file
3
pkg/config/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package config reads everything out of the environment so secrets and
|
||||||
|
// settings stay out of the source code.
|
||||||
|
package config
|
||||||
3
pkg/database/doc.go
Normal file
3
pkg/database/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package database opens the SQLite connection, runs the migrations, and
|
||||||
|
// drops in some seed data so the shop isn't empty on a fresh boot.
|
||||||
|
package database
|
||||||
3
pkg/models/doc.go
Normal file
3
pkg/models/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package models is the shared vocabulary of the app: coffee, carts, orders,
|
||||||
|
// addresses, cards, users, and the other nouns everything passes around.
|
||||||
|
package models
|
||||||
3
pkg/observability/doc.go
Normal file
3
pkg/observability/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package observability sets up tracing and structured logs so that when
|
||||||
|
// something breaks at 3am you stand a chance of figuring out why.
|
||||||
|
package observability
|
||||||
3
pkg/shipping/doc.go
Normal file
3
pkg/shipping/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package shipping holds the plain shipping types that the rest of the app
|
||||||
|
// passes back and forth.
|
||||||
|
package shipping
|
||||||
2
pkg/shippo/doc.go
Normal file
2
pkg/shippo/doc.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package shippo talks to the Shippo API for shipping rates and labels.
|
||||||
|
package shippo
|
||||||
3
pkg/stripeclient/doc.go
Normal file
3
pkg/stripeclient/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package stripeclient wires up the Stripe SDK once at startup (with tracing
|
||||||
|
// baked in) so everyone else can just make calls.
|
||||||
|
package stripeclient
|
||||||
3
pkg/tui/doc.go
Normal file
3
pkg/tui/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package tui is the terminal UI you see over SSH: the shop, the cart, your
|
||||||
|
// account, and the checkout flow, all drawn with Bubbletea.
|
||||||
|
package tui
|
||||||
@@ -276,9 +276,7 @@ func (m Model) updatePaymentViewport() Model {
|
|||||||
breadH := lipgloss.Height(m.BuildBreadcrumbs())
|
breadH := lipgloss.Height(m.BuildBreadcrumbs())
|
||||||
footerH := lipgloss.Height(m.BuildFooter())
|
footerH := lipgloss.Height(m.BuildFooter())
|
||||||
availH := m.heightContainer - headerH - footerH - breadH
|
availH := m.heightContainer - headerH - footerH - breadH
|
||||||
if availH < 1 {
|
availH = max(availH, 1)
|
||||||
availH = 1
|
|
||||||
}
|
|
||||||
if !m.payment.viewportReady {
|
if !m.payment.viewportReady {
|
||||||
m.payment.viewport = viewport.New(viewport.WithWidth(m.widthContent), viewport.WithHeight(availH))
|
m.payment.viewport = viewport.New(viewport.WithWidth(m.widthContent), viewport.WithHeight(availH))
|
||||||
m.payment.viewport.KeyMap = viewport.KeyMap{}
|
m.payment.viewport.KeyMap = viewport.KeyMap{}
|
||||||
@@ -303,7 +301,7 @@ func (m Model) PaymentPageView() string {
|
|||||||
m.widthContainer,
|
m.widthContainer,
|
||||||
m.payment.viewport.Height(),
|
m.payment.viewport.Height(),
|
||||||
lipgloss.Center, lipgloss.Center,
|
lipgloss.Center, lipgloss.Center,
|
||||||
m.renderPaymentHttpsView(),
|
m.renderPaymentHTTPSView(),
|
||||||
)
|
)
|
||||||
} else if m.payment.view == 0 && m.payment.form == nil {
|
} else if m.payment.view == 0 && m.payment.form == nil {
|
||||||
content = m.RenderCardList()
|
content = m.RenderCardList()
|
||||||
@@ -374,7 +372,7 @@ func (m Model) RenderCardList() string {
|
|||||||
return lipgloss.JoinVertical(lipgloss.Left, parts...)
|
return lipgloss.JoinVertical(lipgloss.Left, parts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) renderPaymentHttpsView() string {
|
func (m Model) renderPaymentHTTPSView() string {
|
||||||
baseStyle := m.theme.TextLabel()
|
baseStyle := m.theme.TextLabel()
|
||||||
accentStyle := m.theme.TextHighlight()
|
accentStyle := m.theme.TextHighlight()
|
||||||
|
|
||||||
|
|||||||
3
pkg/tui/qrfefe/doc.go
Normal file
3
pkg/tui/qrfefe/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package qrfefe turns text into a QR code drawn with terminal block
|
||||||
|
// characters, handy for showing links you can scan right off the screen.
|
||||||
|
package qrfefe
|
||||||
@@ -24,9 +24,7 @@ const (
|
|||||||
// menu(menuW+4) + gap(1) + detail(detailW+4) = contentW = wideW + 4.
|
// menu(menuW+4) + gap(1) + detail(detailW+4) = contentW = wideW + 4.
|
||||||
func (m Model) shopLayout() (contentW, menuW, detailW, wideW int) {
|
func (m Model) shopLayout() (contentW, menuW, detailW, wideW int) {
|
||||||
contentW = m.widthContent
|
contentW = m.widthContent
|
||||||
if contentW > 74 {
|
contentW = min(contentW, 74)
|
||||||
contentW = 74
|
|
||||||
}
|
|
||||||
wideW = contentW - 4
|
wideW = contentW - 4
|
||||||
if m.size < large {
|
if m.size < large {
|
||||||
// Stacked layout: both panels span the full content width.
|
// Stacked layout: both panels span the full content width.
|
||||||
@@ -66,6 +64,7 @@ func clampLines(s string, n int) string {
|
|||||||
|
|
||||||
// roastMeter renders the strength dots, e.g. ● ● ● ○ ○
|
// roastMeter renders the strength dots, e.g. ● ● ● ○ ○
|
||||||
func roastMeter(n int) string {
|
func roastMeter(n int) string {
|
||||||
|
n = max(0, min(n, 5))
|
||||||
on := lipgloss.NewStyle().Foreground(cGold).Render(strings.Repeat("● ", n))
|
on := lipgloss.NewStyle().Foreground(cGold).Render(strings.Repeat("● ", n))
|
||||||
off := pDim.Render(strings.Repeat("○ ", 5-n))
|
off := pDim.Render(strings.Repeat("○ ", 5-n))
|
||||||
return strings.TrimRight(on+off, " ")
|
return strings.TrimRight(on+off, " ")
|
||||||
@@ -218,12 +217,8 @@ func (m Model) shopMoveSelected(previous bool) Model {
|
|||||||
} else {
|
} else {
|
||||||
next++
|
next++
|
||||||
}
|
}
|
||||||
if next < 0 {
|
next = max(next, 0)
|
||||||
next = 0
|
next = min(next, len(m.Coffees)-1)
|
||||||
}
|
|
||||||
if next >= len(m.Coffees) {
|
|
||||||
next = len(m.Coffees) - 1
|
|
||||||
}
|
|
||||||
m.shop.selected = next
|
m.shop.selected = next
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|||||||
3
pkg/tui/theme/doc.go
Normal file
3
pkg/tui/theme/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package theme keeps the colors and styles in one spot so the whole UI
|
||||||
|
// looks like it was built by the same person.
|
||||||
|
package theme
|
||||||
3
pkg/utils/doc.go
Normal file
3
pkg/utils/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package utils is the catch-all drawer for tiny HTTP helpers that didn't
|
||||||
|
// earn a package of their own.
|
||||||
|
package utils
|
||||||
3
pkg/validate/doc.go
Normal file
3
pkg/validate/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package validate gives user input a once-over before the rest of the app
|
||||||
|
// trusts it.
|
||||||
|
package validate
|
||||||
Reference in New Issue
Block a user