From 6d7cd2573dbabae0b0ac526a0da87964fae2b352 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 26 Nov 2023 22:07:56 +0100 Subject: [PATCH] Show user invoices --- db/invoice.go | 27 ++++++++++++++ db/types.go | 1 + server/router/handler/invoice.go | 15 ++++++++ server/router/router.go | 3 ++ vue/package.json | 1 + vue/src/components/UserHome.vue | 18 ++++++++++ vue/src/components/UserInvoices.vue | 56 +++++++++++++++++++++++++++++ vue/src/main.js | 9 ++++- vue/src/views/UserView.vue | 31 ++++++++-------- vue/yarn.lock | 5 +++ 10 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 vue/src/components/UserHome.vue create mode 100644 vue/src/components/UserInvoices.vue diff --git a/db/invoice.go b/db/invoice.go index 82d60db..e2c9bae 100644 --- a/db/invoice.go +++ b/db/invoice.go @@ -70,6 +70,33 @@ func (db *DB) FetchInvoices(where *FetchInvoicesWhere, invoices *[]Invoice) erro return nil } +func (db *DB) FetchUserInvoices(pubkey string, invoices *[]Invoice) error { + var ( + rows *sql.Rows + invoice Invoice + err error + ) + var ( + query = "" + + "SELECT id, pubkey, msats, preimage, hash, bolt11, created_at, expires_at, confirmed_at, held_since, COALESCE(description, ''), " + + "CASE WHEN confirmed_at IS NOT NULL THEN 'PAID' WHEN expires_at < CURRENT_TIMESTAMP THEN 'EXPIRED' ELSE 'WAITING' END AS status " + + "FROM invoices " + + "WHERE pubkey = $1 " + + "ORDER BY created_at DESC" + ) + if rows, err = db.Query(query, pubkey); err != nil { + return err + } + defer rows.Close() + for rows.Next() { + rows.Scan( + &invoice.Id, &invoice.Pubkey, &invoice.Msats, &invoice.Preimage, &invoice.Hash, + &invoice.PaymentRequest, &invoice.CreatedAt, &invoice.ExpiresAt, &invoice.ConfirmedAt, &invoice.HeldSince, &invoice.Description, &invoice.Status) + *invoices = append(*invoices, invoice) + } + return nil +} + func (db *DB) ConfirmInvoice(hash string, confirmedAt time.Time, msatsReceived int) error { if _, err := db.Exec("UPDATE invoices SET confirmed_at = $2, msats_received = $3 WHERE hash = $1", hash, confirmedAt, msatsReceived); err != nil { return err diff --git a/db/types.go b/db/types.go index e0d817e..fa8cd81 100644 --- a/db/types.go +++ b/db/types.go @@ -47,6 +47,7 @@ type ( ConfirmedAt null.Time HeldSince null.Time Description string + Status string } Order struct { Id UUID diff --git a/server/router/handler/invoice.go b/server/router/handler/invoice.go index 45e888d..f9d1073 100644 --- a/server/router/handler/invoice.go +++ b/server/router/handler/invoice.go @@ -93,3 +93,18 @@ func HandleInvoice(sc context.ServerContext) echo.HandlerFunc { return sc.Render(c, http.StatusOK, "invoice.html", data) } } + +func HandleInvoices(sc context.ServerContext) echo.HandlerFunc { + return func(c echo.Context) error { + var ( + u db.User + invoices []db.Invoice + err error + ) + u = c.Get("session").(db.User) + if err = sc.Db.FetchUserInvoices(u.Pubkey, &invoices); err != nil { + return err + } + return c.JSON(http.StatusOK, invoices) + } +} diff --git a/server/router/router.go b/server/router/router.go index 25a3b8b..bbd9569 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -57,6 +57,9 @@ func addBackendRoutes(e *echo.Echo, sc ServerContext) { GET(e, sc, "/api/invoice/:id", handler.HandleInvoiceStatus, middleware.SessionGuard) + GET(e, sc, "/api/invoices", + handler.HandleInvoices, + middleware.SessionGuard) } func GET(e *echo.Echo, sc ServerContext, path string, scF HandlerFunc, scM ...MiddlewareFunc) *echo.Route { diff --git a/vue/package.json b/vue/package.json index 43f3368..260bc1c 100644 --- a/vue/package.json +++ b/vue/package.json @@ -12,6 +12,7 @@ "core-js": "^3.8.3", "pinia": "^2.1.7", "register-service-worker": "^1.7.2", + "s-ago": "^2.2.0", "vite": "^4.5.0", "vue": "^3.2.13", "vue-router": "4" diff --git a/vue/src/components/UserHome.vue b/vue/src/components/UserHome.vue new file mode 100644 index 0000000..2fe2f69 --- /dev/null +++ b/vue/src/components/UserHome.vue @@ -0,0 +1,18 @@ + + + diff --git a/vue/src/components/UserInvoices.vue b/vue/src/components/UserInvoices.vue new file mode 100644 index 0000000..11f2d59 --- /dev/null +++ b/vue/src/components/UserInvoices.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/vue/src/main.js b/vue/src/main.js index 3fa9819..948895e 100644 --- a/vue/src/main.js +++ b/vue/src/main.js @@ -10,6 +10,8 @@ import LoginView from '@/views/LoginView' import UserView from '@/views/UserView' import MarketView from '@/views/MarketView' import InvoiceView from '@/views/InvoiceView' +import UserHome from '@/components/UserHome' +import UserInvoices from '@/components/UserInvoices' const routes = [ { @@ -19,7 +21,12 @@ const routes = [ path: '/login', component: LoginView }, { - path: '/user', component: UserView + path: '/user', + component: UserView, + children: [ + { path: '', name: 'user', component: UserHome }, + { path: 'invoices', name: 'invoices', component: UserInvoices } + ] }, { path: '/market/:id', component: MarketView diff --git a/vue/src/views/UserView.vue b/vue/src/views/UserView.vue index 73201f6..2521a67 100644 --- a/vue/src/views/UserView.vue +++ b/vue/src/views/UserView.vue @@ -9,21 +9,24 @@ \__,_|___/\___|_| -
-
authenticated as {{ session.pubkey.slice(0, 8) }}
- -
+
+ +
+ + + - +nav>a { + margin: 0 3px; +} + diff --git a/vue/yarn.lock b/vue/yarn.lock index f20a5cf..bbd5f2a 100644 --- a/vue/yarn.lock +++ b/vue/yarn.lock @@ -4012,6 +4012,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +s-ago@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/s-ago/-/s-ago-2.2.0.tgz#4143a9d0176b3100dcf649c78e8a1ec8a59b1312" + integrity sha512-t6Q/aFCCJSBf5UUkR/WH0mDHX8EGm2IBQ7nQLobVLsdxOlkryYMbOlwu2D4Cf7jPUp0v1LhfPgvIZNoi9k8lUA== + safe-array-concat@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c"