btcpayserver/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml

209 lines
12 KiB
Text

@model BTCPayServer.Models.InvoicingModels.InvoiceReceiptViewModel
@using BTCPayServer.Client
@using BTCPayServer.Client.Models
@using BTCPayServer.Components.QRCode
@using BTCPayServer.Services
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.TagHelpers
@using BTCPayServer.Payments
@inject BTCPayServerEnvironment Env
@inject DisplayFormatter DisplayFormatter
@{
Layout = null;
ViewData["Title"] = $"Receipt from {Model.StoreName}";
var isProcessing = Model.Status == InvoiceStatus.Processing;
var isFreeInvoice = (Model.Status == InvoiceStatus.New && Model.Amount == 0);
var isSettled = Model.Status == InvoiceStatus.Settled;
}
<!DOCTYPE html>
<html lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
<meta name="robots" content="noindex,nofollow">
@if (isProcessing)
{
<script type="text/javascript">
setTimeout(() => { window.location.reload(); }, 10000);
</script>
}else if (isFreeInvoice)
{
<script type="text/javascript">
setTimeout(() => { window.location.reload(); }, 2000);
</script>
}
<style>
#InvoiceSummary { gap: var(--btcpay-space-l); }
#PaymentDetails table tbody tr:first-child td { padding-top: 1rem; }
#PaymentDetails table tbody:not(:last-child) tr:last-child > th,td { padding-bottom: 1rem; }
#posData td > table:last-child { margin-bottom: 0 !important; }
#posData table > tbody > tr:first-child > td > h4 { margin-top: 0 !important; }
</style>
</head>
<body class="min-vh-100">
<div class="public-page-wrap flex-column">
<main class="flex-grow-1">
<div class="container" style="max-width:720px;">
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData) { { "Margin", "mb-4" } })"/>
<div class="d-flex flex-column justify-content-center gap-4">
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<div id="InvoiceSummary" class="bg-tile p-3 p-sm-4 rounded d-flex flex-wrap align-items-center justify-content-center">
@if (isProcessing)
{
<div class="lead text-center p-4 fw-semibold" id="invoice-processing">
The invoice has detected a payment but is still waiting to be settled.
</div>
}
else if (!isSettled)
{
<div class="lead text-center p-4 fw-semibold" id="invoice-unsettled">
The invoice is not settled.
</div>
}
else
{
if (Model.ReceiptOptions.ShowQR is true)
{
<vc:qr-code data="@Context.Request.GetCurrentUrl()"></vc:qr-code>
}
<dl class="d-flex flex-column gap-4 mb-0 flex-fill">
<div class="d-flex flex-column">
<div class="d-flex align-items-center justify-content-between">
<button type="button" class="btn btn-link p-0 d-print-none fw-semibold order-1" onclick="window.print()">
Print
</button>
<dd class="text-muted mb-0 fw-semibold">Amount Paid</dd>
</div>
<dt class="fs-2 mb-0 text-nowrap fw-semibold">@DisplayFormatter.Currency(Model.Amount, Model.Currency, DisplayFormatter.CurrencyFormat.Symbol)</dt>
</div>
<div class="d-flex flex-column">
<dd class="text-muted mb-0 fw-semibold">Date</dd>
<dt class="fs-5 mb-0 text-nowrap fw-semibold">@Model.Timestamp.ToBrowserDate()</dt>
</div>
@if (!string.IsNullOrEmpty(Model.OrderId))
{
<div class="d-flex flex-column">
<dd class="text-muted mb-0 fw-semibold">Order ID</dd>
<dt class="fs-5 mb-0 text-break fw-semibold">
@if (!string.IsNullOrEmpty(Model.OrderUrl))
{
<a href="@Model.OrderUrl" rel="noreferrer noopener" target="_blank">
@if (string.IsNullOrEmpty(Model.OrderId))
{
<span>View Order</span>
}
else
{
@Model.OrderId
}
</a>
}
else
{
<span>@Model.OrderId</span>
}
</dt>
</div>
}
</dl>
}
</div>
@if (isProcessing)
{
<small class="d-block text-muted text-center px-4">This page will refresh periodically until the invoice is settled.</small>
}
else if (isSettled)
{
if (Model.Payments?.Any() is true)
{
<div id="PaymentDetails" class="bg-tile p-3 p-sm-4 rounded">
<h2 class="h4 mb-3">Payment Details</h2>
<div class="table-responsive my-0 d-print-none">
<table class="table table-borderless my-0">
<thead>
<tr>
<th class="fw-normal text-secondary">Date</th>
<th class="fw-normal text-secondary">Payment</th>
<th class="fw-normal text-secondary text-end">Paid</th>
<th class="fw-normal text-secondary text-end">Rate</th>
</tr>
</thead>
@foreach (var payment in Model.Payments)
{
<tbody>
<tr>
<td class="text-nowrap">@payment.ReceivedDate.ToBrowserDate()</td>
<td class="text-nowrap">@payment.Amount @payment.PaymentMethod</td>
<td class="text-end text-nowrap">@payment.PaidFormatted</td>
<td class="text-end text-nowrap">@payment.RateFormatted</td>
</tr>
@if (!string.IsNullOrEmpty(payment.Destination))
{
<tr>
<th class="fw-normal text-nowrap text-secondary">
Destination
</th>
<td class="fw-normal" colspan="3">
<vc:truncate-center text="@payment.Destination" classes="truncate-center-id" />
</td>
</tr>
}
@if (!string.IsNullOrEmpty(payment.PaymentProof))
{
<tr>
<th class="fw-normal text-nowrap text-secondary">
Payment Proof
</th>
<td class="fw-normal" colspan="3">
<vc:truncate-center text="@payment.PaymentProof" link="@payment.Link" classes="truncate-center-id" />
</td>
</tr>
}
</tbody>
}
</table>
</div>
<div class="d-none d-print-block">
@foreach (var payment in Model.Payments)
{
<div class="mb-4">
<strong>@payment.PaidFormatted</strong> = @payment.Amount @payment.PaymentMethod, Rate: @payment.RateFormatted
@if (!string.IsNullOrEmpty(payment.PaymentProof))
{
<div>Proof: @payment.PaymentProof</div>
}
</div>
}
</div>
</div>
}
if (Model.AdditionalData?.Any() is true)
{
<div id="AdditionalData" class="bg-tile p-3 p-sm-4 rounded">
<h2 class="h4 mb-3">Additional Data</h2>
<div class="table-responsive my-0">
<partial name="PosData" model="(Model.AdditionalData, 1)"/>
</div>
</div>
}
}
</div>
</div>
</main>
<footer class="store-footer">
<p permission="@Policies.CanViewInvoices" class="d-print-none">
<a asp-action="Invoice" asp-route-invoiceId="@Model.InvoiceId">
Admin details
</a>
</p>
<a class="store-powered-by" href="https://btcpayserver.org" target="_blank" rel="noreferrer noopener">
Powered by <partial name="_StoreFooterLogo" />
</a>
</footer>
</div>
<partial name="LayoutFoot"/>
</body>
</html>