Cashier side feature and UI update
-- added option to decline top-up requests by cashier with option to specify reason -- separated pending and processed requests
This commit is contained in:
parent
357c7d35f8
commit
a465104276
@ -229,6 +229,11 @@ sm-form {
|
||||
|
||||
sm-select {
|
||||
--padding: 0.8rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
sm-option {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
strip-select {
|
||||
@ -308,6 +313,10 @@ ul {
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
.gap-0-3 {
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.gap-0-5 {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -210,6 +210,10 @@ sm-form {
|
||||
}
|
||||
sm-select {
|
||||
--padding: 0.8rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
sm-option {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
strip-select {
|
||||
--gap: 0;
|
||||
@ -275,6 +279,9 @@ ul {
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
.gap-0-3 {
|
||||
gap: 0.3rem;
|
||||
}
|
||||
.gap-0-5 {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
79
index.html
79
index.html
@ -301,10 +301,26 @@
|
||||
</div>
|
||||
</div>
|
||||
<section id="cashier" class=" grid gap-1 hide admin-element">
|
||||
<h4>Requests</h4>
|
||||
<ul id="cashier_request_list" class="observe-empty-state"></ul>
|
||||
<div class="empty-state">
|
||||
<p>No requests to process</p>
|
||||
<div class="flex align-center space-between">
|
||||
<h4>Requests</h4>
|
||||
<strip-select id="cashier_requests_selector">
|
||||
<strip-option value="pending" selected>Pending</strip-option>
|
||||
<strip-option value="processed">Processed</strip-option>
|
||||
</strip-select>
|
||||
</div>
|
||||
<div id="cashier_requests_wrapper">
|
||||
<div>
|
||||
<ul id="cashier_pending_request_list" class="observe-empty-state"></ul>
|
||||
<div class="empty-state">
|
||||
<p>No requests to process</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hide">
|
||||
<ul id="cashier_processed_request_list" class="observe-empty-state"></ul>
|
||||
<div class="empty-state">
|
||||
<p>No requests to process</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@ -350,10 +366,11 @@
|
||||
</div>
|
||||
<div id="wallet_history_wrapper" class="grid gap-1-5">
|
||||
<div class="hide grid gap-1">
|
||||
<p>Pending transactions</p>
|
||||
<h4>Pending</h4>
|
||||
<ul id="pending_wallet_transactions" class="grid gap-0-5"></ul>
|
||||
</div>
|
||||
<div class="grid gap-1">
|
||||
<h4>Processed</h4>
|
||||
<ul id="wallet_history" class="observe-empty-state grid gap-0-5"></ul>
|
||||
<div class=" empty-state gap-1 justify-center text-center">
|
||||
<p>No transactions</p>
|
||||
@ -493,7 +510,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<a id="transaction__link" target="_blank" rel="noopener noreferrer">See transaction on blockchain</a>
|
||||
<div id="transaction__note" class="hide flex align-center"></div>
|
||||
<p id="transaction__note" class="hide flex flex-direction-column gap-0-5"></p>
|
||||
</div>
|
||||
<section id="settings" class="inner-page hide">
|
||||
<div class="page__header">
|
||||
@ -834,7 +851,10 @@
|
||||
</div>
|
||||
<sm-copy id="topup_wallet__upi_id" style="font-weight: 700;"></sm-copy>
|
||||
</div>
|
||||
<p>After sending money, please enter the transaction ID of completed transaction.</p>
|
||||
<p>
|
||||
After sending money, please enter the transaction ID of completed transaction. <br>
|
||||
* <strong>PhonePe</strong> users please enter <strong>UTR ID</strong> instead of transaction ID
|
||||
</p>
|
||||
<sm-input id="topup_wallet__txid" minlength="12" maxlength="12"
|
||||
error-text="Please enter UPI transaction ID of money you sent to continue."
|
||||
placeholder="UPI transaction ID" autofocus animate required></sm-input>
|
||||
@ -1039,6 +1059,51 @@
|
||||
</div>
|
||||
</sm-popup>
|
||||
|
||||
<!-- Cashier popups -->
|
||||
<sm-popup id="confirm_topup_popup">
|
||||
<header slot="header" class="popup__header">
|
||||
<button class="popup__header__close justify-self-start" onclick="hidePopup()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||
fill="#000000">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path
|
||||
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
||||
</svg>
|
||||
</button>
|
||||
<h4>Confirm top-up</h4>
|
||||
</header>
|
||||
<div id="confirm_topup_wrapper">
|
||||
<div class="grid gap-1-5">
|
||||
<div class="grid gap-0-5">
|
||||
<p>
|
||||
Check if you have received UPI payment
|
||||
</p>
|
||||
<b id="top_up_amount" style="font-size: 1.5rem;"></b>
|
||||
<sm-copy id="top_up_txid"></sm-copy>
|
||||
</div>
|
||||
<div class="flex justify-right gap-0-3">
|
||||
<button class="button" onclick="showChildElement('confirm_topup_wrapper', 1)">Decline</button>
|
||||
<button class="button" onclick="confirmTopUp()">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-direction-column gap-1-5 hide" style="height: 24rem;">
|
||||
<div class="grid gap-0-3">
|
||||
<p>Select reason</p>
|
||||
<sm-select id="top_up__reason_selector">
|
||||
<sm-option value="1001">Invalid transaction ID</sm-option>
|
||||
<sm-option value="1002">Amount doesn't match</sm-option>
|
||||
<sm-option value="other">Other</sm-option>
|
||||
</sm-select>
|
||||
</div>
|
||||
<div class="grid gap-0-3 hide">
|
||||
<p>Describe reason</p>
|
||||
<sm-textarea id="top_up__specified_reason" rows="4"></sm-textarea>
|
||||
</div>
|
||||
<button class="button justify-right" style="margin-top: auto;" onclick="declineTopUp()">Decline</button>
|
||||
</div>
|
||||
</div>
|
||||
</sm-popup>
|
||||
|
||||
<!-- templates -->
|
||||
<template id="saved_id_template">
|
||||
<li class="saved-id grid interact" tabindex="0">
|
||||
|
||||
@ -687,6 +687,204 @@ customElements.define('sm-input',
|
||||
this.clearBtn.removeEventListener('click', this.clear);
|
||||
}
|
||||
})
|
||||
|
||||
const smTextarea = document.createElement('template')
|
||||
smTextarea.innerHTML = `
|
||||
<style>
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
::-moz-focus-inner{
|
||||
border: none;
|
||||
}
|
||||
.hide{
|
||||
opacity: 0 !important;
|
||||
}
|
||||
:host{
|
||||
display: grid;
|
||||
--danger-color: red;
|
||||
--border-radius: 0.3rem;
|
||||
--background: rgba(var(--text-color,(17,17,17)), 0.06);
|
||||
--padding: initial;
|
||||
--max-height: 8rem;
|
||||
}
|
||||
:host([variant="outlined"]) .textarea {
|
||||
box-shadow: 0 0 0 0.1rem rgba(var(--text-color,(17,17,17)), 0.4) inset;
|
||||
background: rgba(var(--background-color,(255,255,255)), 1);
|
||||
}
|
||||
.textarea{
|
||||
display: grid;
|
||||
position: relative;
|
||||
cursor: text;
|
||||
min-width: 0;
|
||||
text-align: left;
|
||||
overflow: hidden auto;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: stretch;
|
||||
max-height: var(--max-height);
|
||||
background: var(--background);
|
||||
border-radius: var(--border-radius);
|
||||
padding: var(--padding);
|
||||
}
|
||||
.textarea::after,
|
||||
textarea{
|
||||
padding: 0.7rem 1rem;
|
||||
width: 100%;
|
||||
min-width: 1em;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
resize: none;
|
||||
grid-area: 2/1;
|
||||
justify-self: stretch;
|
||||
background: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
line-height: 1.5;
|
||||
overflow: hidden;
|
||||
}
|
||||
.textarea::after{
|
||||
content: attr(data-value) ' ';
|
||||
visibility: hidden;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
hyphens: auto;
|
||||
}
|
||||
.readonly{
|
||||
pointer-events: none;
|
||||
}
|
||||
.textarea:focus-within:not(.readonly){
|
||||
box-shadow: 0 0 0 0.1rem var(--accent-color,teal) inset;
|
||||
}
|
||||
.placeholder{
|
||||
position: absolute;
|
||||
margin: 0.7rem 1rem;
|
||||
opacity: .7;
|
||||
font-weight: inherit;
|
||||
font-size: inherit;
|
||||
line-height: 1.5;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
:host([disabled]) .textarea{
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
@media (any-hover: hover){
|
||||
::-webkit-scrollbar{
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb{
|
||||
background: rgba(var(--text-color,(17,17,17)), 0.3);
|
||||
border-radius: 1rem;
|
||||
&:hover{
|
||||
background: rgba(var(--text-color,(17,17,17)), 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<label class="textarea" part="textarea">
|
||||
<span class="placeholder"></span>
|
||||
<textarea rows="1"></textarea>
|
||||
</label>
|
||||
`;
|
||||
customElements.define('sm-textarea',
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super()
|
||||
this.attachShadow({
|
||||
mode: 'open'
|
||||
}).append(smTextarea.content.cloneNode(true))
|
||||
|
||||
this.textarea = this.shadowRoot.querySelector('textarea')
|
||||
this.textareaBox = this.shadowRoot.querySelector('.textarea')
|
||||
this.placeholder = this.shadowRoot.querySelector('.placeholder')
|
||||
this.reflectedAttributes = ['disabled', 'required', 'readonly', 'rows', 'minlength', 'maxlength']
|
||||
|
||||
this.reset = this.reset.bind(this)
|
||||
this.focusIn = this.focusIn.bind(this)
|
||||
this.fireEvent = this.fireEvent.bind(this)
|
||||
this.checkInput = this.checkInput.bind(this)
|
||||
}
|
||||
static get observedAttributes() {
|
||||
return ['disabled', 'value', 'placeholder', 'required', 'readonly', 'rows', 'minlength', 'maxlength']
|
||||
}
|
||||
get value() {
|
||||
return this.textarea.value
|
||||
}
|
||||
set value(val) {
|
||||
this.setAttribute('value', val)
|
||||
this.fireEvent()
|
||||
}
|
||||
get disabled() {
|
||||
return this.hasAttribute('disabled')
|
||||
}
|
||||
set disabled(val) {
|
||||
if (val) {
|
||||
this.setAttribute('disabled', '')
|
||||
} else {
|
||||
this.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
get isValid() {
|
||||
return this.textarea.checkValidity()
|
||||
}
|
||||
reset() {
|
||||
this.setAttribute('value', '')
|
||||
}
|
||||
focusIn() {
|
||||
this.textarea.focus()
|
||||
}
|
||||
fireEvent() {
|
||||
let event = new Event('input', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
composed: true
|
||||
});
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
checkInput() {
|
||||
if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '')
|
||||
return;
|
||||
if (this.textarea.value !== '') {
|
||||
this.placeholder.classList.add('hide')
|
||||
} else {
|
||||
this.placeholder.classList.remove('hide')
|
||||
}
|
||||
}
|
||||
connectedCallback() {
|
||||
this.textarea.addEventListener('input', e => {
|
||||
this.textareaBox.dataset.value = this.textarea.value
|
||||
this.checkInput()
|
||||
})
|
||||
}
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (this.reflectedAttributes.includes(name)) {
|
||||
if (this.hasAttribute(name)) {
|
||||
this.textarea.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : '')
|
||||
}
|
||||
else {
|
||||
this.textContent.removeAttribute(name)
|
||||
}
|
||||
}
|
||||
else if (name === 'placeholder') {
|
||||
this.placeholder.textContent = this.getAttribute('placeholder')
|
||||
}
|
||||
else if (name === 'value') {
|
||||
this.textarea.value = newValue;
|
||||
this.textareaBox.dataset.value = newValue
|
||||
this.checkInput()
|
||||
}
|
||||
}
|
||||
})
|
||||
const smNotifications = document.createElement('template')
|
||||
smNotifications.innerHTML = `
|
||||
<style>
|
||||
|
||||
@ -164,10 +164,13 @@ User.decideRequest = function (request, note) {
|
||||
const Cashier = {};
|
||||
|
||||
Cashier.init = function () {
|
||||
delegate(getRef('cashier_request_list'), 'click', '.process-cashier-request', e => {
|
||||
delegate(getRef('cashier_pending_request_list'), 'click', '.process-cashier-request', e => {
|
||||
const requestID = e.delegateTarget.closest('.cashier-request').id;
|
||||
cashierUI.completeRequest(requestID)
|
||||
})
|
||||
getRef('cashier_requests_selector').addEventListener('change', e => {
|
||||
showChildElement('cashier_requests_wrapper', e.target.value === 'pending' ? 0 : 1)
|
||||
})
|
||||
return new Promise((resolve, reject) => {
|
||||
let promises = [];
|
||||
//Requests from user to cashier(self) for token-cash exchange
|
||||
|
||||
@ -336,40 +336,29 @@ cashierUI.renderRequests = function (requests, error = null) {
|
||||
else if (typeof requests !== "object" || requests === null)
|
||||
return;
|
||||
const frag = document.createDocumentFragment();
|
||||
for (let r in requests) {
|
||||
const oldCard = document.getElementById(r);
|
||||
if (oldCard) oldCard.remove();
|
||||
frag.prepend(render.cashierRequestCard(requests[r]));
|
||||
for (let transactionID in requests) {
|
||||
const { note, tag } = requests[transactionID];
|
||||
let status = tag ? 'done' : (note ? 'failed' : "pending");
|
||||
getRef('cashier_pending_request_list').querySelectorAll(`[data-vc="${transactionID}"]`).forEach(card => card.remove());
|
||||
getRef(status === 'pending' ? 'cashier_pending_request_list' : 'cashier_processed_request_list').prepend(render.cashierRequestCard(requests[transactionID]))
|
||||
}
|
||||
getRef('cashier_request_list').prepend(frag)
|
||||
}
|
||||
|
||||
cashierUI.completeRequest = function (reqID) {
|
||||
let request = Cashier.Requests[reqID];
|
||||
if (request.message.mode === "cash-to-token")
|
||||
completeCashToTokenRequest(request);
|
||||
else if (request.message.mode === "token-to-cash")
|
||||
completeTokenToCashRequest(request);
|
||||
floGlobals.cashierProcessingRequest = Cashier.Requests[reqID];
|
||||
const { message: { mode } } = floGlobals.cashierProcessingRequest;
|
||||
if (mode === "cash-to-token")
|
||||
completeCashToTokenRequest(floGlobals.cashierProcessingRequest);
|
||||
else if (mode === "token-to-cash")
|
||||
completeTokenToCashRequest(floGlobals.cashierProcessingRequest);
|
||||
}
|
||||
|
||||
function completeCashToTokenRequest(request) {
|
||||
const { message: { upi_txid, amount }, vectorClock, senderID } = request;
|
||||
Cashier.checkIfUpiTxIsValid(upi_txid).then(_ => {
|
||||
getConfirmation('Confirm', {
|
||||
message: `Check if you have received UPI transfer\nTxID: ${upi_txid}\nAmount: ${formatAmount(amount)}`,
|
||||
confirmText: 'Confirm'
|
||||
}).then(confirmed => {
|
||||
if (confirmed) {
|
||||
User.sendToken(senderID, amount, 'for cash-to-token').then(txid => {
|
||||
console.warn(`${amount} cash-to-token for ${senderID}`, txid);
|
||||
Cashier.finishRequest(request, txid).then(result => {
|
||||
console.log(result);
|
||||
console.info('Completed cash-to-token request:', vectorClock);
|
||||
notify("Completed request", 'success');
|
||||
}).catch(error => console.error(error))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
})
|
||||
getRef('top_up_amount').textContent = formatAmount(amount);
|
||||
getRef('top_up_txid').value = upi_txid;
|
||||
showPopup('confirm_topup_popup');
|
||||
}).catch(error => {
|
||||
notify(error, 'error');
|
||||
if (Array.isArray(error) && error[0] === true && typeof error[1] === 'string')
|
||||
@ -380,6 +369,41 @@ function completeCashToTokenRequest(request) {
|
||||
})
|
||||
}
|
||||
|
||||
function confirmTopUp() {
|
||||
const { message: { amount }, vectorClock, senderID } = floGlobals.cashierProcessingRequest;
|
||||
User.sendToken(senderID, amount, 'for cash-to-token').then(txid => {
|
||||
console.warn(`${amount} cash-to-token for ${senderID}`, txid);
|
||||
Cashier.finishRequest(floGlobals.cashierProcessingRequest, txid).then(result => {
|
||||
console.log(result);
|
||||
console.info('Completed cash-to-token request:', vectorClock);
|
||||
notify("Completed request", 'success');
|
||||
}).catch(error => console.error(error))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
getRef('top_up__reason_selector').addEventListener('change', e => {
|
||||
console.log(e.target.value);
|
||||
if (e.target.value === 'other') {
|
||||
getRef('top_up__specified_reason').parentNode.classList.remove('hide');
|
||||
} else {
|
||||
getRef('top_up__specified_reason').parentNode.classList.add('hide');
|
||||
}
|
||||
})
|
||||
function declineTopUp() {
|
||||
const { vectorClock } = floGlobals.cashierProcessingRequest;
|
||||
let reason = getRef('top_up__reason_selector').value;
|
||||
if (reason === 'other') {
|
||||
reason = getRef('top_up__specified_reason').value
|
||||
}
|
||||
Cashier.rejectRequest(floGlobals.cashierProcessingRequest, reason).then(result => {
|
||||
console.log(result);
|
||||
console.info('Rejected cash-to-token request:', vectorClock);
|
||||
notify('Request top-up request', 'success');
|
||||
hidePopup()
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
|
||||
function completeTokenToCashRequest(request) {
|
||||
const { vectorClock, senderID, message: { token_txid, amount, upi_id } } = request
|
||||
Cashier.checkIfTokenTxIsValid(token_txid, senderID, amount).then(result => {
|
||||
@ -427,6 +451,11 @@ function getStatusIcon(status) {
|
||||
}
|
||||
}
|
||||
|
||||
const cashierRejectionErrors = {
|
||||
1001: `Your request was reject because of wrong transaction ID. If you have sent money, it'll be returned within 24 hrs.`,
|
||||
1002: `Amount requested and amount sent via UPI doesn't match. your transferred money will be returned within 24hrs.`
|
||||
}
|
||||
|
||||
const render = {
|
||||
savedId(floID, details) {
|
||||
const { title } = details;
|
||||
@ -469,7 +498,7 @@ const render = {
|
||||
:
|
||||
`<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"></path><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></svg>`;
|
||||
if (status)
|
||||
clone.querySelector('.cashier-request__status').textContent = status;
|
||||
clone.querySelector('.cashier-request__status').textContent = status.includes(':') ? status.split(':')[0] : status;
|
||||
else
|
||||
clone.querySelector('.cashier-request__status').innerHTML = `<button class="button process-cashier-request">Process</button>`;
|
||||
return clone;
|
||||
|
||||
@ -72,7 +72,7 @@ const debounce = (callback, wait) => {
|
||||
};
|
||||
}
|
||||
|
||||
let zIndex = 10
|
||||
let zIndex = 100
|
||||
// function required for popups or modals to appear
|
||||
function showPopup(popupId, pinned) {
|
||||
zIndex++
|
||||
@ -135,6 +135,9 @@ document.addEventListener('popupclosed', e => {
|
||||
case 'transfer_to_exchange_popup':
|
||||
showChildElement('exchange_transfer_process', 0);
|
||||
break;
|
||||
case 'confirm_topup_popup':
|
||||
showChildElement('confirm_topup_wrapper', 0);
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
@ -448,6 +451,7 @@ async function showPage(targetPage, options = {}) {
|
||||
}
|
||||
} else if (params.type === 'wallet') {
|
||||
transactionDetails = User.cashierRequests[params.transactionId]
|
||||
console.log(transactionDetails)
|
||||
const { message: { amount, mode, upi_id, upi_txid }, note, tag } = transactionDetails
|
||||
status = tag ? tag : (note ? 'REJECTED' : "PENDING");
|
||||
getRef('transaction__type').textContent = mode === 'cash-to-token' ? 'Wallet top-up' : 'Withdraw';
|
||||
@ -459,7 +463,15 @@ async function showPage(targetPage, options = {}) {
|
||||
getRef('transaction__note').classList.remove('hide')
|
||||
}
|
||||
if (mode === 'cash-to-token') {
|
||||
getRef('transaction__note').textContent = `UPI transaction ID: ${upi_txid}`
|
||||
if (status === 'COMPLETED') {
|
||||
getRef('transaction__note').textContent = `UPI transaction ID: ${upi_txid}`
|
||||
} else if (status === 'REJECTED') {
|
||||
const reason = ['1001', '1002'].includes(note.split(':')[1]) ? cashierRejectionErrors[note.split(':')[1]] : note.split(':')[1]
|
||||
getRef('transaction__note').innerHTML = `
|
||||
<svg class="icon failed" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></svg>
|
||||
${reason}
|
||||
`
|
||||
}
|
||||
getRef('transaction__note').classList.remove('hide')
|
||||
|
||||
} else {
|
||||
@ -806,7 +818,13 @@ function createState(defaultValue, key, callback) {
|
||||
return reactiveState.createState(defaultValue, key, callback)
|
||||
}
|
||||
const smState = document.createElement('template')
|
||||
smState.innerHTML = ``
|
||||
smState.innerHTML = `
|
||||
<style>
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
font-family: inherit;
|
||||
</style>
|
||||
`
|
||||
class SmState extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user