diff --git a/api/handlers/tracking.go b/api/handlers/tracking.go new file mode 100644 index 0000000..83b2d0a --- /dev/null +++ b/api/handlers/tracking.go @@ -0,0 +1,33 @@ +package handlers + +import ( + "net/http" + "strconv" + + "github.com/go-chi/chi/v5" + + "terminalShop/pkg/database" + "terminalShop/pkg/models" +) + +// TrackingRedirect resolves an order ID and 302s to the carrier's tracking URL. +// Public (no auth) so the URL stays short enough to copy from any TUI width. +func TrackingRedirect(w http.ResponseWriter, r *http.Request) { + idStr := chi.URLParam(r, "id") + id, err := strconv.ParseUint(idStr, 10, 32) + if err != nil { + http.Error(w, "bad order id", http.StatusBadRequest) + return + } + + var order models.Order + if err := database.GetDB().Select("tracking_url").Where("id = ?", uint(id)).First(&order).Error; err != nil { + http.NotFound(w, r) + return + } + if order.TrackingURL == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, order.TrackingURL, http.StatusFound) +} diff --git a/api/routes/routes.go b/api/routes/routes.go index fd26eae..c162203 100644 --- a/api/routes/routes.go +++ b/api/routes/routes.go @@ -56,6 +56,7 @@ func SetupRoutes( // Short payment redirect and success page — no auth required. r.Get("/pay/{token}", handlers.PayRedirect) + r.Get("/t/{id}", handlers.TrackingRedirect) r.Get("/card-added", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") w.Write([]byte(`

Card added.

You can close this tab.

`)) diff --git a/pkg/tui/account_orders.go b/pkg/tui/account_orders.go index e9b622c..d14085b 100644 --- a/pkg/tui/account_orders.go +++ b/pkg/tui/account_orders.go @@ -196,7 +196,7 @@ func (m Model) buildOrderDetailView(order models.Order, _ int) string { b.WriteString("\n") } if order.TrackingURL != "" { - b.WriteString(hyperlink(dimStyle.Render(fmt.Sprintf(" View on %s ->", order.Carrier)), order.TrackingURL)) + b.WriteString(dimStyle.Render(fmt.Sprintf(" https://api.sshops.uk/t/%d", order.ID))) b.WriteString("\n") } } @@ -249,10 +249,3 @@ func (m Model) displayStyle(k models.DisplayKind) lipgloss.Style { return m.theme.TextHighlight() } -// hyperlink wraps label in OSC 8 escape sequences so supporting terminals -// render it as a clickable link to url. Uses BEL (\x07) as the string -// terminator — some renderers in the pipeline (bubbletea/lipgloss) handled -// the BEL form when they didn't handle the ST (\x1b\\) form. -func hyperlink(label, url string) string { - return fmt.Sprintf("\x1b]8;;%s\x07%s\x1b]8;;\x07", url, label) -}