mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 23:54:26 +01:00
203 lines
9.1 KiB
Plaintext
203 lines
9.1 KiB
Plaintext
@using Microsoft.AspNetCore.Routing
|
|
@using BTCPayServer.Plugins.TicketTailor
|
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@using NBitcoin
|
|
@model BTCPayServer.Plugins.TicketTailor.TicketTailorViewModel
|
|
|
|
@inject BTCPayServer.Security.ContentSecurityPolicies csp;
|
|
@{
|
|
|
|
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
|
csp.Add("script-src", $"'nonce-{nonce}'");
|
|
csp.AllowUnsafeHashes();
|
|
Layout = "_LayoutSimple";
|
|
var available = Model.Settings.BypassAvailabilityCheck || (Model.Event.Unavailable != "true" && Model.Event.TicketsAvailable == "true");
|
|
Model.Settings.SpecificTickets ??= new List<SpecificTicket>();
|
|
Context.Request.Query.TryGetValue("accessCode", out var accessCode);
|
|
}
|
|
<style>
|
|
hr:last-child{
|
|
display: none;
|
|
}
|
|
footer {
|
|
display: none;
|
|
}
|
|
|
|
@if (!string.IsNullOrEmpty(Model.Settings.CustomCSS))
|
|
{
|
|
@Safe.Raw(Model.Settings.CustomCSS)
|
|
}
|
|
|
|
</style>
|
|
<script nonce="@nonce">
|
|
document.addEventListener("DOMContentLoaded", ()=>{
|
|
const btn = document.querySelector("button[type='submit']");
|
|
document.querySelectorAll("input").forEach(value => value.addEventListener("change", (evt)=>{
|
|
|
|
if (!!evt.target.value && parseInt(evt.target.value) > 0){
|
|
btn.style.display = "block";
|
|
}
|
|
|
|
let total = 0;
|
|
document.querySelectorAll("[data-price]").forEach(value1 => {
|
|
if (!!value1.value){
|
|
const qty = parseInt(value1.value);
|
|
if (qty > 0){
|
|
|
|
const price = parseInt(value1.dataset.price);
|
|
total += price * qty;
|
|
}
|
|
}
|
|
});
|
|
|
|
btn.textContent = `Purchase for ${total}${@Safe.Json(@Model.Event.Currency)}`
|
|
}))
|
|
document.querySelector("form").addEventListener("submit", ()=>{
|
|
btn.setAttribute("disabled", "disabled");
|
|
})
|
|
})
|
|
</script>
|
|
<div class="container d-flex h-100">
|
|
<div class="justify-content-center mx-auto px-2 py-3 w-100 m-auto">
|
|
<partial name="_StatusMessage"/>
|
|
|
|
<h1 class="text-center ">@Model.Event.Title</h1>
|
|
<h2 class="text-muted mb-4 text-center ">@Model.Event.Start.Formatted - @Model.Event.EventEnd.Formatted</h2>
|
|
@if (Model.Settings.ShowDescription && !string.IsNullOrEmpty(Model.Event.Description))
|
|
{
|
|
<div class="row" id="ticket-tailor-description text-center ">
|
|
<div class="overflow-hidden col-12 ">@Safe.Raw(Model.Event.Description)</div>
|
|
</div>
|
|
}
|
|
<form method="post" asp-controller="TicketTailor" asp-action="Purchase" asp-antiforgery="false" asp-route-storeId="@Context.GetRouteValue("storeId")">
|
|
<input type="hidden" asp-for="AccessCode" value="@accessCode"/>
|
|
<div class="row g-2 justify-content-center mb-4" id="ticket-form-container">
|
|
<div class="col-sm-6 col-md-4">
|
|
<div class="form-floating">
|
|
<input type="text" minlength="3" asp-for="Name" class="form-control">
|
|
<label >Name</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-6 col-md-4">
|
|
<div class="form-floating">
|
|
<input required type="email" name="email" asp-for="Email" class="form-control"/>
|
|
<label >Email</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row g-2 justify-content-center mb-4">
|
|
<div class="col-sm-12 col-md-8">
|
|
|
|
@{
|
|
var index = -1;
|
|
|
|
foreach (var groupedTickets in Model.Event.TicketTypes.GroupBy(type => type.GroupId).OrderBy(groupedTickets => Model.Event.TicketGroups.FirstOrDefault(ticketGroup => ticketGroup.Id == groupedTickets.Key)?.SortOrder))
|
|
{
|
|
<div class="bg-tile w-100 p-4 mb-2">
|
|
|
|
|
|
|
|
@if (!string.IsNullOrEmpty(groupedTickets.Key))
|
|
{
|
|
var group = Model.Event.TicketGroups.First(ticketGroup => ticketGroup.Id == groupedTickets.Key);
|
|
<h4 class="mb-2 text-center ">@group.Name</h4>
|
|
}
|
|
@foreach (var item in groupedTickets)
|
|
{
|
|
var availableToShow = new[] {"on_sale", "sold_out", "unavailable"}.Contains(item.Status);
|
|
if (!string.IsNullOrEmpty(item.AccessCode) && item.AccessCode.Equals(accessCode, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
availableToShow = true;
|
|
}
|
|
var specific = false;
|
|
|
|
if (Model.Settings.SpecificTickets?.Any() is true)
|
|
{
|
|
var matched = Model.Settings.SpecificTickets.FirstOrDefault(ticket => ticket.TicketTypeId == item.Id);
|
|
if (matched is null || matched.Hidden)
|
|
{
|
|
continue;
|
|
}
|
|
if (matched.Price is not null)
|
|
{
|
|
item.Price = matched.Price.Value;
|
|
}
|
|
if (!string.IsNullOrEmpty(matched.Name))
|
|
{
|
|
item.Name = matched.Name;
|
|
}
|
|
if (!string.IsNullOrEmpty(matched.Description))
|
|
{
|
|
item.Description = matched.Description;
|
|
}
|
|
availableToShow = true;
|
|
specific = true;
|
|
}
|
|
if (!availableToShow)
|
|
{
|
|
continue;
|
|
}
|
|
index++;
|
|
|
|
<input type="hidden" asp-for="Items[index].TicketTypeId" value="@item.Id"/>
|
|
var purchasable = available && (specific || new[] {"on_sale", "locked"}.Contains(item.Status)) && item.Quantity > 0;
|
|
|
|
<div class="d-flex justify-content-between">
|
|
<div style="flex:2">
|
|
<h5 >@item.Name</h5>
|
|
<p>@Safe.Raw(item.Description)</p>
|
|
</div>
|
|
<div style="flex:1">
|
|
@if (purchasable)
|
|
{
|
|
<div class="input-group">
|
|
<div class="form-floating">
|
|
<input type="number"
|
|
class="form-control" asp-for="Items[index].Quantity" max="@item.MaxPerOrder"
|
|
min="0" data-price="@item.Price">
|
|
|
|
<label >Quantity</label>
|
|
</div>
|
|
|
|
<span class="input-group-text">
|
|
@(item.Price == 0 ? "FREE" : $"{item.Price} {Model.Event.Currency.ToUpperInvariant()}")
|
|
|
|
</span>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div >Unavailable</div>
|
|
}
|
|
|
|
|
|
</div>
|
|
</div>
|
|
<hr/>
|
|
}
|
|
|
|
</div>
|
|
}
|
|
|
|
}
|
|
|
|
|
|
</div>
|
|
<div class="col-sm-12 col-md-8">
|
|
<button class="btn btn-primary btn-lg m-auto" type="submit" style="display: none">Purchase</button>
|
|
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
|
|
<div class="row text-center">
|
|
<div class="col-12" id="fiat-page-link">
|
|
<a href="@Model.Event.Url">Back to fiat ticket page</a>
|
|
</div>
|
|
<div class="powered__by__btcpayserver col-12">
|
|
Powered by <a target="_blank" href="https://github.com/btcpayserver/btcpayserver" rel="noreferrer noopener">BTCPay Server</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> |