I have put too much code into the same files. Also, I put everything into the same package: main. This package is only meant for executables. Therefore, I have refactored my code to use multiple packages. These packages also guarantee separation of concerns since Golang doesn't allow cyclic imports.
113 lines
4.0 KiB
HTML
113 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
|
|
<head>
|
|
<title>delphi.market</title>
|
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
|
<link rel="manifest" href="/site.webmanifest" />
|
|
<link rel="stylesheet" href="/index.css" />
|
|
<link rel="stylesheet" href="/market.css" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta name="theme-color" content="#091833" />
|
|
{{ if eq .ENV "development" }}
|
|
<script defer src="/hotreload.js"></script>
|
|
{{ end }}
|
|
</head>
|
|
|
|
<body>
|
|
<header class="flex flex-row text-center justify-center pt-1">
|
|
<nav>
|
|
<a href="/">home</a>
|
|
{{ if .session }}
|
|
<a href='/user'>user</a>
|
|
{{ else }} <a href="/login">login</a> {{ end }}
|
|
</nav>
|
|
</header>
|
|
<div class="container flex flex-column text-center justify-center">
|
|
<code>
|
|
<strong>
|
|
<pre>
|
|
_ _ ___ ____
|
|
| || | / _ \___ \
|
|
| || |_| | | |__) |
|
|
|__ _| |_| / __/
|
|
|_| \___/_____|</pre>
|
|
</strong>
|
|
</code>
|
|
<div class="font-mono mb-1">
|
|
<div class="mb-1">Payment Required</div>
|
|
<div id="status" hidden>
|
|
<div id="status-label"></div>
|
|
<div id="countdown" hidden>Redirecting in 3 ...</div>
|
|
</div>
|
|
</div>
|
|
<div id="qr">
|
|
<a href="lightning:{{.lnurl}}">
|
|
<img class="m-auto mb-1" src="data:image/png;base64,{{.qr}}" width="100%" />
|
|
</a>
|
|
<div class="font-mono word-wrap mb-1">{{.lnurl}}</div>
|
|
<details class="font-mono mb-1 align-left">
|
|
<summary>details</summary>
|
|
<div>id: {{.invoice.Id}}</div>
|
|
<div>amount: {{div .invoice.Msats 1000}} sats</div>
|
|
<div>created: {{.invoice.CreatedAt}}</div>
|
|
<div>expiry : {{.invoice.ExpiresAt}}</div>
|
|
<div class="word-wrap">hash: {{.invoice.Hash}}</div>
|
|
</details>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
<script>
|
|
const statusElement = document.querySelector("#status")
|
|
const label = document.querySelector("#status-label")
|
|
const status = "{{.status}}"
|
|
const redirectUrl = "{{.redirectURL}}"
|
|
function poll() {
|
|
const invoiceId = "{{.invoice.Id}}"
|
|
const countdown = document.querySelector("#countdown")
|
|
const redirect = () => {
|
|
clearInterval(interval)
|
|
countdown.removeAttribute("hidden")
|
|
let timer = 2
|
|
const redirect = setInterval(() => {
|
|
countdown.textContent = `Redirecting in ${timer--} ...`
|
|
if (timer === -1) {
|
|
window.location.href = redirectUrl;
|
|
}
|
|
}, 1000)
|
|
}
|
|
const interval = setInterval(async () => {
|
|
const body = await fetch(`/api/invoice/${invoiceId}`)
|
|
.then((r) => r.json())
|
|
.catch(console.error)
|
|
if (body.ConfirmedAt) {
|
|
statusElement.removeAttribute("hidden")
|
|
statusElement.classList.add("yes")
|
|
label.textContent = "Paid"
|
|
if (redirectUrl) redirect()
|
|
} else if (new Date(body.ExpiresAt) <= new Date()) {
|
|
statusElement.removeAttribute("hidden")
|
|
statusElement.classList.add("no")
|
|
label.textContent = "Expired"
|
|
if (redirectUrl) redirect()
|
|
}
|
|
}, 1000)
|
|
}
|
|
if (status) {
|
|
console.log(status)
|
|
statusElement.removeAttribute("hidden")
|
|
label.textContent = status
|
|
if (status === "Paid") {
|
|
statusElement.classList.add("yes")
|
|
}
|
|
else if (status === "Expired") {
|
|
statusElement.classList.add("no")
|
|
}
|
|
}
|
|
else poll()
|
|
</script>
|
|
|
|
</html> |