283 lines
11 KiB
Plaintext
283 lines
11 KiB
Plaintext
@page "{id:int}"
|
|
@using AfRApay.Web.Backend.Database
|
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@using Microsoft.EntityFrameworkCore
|
|
@using System.Globalization
|
|
@using AfRApay.Web.Backend.Database.Tables
|
|
@model EditUserModel
|
|
@{
|
|
ViewData["Title"] = "Edit User";
|
|
if (Request.Method == "POST" && Request.Form["action"] == "delete") {
|
|
return;
|
|
}
|
|
var db = new DatabaseContext();
|
|
var user = db.Users.First(p => p.Id == int.Parse(RouteData.Values["id"]!.ToString()!));
|
|
var cards = db.Cards.Include(p => p.User).Where(p => p.User == user);
|
|
var formattedBalance = (user.Balance / 100m).ToString(CultureInfo.InvariantCulture);
|
|
|
|
if (user.Balance % 10 == 0) {
|
|
formattedBalance += formattedBalance.Contains(".") ? "0" : ".00";
|
|
}
|
|
|
|
var linkFlag = db.Config.FirstOrDefault(p => p.Name == "link");
|
|
var lTimeFlag = db.Config.FirstOrDefault(p => p.Name == "lTime");
|
|
var linkActive = !string.IsNullOrWhiteSpace(linkFlag?.Value) && linkFlag.Value == user.Id.ToString() && !string.IsNullOrWhiteSpace(lTimeFlag?.Value) && DateTime.UtcNow - DateTime.Parse(lTimeFlag.Value) < TimeSpan.FromMinutes(5);
|
|
}
|
|
|
|
@section HeaderNavAddLocation {
|
|
<span class="navbar-text">
|
|
Edit User
|
|
</span>
|
|
}
|
|
|
|
@section Scripts {
|
|
<script src="/js/idle-timer.min.js"></script>
|
|
|
|
@if (linkActive) {
|
|
<script>
|
|
$(() => {
|
|
setInterval(() => {
|
|
fetch(document.location).then(res => {
|
|
res.text().then(text => {
|
|
let dummyDOM = $('<div></div>');
|
|
dummyDOM.html(text);
|
|
let newTableContents = $('#cards>', dummyDOM);
|
|
$('#cards').html(newTableContents);
|
|
})
|
|
});
|
|
}, 1000);
|
|
});
|
|
</script>
|
|
}
|
|
else {
|
|
<script>
|
|
$(() => {
|
|
$.idleTimer(30000);
|
|
});
|
|
|
|
$(document).on("idle.idleTimer", () => {
|
|
window.location.replace('/');
|
|
});
|
|
</script>
|
|
}
|
|
}
|
|
|
|
<form id="change_user" method="POST">
|
|
<div class="d-flex flex-row align-items-center my-3">
|
|
<h3>Account</h3>
|
|
<button type="button" class="btn btn-lg btn-danger mx-3" name="action" data-bs-toggle="modal" data-bs-target="#deleteConfirmModal">Delete</button> <!-- Calls the modal dialog to confirm user deletion -->
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="nickname" class="form-label">Nickname</label>
|
|
<input type="text" maxlength="10" class="form-control" id="nickname" name="nickname" value="@user.Nickname" required>
|
|
</div>
|
|
<div class="my-3">
|
|
<label for="balance" class="form-label">Balance (€)</label>
|
|
<input type="number" max="999.50" min="-99.50" step=".50" class="form-control" id="balance" name="balance" value="@formattedBalance" required>
|
|
</div>
|
|
|
|
<div class="d-flex">
|
|
<button type="submit" class="btn btn-lg m-1 btn-primary" name="action" value="save">Save</button>
|
|
<div class="container p-0">
|
|
<div class="row row-cols-2 row-cols-lg-auto justify-content-center g-0">
|
|
<div class="col"><button type="submit" class="btn float-end transact-btn btn-danger" name="amount" value="-150">-1.50€</button></div>
|
|
<div class="col"><button type="submit" class="btn transact-btn btn-danger" name="amount" value="-200">-2€</button></div>
|
|
<div class="col"><button type="submit" class="btn float-end transact-btn btn-danger" name="amount" value="-500">-5€</button></div>
|
|
<div class="col"><button type="submit" class="btn transact-btn btn-danger" name="amount" value="-1000">-10€</button></div>
|
|
</div>
|
|
</div>
|
|
<div class="container p-0">
|
|
<div class="row row-cols-2 row-cols-lg-auto justify-content-center g-0">
|
|
<div class="col"><button type="submit" class="btn float-end transact-btn btn-success" name="amount" value="150">+1.50€</button></div>
|
|
<div class="col"><button type="submit" class="btn transact-btn btn-success" name="amount" value="200">+2€</button></div>
|
|
<div class="col"><button type="submit" class="btn float-end transact-btn btn-success" name="amount" value="500">+5€</button></div>
|
|
<div class="col"><button type="submit" class="btn transact-btn btn-success" name="amount" value="1000">+10€</button></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Modal dialog to confirm user deletion -->
|
|
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-labelledby="deleteConfirmModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteConfirmModalLabel">Delete user @user.Nickname?</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
Are you sure you want to delete this user?<br>This cannot be undone.
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" form="change_user" class="btn btn-lg btn-danger" name="action" value="delete">Delete User</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<br/>
|
|
<h3 class="text-center">Cards</h3>
|
|
@{
|
|
async Task RenderCard(string cardHolder, string cardNumber = "Awooo!", string expDate = "01/2038", Card.CardType cardType = Card.CardType.Unknown, EditUserModel.CardDisplayType displayType = EditUserModel.CardDisplayType.Normal) {
|
|
var cardTypeClasses = displayType switch {
|
|
EditUserModel.CardDisplayType.Normal => "fake-card",
|
|
EditUserModel.CardDisplayType.LinkPlaceholder => "fake-card ghost-card",
|
|
EditUserModel.CardDisplayType.DeletionConfirmation => "fake-card",
|
|
_ => throw new ArgumentOutOfRangeException(nameof(displayType), displayType, null)};
|
|
|
|
var blurClasses = displayType == EditUserModel.CardDisplayType.Normal ? " blur-true m-2" : "m-2";
|
|
|
|
<div class="fake-card-wrapper @blurClasses">
|
|
@if (displayType == EditUserModel.CardDisplayType.Normal) {
|
|
<form id="@cardNumber" method="POST">
|
|
<input type="hidden" name="cardId" value="@cardNumber">
|
|
<button type="button" class="btn btn-danger btn-lg hover-button" data-bs-toggle="modal" data-bs-target="#delete_card_@(cardNumber)_modal">Delete</button>
|
|
</form>
|
|
}
|
|
else if (displayType == EditUserModel.CardDisplayType.LinkPlaceholder) {
|
|
if (linkActive) {
|
|
<button class="btn btn-secondary btn-lg link-card-button-in-progress">Link in progress</button>
|
|
}
|
|
else {
|
|
<form method="POST">
|
|
<input type="hidden" name="userId" value="@user.Id">
|
|
<button type="submit" class="btn btn-success btn-lg link-card-button" name="action" value="linkCard">Link Card</button>
|
|
</form>
|
|
}
|
|
}
|
|
<div class="@cardTypeClasses">
|
|
<div class="face-card front">
|
|
<div class="chip">
|
|
<div>
|
|
<div>
|
|
<div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@if (cardNumber.Length < 12) {
|
|
if (cardType == Card.CardType.Rfid125KhzGeneric) {
|
|
<h2 class="card-number">
|
|
<span class="text-blur">0000000</span>@cardNumber[^3..]
|
|
</h2>
|
|
}
|
|
else {
|
|
<h2 class="card-number">@cardNumber</h2>
|
|
}
|
|
}
|
|
else {
|
|
<h2 class="card-number-long">@cardNumber</h2>
|
|
}
|
|
<h3 class="card-holder">@cardHolder</h3>
|
|
<span class="validity">
|
|
<span class="small">VALID<br>THRU</span>
|
|
<span>@expDate</span>
|
|
</span>
|
|
|
|
@switch (cardType) {
|
|
case Card.CardType.Rfid125KhzGeneric:
|
|
<div class="fake-card-logo-top-rfid">
|
|
<img src="/img/rfid.png" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.NfcGeneric:
|
|
<div class="fake-card-logo-top-nfc">
|
|
<img src="/img/nfc.png" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.FeliCaGeneric:
|
|
<div class="fake-card-logo-top-felica">
|
|
<img src="/img/felica.png" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.NfcMifareClassic:
|
|
<div class="fake-card-logo-top-mifare">
|
|
<img src="/img/mifare.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.NfcTflOyster:
|
|
<div class="fake-card-logo-top-oyster">
|
|
<img src="/img/oyster.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.NfcOvChipkaart:
|
|
<div class="fake-card-logo-top-ovc">
|
|
<img src="/img/ovc.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.NfcItso:
|
|
<div class="fake-card-logo-top-itso">
|
|
<img src="/img/itso.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.NfcContactless:
|
|
<div class="fake-card-logo-top-contactless">
|
|
<img src="/img/contactless.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.FeliCaSuica:
|
|
<div class="fake-card-logo-top-suica">
|
|
<img src="/img/suica.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.FeliCaPasmo:
|
|
<div class="fake-card-logo-top-pasmo">
|
|
<img src="/img/pasmo.svg" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.FeliCaApplePay:
|
|
<div class="fake-card-logo-top-apay">
|
|
<img src="/img/apay.svg" class="fake-card-logo-inner" alt="">
|
|
<img src="/img/felica.png" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
break;
|
|
case Card.CardType.Unknown:
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException(nameof(cardType), cardType, null);
|
|
}
|
|
<div class="fake-card-logo-bottom-matecard">
|
|
<img src="/img/matecard.png" class="fake-card-logo-inner" alt="">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
@{
|
|
async Task RenderCardModal(string cardHolder, string cardNumber, Card.CardType cardType = Card.CardType.Unknown) {
|
|
<div class="modal fade" id="delete_card_@(cardNumber)_modal" tabindex="-1" aria-labelledby="delete_card_@(cardNumber)_modal_label" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="delete_card_@(cardNumber)_modal_label">Delete this card?</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body d-flex justify-content-center">
|
|
@{
|
|
await RenderCard(cardHolder, cardNumber, cardType: cardType, displayType: EditUserModel.CardDisplayType.DeletionConfirmation);
|
|
}
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" form="@cardNumber" class="btn btn-danger btn-lg" name="action" value="deleteCard">Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
<div class="row justify-content-center" id="cards">
|
|
@{
|
|
foreach (var card in cards) {
|
|
await RenderCard(user.Nickname, card.Id, cardType: card.Type);
|
|
await RenderCardModal(user.Nickname, card.Id, cardType: card.Type);
|
|
}
|
|
|
|
await RenderCard(user.Nickname, displayType: EditUserModel.CardDisplayType.LinkPlaceholder);
|
|
}
|
|
</div>
|