adding transaction details page

This commit is contained in:
sairaj mote 2022-04-17 21:13:22 +05:30
parent e5bdb5e122
commit 5e51d8d5e5
6 changed files with 306 additions and 125 deletions

View File

@ -247,27 +247,6 @@ ul {
grid-column: 1/-1; grid-column: 1/-1;
} }
.h1 {
font-size: 1.5rem;
}
.h2 {
font-size: 1.2rem;
}
h3 {
font-size: 1.2rem;
line-height: 1.3;
}
.h4 {
font-size: 0.9rem;
}
.h5 {
font-size: 0.75rem;
}
.uppercase { .uppercase {
text-transform: uppercase; text-transform: uppercase;
} }
@ -346,7 +325,7 @@ h3 {
} }
.justify-start { .justify-start {
justify-content: start; justify-items: start;
} }
.justify-center { .justify-center {
@ -630,7 +609,7 @@ h3 {
padding: 0.5rem 0.3rem; padding: 0.5rem 0.3rem;
color: var(--text-color); color: var(--text-color);
font-size: 0.7rem; font-size: 0.7rem;
border-radius: 0.7rem; border-radius: 0.3rem;
} }
.nav-item .icon { .nav-item .icon {
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
@ -699,13 +678,15 @@ h3 {
position: relative; position: relative;
} }
#user { #user,
#cashier {
position: relative; position: relative;
gap: 2rem; gap: 2rem;
height: 100%; height: 100%;
padding: 0 1.5rem; padding: 0 1.5rem;
overflow-y: auto; overflow-y: auto;
padding-bottom: 5rem; padding-bottom: 5rem;
align-content: flex-start;
} }
#quick_actions_container { #quick_actions_container {
@ -732,10 +713,10 @@ h3 {
} }
#rupee_balance span:first-of-type { #rupee_balance span:first-of-type {
font-size: 1.5rem; font-size: 2rem;
} }
#rupee_balance span:last-of-type { #rupee_balance span:last-of-type {
font-size: 0.8rem; font-size: 1rem;
} }
.wallet-action { .wallet-action {
@ -761,19 +742,20 @@ h3 {
grid-template-columns: auto 1fr; grid-template-columns: auto 1fr;
gap: 0 0.8rem; gap: 0 0.8rem;
border-radius: 0.3rem; border-radius: 0.3rem;
padding: 0.5rem 0;
background-color: rgba(var(--text-color), 0.03);
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
align-items: center;
} }
.saved-id.highlight { .saved-id.highlight {
box-shadow: 0 0 0.1rem 0.1rem var(--accent-color) inset; box-shadow: 0 0 0.1rem 0.1rem var(--accent-color) inset;
} }
.saved-id .edit-saved { .saved-id .edit-saved {
grid-area: 1/1/3/2;
padding: 0.3rem; padding: 0.3rem;
position: relative; position: relative;
justify-self: center;
} }
.saved-id .edit-saved .icon { .saved-id .edit-saved .icon {
position: absolute; position: absolute;
@ -801,8 +783,13 @@ h3 {
border-radius: 2rem; border-radius: 2rem;
} }
.saved-id__title { .saved-id__title {
font-size: 0.9rem; align-self: flex-end;
font-weight: 500; overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.saved-id__flo-id {
font-size: 0.8rem;
} }
.card { .card {
@ -827,7 +814,7 @@ h3 {
overflow-y: auto; overflow-y: auto;
flex: 1; flex: 1;
padding: 0 max(1rem, 8vw); padding: 0 max(1rem, 8vw);
align-items: flex-start; align-content: flex-start;
} }
.transaction-message { .transaction-message {
@ -859,6 +846,10 @@ h3 {
font-size: 0.8rem; font-size: 0.8rem;
} }
#transaction {
padding: 1.5rem;
}
#wallet_history_wrapper { #wallet_history_wrapper {
margin-top: 1.5rem; margin-top: 1.5rem;
padding-bottom: 3rem; padding-bottom: 3rem;
@ -904,9 +895,7 @@ h3 {
border-radius: 2rem; border-radius: 2rem;
} }
.transaction__receiver { .transaction__receiver {
font-size: 0.9rem;
font-weight: 500; font-weight: 500;
color: rgba(var(--text-color), 0.8);
} }
.transaction__time { .transaction__time {
font-size: 0.8rem; font-size: 0.8rem;
@ -1028,7 +1017,7 @@ h3 {
align-items: center; align-items: center;
padding: 0.8rem; padding: 0.8rem;
border-radius: 0.3rem; border-radius: 0.3rem;
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.03);
} }
.cashier-request:not(:last-of-type), .cashier-request:not(:last-of-type),
.payment-request:not(:last-of-type) { .payment-request:not(:last-of-type) {
@ -1039,14 +1028,44 @@ h3 {
font-size: 0.8rem; font-size: 0.8rem;
} }
#payment_request_history {
padding-bottom: 3rem;
}
.payment-request { .payment-request {
display: grid; display: grid;
gap: 0.5rem 1rem;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
color: rgba(var(--text-color), 1);
} }
.payment-request__amount { .payment-request__amount {
font-weight: 700; font-weight: 700;
text-align: right; text-align: right;
} }
.payment-request__status {
display: flex;
align-items: center;
font-size: 0.8rem;
font-weight: 500;
letter-spacing: 0.05em;
}
.payment-request__status .icon {
height: 1rem;
width: 1rem;
margin-left: 0.3rem;
}
.payment-request .icon.paid {
fill: var(--green);
}
.payment-request .icon.declined {
fill: var(--danger-color);
}
.payment-request .button {
background-color: transparent;
padding: 0.6rem 0.8rem;
color: var(--accent-color);
background-color: rgba(var(--foreground-color), 1);
}
.wallet-request { .wallet-request {
display: grid; display: grid;
@ -1121,7 +1140,7 @@ h3 {
height: calc(100vh - 3rem); height: calc(100vh - 3rem);
width: calc(100vw - 3rem); width: calc(100vw - 3rem);
position: relative; position: relative;
border-radius: 1rem; border-radius: 0.5rem;
overflow: hidden; overflow: hidden;
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.05), 0 1rem 3rem rgba(0, 0, 0, 0.2); box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.05), 0 1rem 3rem rgba(0, 0, 0, 0.2);
} }
@ -1166,13 +1185,8 @@ h3 {
padding: 1.5rem; padding: 1.5rem;
} }
#user {
gap: 1rem;
align-items: flex-start;
}
#saved_ids_list { #saved_ids_list {
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
} }
} }
@media screen and (min-width: 56rem) { @media screen and (min-width: 56rem) {

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -219,27 +219,6 @@ ul {
.full-bleed { .full-bleed {
grid-column: 1/-1; grid-column: 1/-1;
} }
.h1 {
font-size: 1.5rem;
}
.h2 {
font-size: 1.2rem;
}
h3 {
font-size: 1.2rem;
line-height: 1.3;
}
.h4 {
font-size: 0.9rem;
}
.h5 {
font-size: 0.75rem;
}
.uppercase { .uppercase {
text-transform: uppercase; text-transform: uppercase;
} }
@ -312,7 +291,7 @@ h3 {
} }
.justify-start { .justify-start {
justify-content: start; justify-items: start;
} }
.justify-center { .justify-center {
@ -587,7 +566,7 @@ h3 {
padding: 0.5rem 0.3rem; padding: 0.5rem 0.3rem;
color: var(--text-color); color: var(--text-color);
font-size: 0.7rem; font-size: 0.7rem;
border-radius: 0.7rem; border-radius: 0.3rem;
.icon { .icon {
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
} }
@ -653,13 +632,15 @@ h3 {
padding: 0; padding: 0;
position: relative; position: relative;
} }
#user { #user,
#cashier {
position: relative; position: relative;
gap: 2rem; gap: 2rem;
height: 100%; height: 100%;
padding: 0 1.5rem; padding: 0 1.5rem;
overflow-y: auto; overflow-y: auto;
padding-bottom: 5rem; padding-bottom: 5rem;
align-content: flex-start;
} }
#quick_actions_container { #quick_actions_container {
display: grid; display: grid;
@ -684,10 +665,10 @@ h3 {
} }
#rupee_balance { #rupee_balance {
span:first-of-type { span:first-of-type {
font-size: 1.5rem; font-size: 2rem;
} }
span:last-of-type { span:last-of-type {
font-size: 0.8rem; font-size: 1rem;
} }
} }
.wallet-action { .wallet-action {
@ -712,15 +693,16 @@ h3 {
grid-template-columns: auto 1fr; grid-template-columns: auto 1fr;
gap: 0 0.8rem; gap: 0 0.8rem;
border-radius: 0.3rem; border-radius: 0.3rem;
padding: 0.5rem 0;
background-color: rgba(var(--text-color), 0.03);
user-select: none; user-select: none;
align-items: center;
&.highlight { &.highlight {
box-shadow: 0 0 0.1rem 0.1rem var(--accent-color) inset; box-shadow: 0 0 0.1rem 0.1rem var(--accent-color) inset;
} }
.edit-saved { .edit-saved {
grid-area: 1/1/3/2;
padding: 0.3rem; padding: 0.3rem;
position: relative; position: relative;
justify-self: center;
.icon { .icon {
position: absolute; position: absolute;
height: 1.2rem; height: 1.2rem;
@ -748,8 +730,13 @@ h3 {
border-radius: 2rem; border-radius: 2rem;
} }
&__title { &__title {
font-size: 0.9rem; align-self: flex-end;
font-weight: 500; overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__flo-id {
font-size: 0.8rem;
} }
} }
@ -773,7 +760,7 @@ h3 {
overflow-y: auto; overflow-y: auto;
flex: 1; flex: 1;
padding: 0 max(1rem, 8vw); padding: 0 max(1rem, 8vw);
align-items: flex-start; align-content: flex-start;
} }
.transaction-message { .transaction-message {
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.06);
@ -805,6 +792,10 @@ h3 {
} }
} }
#transaction {
padding: 1.5rem;
}
#wallet_history_wrapper { #wallet_history_wrapper {
margin-top: 1.5rem; margin-top: 1.5rem;
padding-bottom: 3rem; padding-bottom: 3rem;
@ -851,9 +842,7 @@ h3 {
border-radius: 2rem; border-radius: 2rem;
} }
&__receiver { &__receiver {
font-size: 0.9rem;
font-weight: 500; font-weight: 500;
color: rgba(var(--text-color), 0.8);
} }
&__time { &__time {
font-size: 0.8rem; font-size: 0.8rem;
@ -956,7 +945,7 @@ h3 {
align-items: center; align-items: center;
padding: 0.8rem; padding: 0.8rem;
border-radius: 0.3rem; border-radius: 0.3rem;
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.03);
&:not(:last-of-type) { &:not(:last-of-type) {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
@ -964,13 +953,42 @@ h3 {
font-size: 0.8rem; font-size: 0.8rem;
} }
} }
#payment_request_history {
padding-bottom: 3rem;
}
.payment-request { .payment-request {
display: grid; display: grid;
gap: 0.5rem 1rem;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
color: rgba(var(--text-color), 1);
&__amount { &__amount {
font-weight: 700; font-weight: 700;
text-align: right; text-align: right;
} }
&__status {
display: flex;
align-items: center;
font-size: 0.8rem;
font-weight: 500;
letter-spacing: 0.05em;
.icon {
height: 1rem;
width: 1rem;
margin-left: 0.3rem;
}
}
.icon.paid {
fill: var(--green);
}
.icon.declined {
fill: var(--danger-color);
}
.button {
background-color: transparent;
padding: 0.6rem 0.8rem;
color: var(--accent-color);
background-color: rgba(var(--foreground-color), 1);
}
} }
.wallet-request { .wallet-request {
display: grid; display: grid;
@ -1049,7 +1067,7 @@ h3 {
grid-template-areas: "nav header" "nav ."; grid-template-areas: "nav header" "nav .";
} }
position: relative; position: relative;
border-radius: 1rem; border-radius: 0.5rem;
overflow: hidden; overflow: hidden;
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.05), box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.05),
0 1rem 3rem rgba(0, 0, 0, 0.2); 0 1rem 3rem rgba(0, 0, 0, 0.2);
@ -1086,12 +1104,8 @@ h3 {
.card { .card {
padding: 1.5rem; padding: 1.5rem;
} }
#user {
gap: 1rem;
align-items: flex-start;
}
#saved_ids_list { #saved_ids_list {
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
} }
} }
@media screen and (min-width: 56rem) { @media screen and (min-width: 56rem) {

View File

@ -548,9 +548,18 @@
<circle cx="497.22047" cy="216.17011" r="6.46689" fill="#f2f2f2" /> <circle cx="497.22047" cy="216.17011" r="6.46689" fill="#f2f2f2" />
</svg> </svg>
</div> </div>
<ul id="user-money-requests" class="observe-empty-state"></ul> <div id="requests_history_wrapper" class="grid gap-1-5">
<div class=" empty-state gap-1 justify-center text-center"> <div class="hide grid gap-1">
<h4>No requests</h4> <h4>Pending requests</h4>
<ul id="pending_payment_requests" class="grid gap-0-5"></ul>
</div>
<div class="grid gap-1">
<h4>History</h4>
<ul id="payment_request_history" class="observe-empty-state grid gap-0-5"></ul>
<div class=" empty-state gap-1 justify-center text-center">
<h4>No requests</h4>
</div>
</div>
</div> </div>
</section> </section>
<section id="wallet" class="inner-page hide"> <section id="wallet" class="inner-page hide">
@ -627,7 +636,7 @@
transform="translate(-229.66231 -151.4124)" fill="#3f3d56" /> transform="translate(-229.66231 -151.4124)" fill="#3f3d56" />
</svg> </svg>
</div> </div>
<div class="grid"> <div class="grid gap-1" style="width: min(24rem, 100%);">
<div class="grid gap-0-5"> <div class="grid gap-0-5">
<h5>Balance</h5> <h5>Balance</h5>
<h1 class="h1" id="rupee_balance"></h1> <h1 class="h1" id="rupee_balance"></h1>
@ -677,7 +686,7 @@
</div> </div>
</section> </section>
<div id="transaction" class="inner-page hide"> <div id="transaction" class="inner-page hide">
<div class="flex align-center"> <div class="grid gap-0-5 justify-start">
<button class="button icon-only margin-right-0-5" onclick="history.back()"> <button class="button icon-only margin-right-0-5" onclick="history.back()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" <svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000"> fill="#000000">
@ -685,7 +694,13 @@
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" /> <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
</svg> </svg>
</button> </button>
<h4 id="contact__title"></h4> <h4 id="transaction__type"></h4>
</div>
<h1 id="transaction__amount"></h1>
<div class="flex align-center">
<time id="transaction__time"></time>
<div class="bullet-point"></div>
<span id="transaction__status"></span>
</div> </div>
</div> </div>
<section id="settings" class="inner-page hide"> <section id="settings" class="inner-page hide">
@ -816,7 +831,7 @@
<span class="nav-item__title">History</span> <span class="nav-item__title">History</span>
</a> </a>
</li> </li>
<li> <li class="user-element hide">
<a href="#/requests" class="nav-item interact" title='View payment requests'> <a href="#/requests" class="nav-item interact" title='View payment requests'>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" <svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
@ -900,7 +915,7 @@
<sm-copy id="edit_saved_id"></sm-copy> <sm-copy id="edit_saved_id"></sm-copy>
</div> </div>
<sm-form> <sm-form>
<sm-input id="newAddrLabel" placeholder="Name" autofocus animate required></sm-input> <sm-input id="get_new_title" placeholder="Name" autofocus animate required></sm-input>
<div class="flex align-center space-between"> <div class="flex align-center space-between">
<button class="button icon-only" title="Delete this FLO ID?" onclick="deleteSaved()"> <button class="button icon-only" title="Delete this FLO ID?" onclick="deleteSaved()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" <svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
@ -973,7 +988,7 @@
<!-- templates --> <!-- templates -->
<template id="saved_id_template"> <template id="saved_id_template">
<li class="saved-id grid interact" tabindex="0"> <li class="saved-id grid interact" tabindex="0">
<button class="interact edit-saved" title="Edit saved ID"> <button class="interact edit-saved icon-only" title="Edit name">
<div class="saved-id__initials"></div> <div class="saved-id__initials"></div>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" <svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000"> fill="#000000">
@ -983,6 +998,17 @@
</svg> </svg>
</button> </button>
<h4 class="saved-id__title"></h4> <h4 class="saved-id__title"></h4>
<div class="grid align-center" style="grid-template-columns: 1fr auto;">
<div class="saved-id__flo-id overflow-ellipsis"></div>
<button class="copy-saved-id icon-only margin-left-0-5" title="Copy FLO ID">
<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
d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
</div>
</li> </li>
</template> </template>
<template id="transaction_template"> <template id="transaction_template">
@ -1015,8 +1041,8 @@
</a> </a>
</li> </li>
</template> </template>
<template id="payment_request_template"> <template id="pending_payment_request_template">
<li class="payment-request"> <li class="payment-request payment-request--pending">
<div class="grid gap-0-5 flex-1"> <div class="grid gap-0-5 flex-1">
<div class="payment-request__requestor breakable"></div> <div class="payment-request__requestor breakable"></div>
<div class="payment-request__remark"></div> <div class="payment-request__remark"></div>
@ -1024,10 +1050,28 @@
<div class="payment-request__amount"></div> <div class="payment-request__amount"></div>
<div class="flex space-between full-bleed align-center"> <div class="flex space-between full-bleed align-center">
<time class="payment-request__time"></time> <time class="payment-request__time"></time>
<div class="payment-request__actions"></div> <div class="payment-request__actions">
<button class="button decline-payment">Decline</button>
<button class="button pay-requested">Pay</button>
</div>
</div> </div>
</li> </li>
</template> </template>
<template id="processed_payment_request_template">
<li>
<a href="" class="payment-request payment-request--processed interact">
<div class="grid gap-0-5 flex-1">
<div class="payment-request__requestor breakable"></div>
<div class="payment-request__remark"></div>
</div>
<div class="payment-request__amount"></div>
<div class="flex space-between full-bleed align-center">
<time class="payment-request__time"></time>
<div class="payment-request__status"></div>
</div>
</a>
</li>
</template>
<template id="transaction_message_template"> <template id="transaction_message_template">
<li class="transaction-message grid"> <li class="transaction-message grid">
<h3 class="transaction-message__amount"></h3> <h3 class="transaction-message__amount"></h3>

View File

@ -97,7 +97,7 @@ userUI.renderMoneyRequests = function (requests, error = null) {
return; return;
if (pagesData.lastPage === 'requests') { if (pagesData.lastPage === 'requests') {
for (let r in requests) { for (let r in requests) {
let oldCard = getRef('user-money-requests').querySelector(`[data-vc-${r}]`); let oldCard = getRef('payment_request_history').querySelector(`[data-vc-${r}]`);
if (oldCard) if (oldCard)
oldCard.replaceWith(render.paymentRequestCard(requests[r])); oldCard.replaceWith(render.paymentRequestCard(requests[r]));
} }
@ -105,12 +105,12 @@ userUI.renderMoneyRequests = function (requests, error = null) {
}; };
userUI.payRequest = function (reqID) { userUI.payRequest = function (reqID) {
let request = User.moneyRequests[reqID]; let { message: { amount, remark }, senderID } = User.moneyRequests[reqID];
getConfirmation('Pay?', { message: `Do you want to pay ${request.message.amount} to ${request.senderID}?`, confirmText: 'Pay' }).then(confirmation => { getConfirmation('Pay?', { message: `Do you want to pay ${request.message.amount} to ${request.senderID}?`, confirmText: 'Pay' }).then(confirmation => {
if (confirmation) { if (confirmation) {
User.sendToken(request.senderID, request.message.amount, "|" + request.message.remark).then(txid => { User.sendToken(senderID, amount, "|" + remark).then(txid => {
console.warn(`Sent ${request.message.amount} to ${request.senderID}`, txid); console.warn(`Sent ${amount} to ${senderID}`, txid);
notify(`Sent ${request.message.amount} to ${request.senderID}. It may take a few mins to reflect in their wallet`, 'success'); notify(`Sent ${formatAmount(amount)} to ${getFloIdTitle(senderID)}. It may take a few mins to reflect in their wallet`, 'success');
User.decideRequest(request, 'PAID: ' + txid) User.decideRequest(request, 'PAID: ' + txid)
.then(result => console.log(result)) .then(result => console.log(result))
.catch(error => console.error(error)) .catch(error => console.error(error))
@ -131,11 +131,11 @@ userUI.declineRequest = function (reqID) {
}) })
} }
delegate(getRef('user-money-requests'), 'click', '.pay-requested', e => { delegate(getRef('pending_payment_requests'), 'click', '.pay-requested', e => {
const vectorClock = e.target.closest('.payment-request').dataset.vc; const vectorClock = e.target.closest('.payment-request').dataset.vc;
userUI.payRequest(vectorClock); userUI.payRequest(vectorClock);
}) })
delegate(getRef('user-money-requests'), 'click', '.decline-payment', e => { delegate(getRef('pending_payment_requests'), 'click', '.decline-payment', e => {
const vectorClock = e.target.closest('.payment-request').dataset.vc; const vectorClock = e.target.closest('.payment-request').dataset.vc;
userUI.declineRequest(vectorClock); userUI.declineRequest(vectorClock);
}) })
@ -152,9 +152,9 @@ cashierUI.renderRequests = function (requests, error = null) {
for (let r in requests) { for (let r in requests) {
const oldCard = document.getElementById(r); const oldCard = document.getElementById(r);
if (oldCard) oldCard.remove(); if (oldCard) oldCard.remove();
frag.append(render.cashierRequestCard(requests[r])); frag.prepend(render.cashierRequestCard(requests[r]));
} }
getRef('cashier_request_list').append(frag) getRef('cashier_request_list').prepend(frag)
} }
cashierUI.completeRequest = function (reqID) { cashierUI.completeRequest = function (reqID) {
@ -233,11 +233,12 @@ function getStatusIcon(status) {
const render = { const render = {
savedId(floID, details) { savedId(floID, details) {
const { title } = details.hasOwnProperty('title') ? details : { title: details }; const { title } = details;
const clone = getRef('saved_id_template').content.cloneNode(true).firstElementChild; const clone = getRef('saved_id_template').content.cloneNode(true).firstElementChild;
clone.dataset.floId = floID; clone.dataset.floId = floID;
clone.querySelector('.saved-id__initials').textContent = title.charAt(0); clone.querySelector('.saved-id__initials').textContent = title.charAt(0);
clone.querySelector('.saved-id__title').textContent = title; clone.querySelector('.saved-id__title').textContent = title;
clone.querySelector('.saved-id__flo-id').textContent = floID;
return clone; return clone;
}, },
transactionCard(transactionDetails) { transactionCard(transactionDetails) {
@ -281,7 +282,7 @@ const render = {
let status = tag ? tag : (note ? 'REJECTED' : "PENDING"); let status = tag ? tag : (note ? 'REJECTED' : "PENDING");
clone.classList.add(status.toLowerCase()); clone.classList.add(status.toLowerCase());
clone.dataset.vc = vectorClock; clone.dataset.vc = vectorClock;
clone.href = `#/transaction?transactionId=${vectorClock}`; clone.href = `#/transaction?transactionId=${vectorClock}&type=wallet`;
clone.querySelector('.wallet-request__icon').innerHTML = type === 'Deposit' ? clone.querySelector('.wallet-request__icon').innerHTML = type === 'Deposit' ?
`<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 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" /></svg>` `<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 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" /></svg>`
: :
@ -297,21 +298,22 @@ const render = {
}, },
paymentRequestCard(details) { paymentRequestCard(details) {
const { time, senderID, message: { amount, remark }, note, vectorClock } = details; const { time, senderID, message: { amount, remark }, note, vectorClock } = details;
const clone = getRef('payment_request_template').content.cloneNode(true).firstElementChild; const clone = getRef(`${note ? 'processed' : 'pending'}_payment_request_template`).content.cloneNode(true).firstElementChild;
clone.dataset.vc = vectorClock; clone.dataset.vc = vectorClock;
clone.querySelector('.payment-request__requestor').textContent = getFloIdTitle(senderID); clone.querySelector('.payment-request__requestor').textContent = getFloIdTitle(senderID);
clone.querySelector('.payment-request__time').textContent = getFormattedTime(time); clone.querySelector('.payment-request__time').textContent = getFormattedTime(time);
clone.querySelector('.payment-request__amount').textContent = amount.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR' }); clone.querySelector('.payment-request__amount').textContent = amount.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR' });
clone.querySelector('.payment-request__remark').textContent = remark; clone.querySelector('.payment-request__remark').textContent = remark;
const status = note ? note.split(':')[0] : 'PENDING';
let status = note; if (note) {
if (status) clone.firstElementChild.href = `#/transaction?transactionId=${vectorClock}&type=request`;
clone.querySelector('.payment-request__actions').textContent = note; let icon
else if (status === 'PAID')
clone.querySelector('.payment-request__actions').innerHTML = icon = `<svg class="icon paid" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M23,12l-2.44-2.79l0.34-3.69l-3.61-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,12l2.44,2.79l-0.34,3.7 l3.61,0.82L8.6,22.5l3.4-1.47l3.4,1.46l1.89-3.19l3.61-0.82l-0.34-3.69L23,12z M10.09,16.72l-3.8-3.81l1.48-1.48l2.32,2.33 l5.85-5.87l1.48,1.48L10.09,16.72z"/></g></svg>`
`<button class="button pay-requested">Pay</button> else
<button class="button decline-payment">Decline</button>`; icon = `<svg class="icon declined" 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 d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"/></svg>`
clone.querySelector('.payment-request__status').innerHTML = `${status} ${icon}`;
}
return clone; return clone;
}, },
transactionMessage(details) { transactionMessage(details) {
@ -336,6 +338,17 @@ function showTokenTransfer(type) {
} }
showPopup('token_transfer_popup'); showPopup('token_transfer_popup');
} }
function getArrayOfSavedIds() {
const arr = []
for (const key in floGlobals.savedIds) {
arr.push({
floID: key,
details: floGlobals.savedIds[key]
})
}
return arr.sort((a, b) => a.details.title.localeCompare(b.details.title))
}
userUI.renderSavedIds = async function () { userUI.renderSavedIds = async function () {
floGlobals.savedIds = {} floGlobals.savedIds = {}
const frag = document.createDocumentFragment() const frag = document.createDocumentFragment()
@ -356,17 +369,17 @@ userUI.renderSavedIds = async function () {
floGlobals.savedIds[key] = idsToRender[key]; floGlobals.savedIds[key] = idsToRender[key];
} }
} }
for (const key in floGlobals.savedIds) { getArrayOfSavedIds().forEach(({ floID, details }) => {
frag.append(render.savedId(key, floGlobals.savedIds[key])); frag.append(render.savedId(floID, details));
} })
getRef('saved_ids_list').append(frag); getRef('saved_ids_list').append(frag);
} }
async function saveId() { async function saveId() {
const floID = getRef('flo_id_to_save').value.trim(); const floID = getRef('flo_id_to_save').value.trim();
const title = getRef('flo_id_title_to_save').value.trim(); const title = getRef('flo_id_title_to_save').value.trim();
floGlobals.savedIds[floID] = { title } floGlobals.savedIds[floID] = { title }
getRef('saved_ids_list').append(render.savedId(floID, { title }));
syncSavedIds().then(() => { syncSavedIds().then(() => {
insertElementAlphabetically(title, render.savedIdCard(floID, { title }))
notify(`Saved ${floID}`, 'success'); notify(`Saved ${floID}`, 'success');
hidePopup(); hidePopup();
}).catch(error => { }).catch(error => {
@ -381,13 +394,43 @@ delegate(getRef('saved_ids_list'), 'click', '.saved-id', e => {
if (e.target.closest('.edit-saved')) { if (e.target.closest('.edit-saved')) {
const target = e.target.closest('.saved-id'); const target = e.target.closest('.saved-id');
getRef('edit_saved_id').setAttribute('value', target.dataset.floId); getRef('edit_saved_id').setAttribute('value', target.dataset.floId);
getRef('newAddrLabel').value = getFloIdTitle(target.dataset.floId); getRef('get_new_title').value = getFloIdTitle(target.dataset.floId);
showPopup('edit_saved_popup'); showPopup('edit_saved_popup');
} else if (e.target.closest('.copy-saved-id')) {
const target = e.target.closest('.saved-id');
navigator.clipboard.writeText(target.dataset.floId)
target.dispatchEvent(
new CustomEvent('copy', {
bubbles: true,
cancelable: true,
})
);
} else { } else {
const target = e.target.closest('.saved-id'); const target = e.target.closest('.saved-id');
window.location.hash = `#/contact?floId=${target.dataset.floId}`; window.location.hash = `#/contact?floId=${target.dataset.floId}`;
} }
}); });
function saveChanges() {
const floID = getRef('edit_saved_id').value;
let title = getRef('get_new_title').value.trim();
if (title == '')
title = 'Unknown';
floGlobals.savedIds[floID] = { title }
syncSavedIds().then(() => {
const potentialTarget = getRef('saved_ids_list').querySelector(`.saved-id[data-flo-id="${floID}"]`)
if (potentialTarget) {
potentialTarget.querySelector('.saved-id__title').textContent = title;
potentialTarget.querySelector('.saved-id__initials').textContent = title.charAt(0).toUpperCase();
// place the renamed card in alphabetically correct position
const clone = potentialTarget.cloneNode(true);
potentialTarget.remove();
insertElementAlphabetically(title, clone)
}
hidePopup();
}).catch(error => {
notify(error, 'error');
})
}
function deleteSaved() { function deleteSaved() {
getConfirmation('Do you want delete this FLO ID?', { getConfirmation('Do you want delete this FLO ID?', {
confirmText: 'Delete', confirmText: 'Delete',
@ -406,6 +449,27 @@ function deleteSaved() {
} }
}); });
} }
const savedIdsObserver = new MutationObserver((mutationList) => {
mutationList.forEach(mutation => {
getRef('saved_ids_tip').textContent = mutation.target.children.length === 0 ? `Click 'Add FLO ID' to add a new FLO ID.` : `Tap on saved IDs to see transaction history.`
})
})
savedIdsObserver.observe(getRef('saved_ids_list'), {
childList: true,
})
function insertElementAlphabetically(name, elementToInsert) {
const elementInserted = [...getRef('saved_ids_list').children].some(child => {
const floID = child.dataset.floId;
if (floGlobals.savedIds[floID].title.localeCompare(name) > 0) {
child.before(elementToInsert)
return true
}
})
if (!elementInserted) {
getRef('saved_ids_list').append(elementToInsert)
}
}
function executeUserAction() { function executeUserAction() {
const floID = getRef('tt_flo_id').value.trim(), const floID = getRef('tt_flo_id').value.trim(),

View File

@ -5,6 +5,7 @@ const currentYear = new Date().getFullYear();
let paymentsHistoryLoader = null; let paymentsHistoryLoader = null;
let walletHistoryLoader = null; let walletHistoryLoader = null;
let contactHistoryLoader = null; let contactHistoryLoader = null;
let paymentRequestsLoader = null;
//Checks for internet connection status //Checks for internet connection status
if (!navigator.onLine) if (!navigator.onLine)
@ -350,12 +351,33 @@ async function showPage(targetPage, options = {}) {
}) })
break; break;
case 'requests': case 'requests':
const frag = document.createDocumentFragment(); const paymentRequests = []
for (let transactionID in User.moneyRequests) { if (paymentRequestsLoader)
frag.prepend(render.paymentRequestCard(User.moneyRequests[transactionID])); paymentRequestsLoader.clear()
const pendingPaymentRequests = document.createDocumentFragment()
let arePaymentsPending = false
for (const transactionId in User.moneyRequests) {
if (!User.moneyRequests[transactionId].note) {
arePaymentsPending = true
pendingPaymentRequests.prepend(render.paymentRequestCard(User.moneyRequests[transactionId]))
} else {
paymentRequests.unshift(User.moneyRequests[transactionId])
}
} }
getRef('user-money-requests').innerHTML = ''; if (arePaymentsPending) {
getRef('user-money-requests').prepend(frag); getRef('pending_payment_requests').innerHTML = ''
getRef('pending_payment_requests').append(pendingPaymentRequests)
getRef('pending_payment_requests').parentNode.classList.remove('hide')
} else {
getRef('pending_payment_requests').parentNode.classList.add('hide')
}
if (paymentRequestsLoader) {
paymentRequestsLoader.update(paymentRequests)
} else {
paymentRequestsLoader = new LazyLoader('#payment_request_history', paymentRequests, render.paymentRequestCard);
}
paymentRequestsLoader.init()
break; break;
case 'wallet': case 'wallet':
const walletTransactions = [] const walletTransactions = []
@ -386,6 +408,29 @@ async function showPage(targetPage, options = {}) {
} }
walletHistoryLoader.init() walletHistoryLoader.init()
break; break;
case 'transaction':
let transactionDetails
let status
switch (params.type) {
case 'request':
transactionDetails = User.moneyRequests[params.transactionId]
status = transactionDetails.note ? transactionDetails.note.split(':')[0] : 'PENDING';
getRef('transaction__type').textContent = 'Payment request'
break;
case 'wallet':
transactionDetails = User.cashierRequests[params.transactionId]
const { message: { mode }, note, tag } = transactionDetails
status = tag ? tag : (note ? 'REJECTED' : "PENDING");
getRef('transaction__type').textContent = mode === 'cash-to-token' ? 'Deposit' : 'Withdraw';
break;
}
const { message: { amount, remark }, note, senderID, receiverID, time } = transactionDetails
console.log(transactionDetails)
getRef('transaction__time').textContent = getFormattedTime(time)
getRef('transaction__amount').textContent = formatAmount(amount)
getRef('transaction__status').textContent = status
break;
default: default:
break; break;
} }