diff --git a/src/api.ts b/src/api.ts index 5225b2d..37222bd 100644 --- a/src/api.ts +++ b/src/api.ts @@ -210,7 +210,7 @@ export class LNVpsApi { constructor( readonly url: string, readonly publisher: EventPublisher | undefined, - ) { } + ) {} async getAccount() { const { data } = await this.#handleResponse>( diff --git a/src/pages/vm-billing.tsx b/src/pages/vm-billing.tsx index 9fbcd39..f5405a3 100644 --- a/src/pages/vm-billing.tsx +++ b/src/pages/vm-billing.tsx @@ -8,6 +8,9 @@ import CostLabel, { CostAmount } from "../components/cost"; import { RevolutPayWidget } from "../components/revolut"; import { timeValue } from "../utils"; import { Icon } from "../components/icon"; +import { ApiUrl } from "../const"; +import QrCode from "../components/qr"; +import { LNURL } from "@snort/shared"; export function VmBillingPage() { const location = useLocation() as { state?: VmInstance }; @@ -48,7 +51,29 @@ export function VmBillingPage() { const className = "flex items-center justify-between px-3 py-2 bg-neutral-900 rounded-xl cursor-pointer"; + const nameRow = (v: PaymentMethod) => { + return ( +
+ {v.name.toUpperCase()} ({v.currencies.join(",")}) +
+ ); + }; switch (v.name) { + case "lnurl": { + const addr = v.metadata?.["address"]; + return ( +
{ + setMethod(v); + }} + > + {nameRow(v)} +
{addr}
+
+ ); + } case "lightning": { return (
-
- {v.name.toUpperCase()} ({v.currencies.join(",")}) -
+ {nameRow(v)}
Pay Now
); @@ -71,9 +94,7 @@ export function VmBillingPage() { if (!pkey) return Missing Revolut pubkey; return (
-
- {v.name.toUpperCase()} ({v.currencies.join(",")}) -
+ {nameRow(v)} {state && ( @@ -157,7 +188,23 @@ export function VmBillingPage() { {methods && !method && ( <>
Payment Method:
- {methods.map((v) => paymentMethod(v))} + {[lnurl, ...methods].map((v) => paymentMethod(v))} + + )} + {method?.name === "lnurl" && ( + <> +
+ +
+ {lud16} +
+
)} {payment && ( @@ -172,35 +219,69 @@ export function VmBillingPage() { /> )} -
Payment History
- - - - - - - - - - - - {payments.sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime()) - .map(a => - - - - - - )} - -
DateAmountTimeStatus
{new Date(a.created).toLocaleString()}{timeValue(a.time)}{a.is_paid ? "Paid" : (new Date(a.expires) <= new Date() ? "Expired" : "Unpaid")} - {a.is_paid &&
{ - const l = await login?.api.invoiceLink(a.id); - window.open(l, "_blank"); - }}> - -
} -
+ {!methods && ( + <> +
Payment History
+ + + + + + + + + + + + {payments + .sort( + (a, b) => + new Date(b.created).getTime() - + new Date(a.created).getTime(), + ) + .map((a) => ( + + + + + + + + ))} + +
DateAmountTimeStatus
+ {new Date(a.created).toLocaleString()} + + + {timeValue(a.time)} + {a.is_paid + ? "Paid" + : new Date(a.expires) <= new Date() + ? "Expired" + : "Unpaid"} + + {a.is_paid && ( +
{ + const l = await login?.api.invoiceLink(a.id); + window.open(l, "_blank"); + }} + > + +
+ )} +
+ + )}
); } diff --git a/src/pages/vm.tsx b/src/pages/vm.tsx index 0447d8f..21b22b5 100644 --- a/src/pages/vm.tsx +++ b/src/pages/vm.tsx @@ -59,9 +59,10 @@ export default function VmPage() { ); } + const hasNoIps = (state?.ip_assignments?.length ?? 0) === 0; function networkInfo() { if (!state) return; - if ((state.ip_assignments?.length ?? 0) === 0) { + if (hasNoIps) { return
No IP's assigned
; } return <>{state.ip_assignments?.map((i) => ipRow(i, true))}; @@ -86,9 +87,7 @@ export default function VmPage() { return (
- - < Back - + < Back
Network:
@@ -102,12 +101,14 @@ export default function VmPage() {
setEditKey(true)} /> -
-
Login:
-
-            ssh {state.image.default_username}@{bestHost()}
-          
-
+ {!hasNoIps && ( +
+
Login:
+
+              ssh {state.image.default_username}@{bestHost()}
+            
+
+ )}
diff --git a/src/utils.ts b/src/utils.ts index eecd6b9..072399a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -64,11 +64,16 @@ export function timeValue(n: number): string { if (n >= 3600) { const hours = Math.floor(n / 3600); const minutes = Math.floor((n % 3600) / 60); - return hours + " hr" + (hours !== 1 ? "s" : "") + (minutes > 0 ? " " + minutes + " min" + (minutes !== 1 ? "s" : "") : ""); + return ( + hours + + " hr" + + (hours !== 1 ? "s" : "") + + (minutes > 0 ? " " + minutes + " min" + (minutes !== 1 ? "s" : "") : "") + ); } if (n >= 60) { const minutes = Math.floor(n / 60); return minutes + " min" + (minutes !== 1 ? "s" : ""); } return n + " sec" + (n !== 1 ? "s" : ""); -} \ No newline at end of file +}