Added status based filtering for user accounts

This commit is contained in:
sairaj mote 2021-09-10 00:55:14 +05:30
parent 9bafae9387
commit 599c7d70c5
7 changed files with 738 additions and 277 deletions

View File

@ -1382,8 +1382,8 @@ class SquareLoader extends HTMLElement {
}).append(spinner.content.cloneNode(true))
}
}
window.customElements.define('sm-spinner', SquareLoader);
const themeToggle = document.createElement('template')
themeToggle.innerHTML = `
<style>
@ -1446,18 +1446,13 @@ themeToggle.innerHTML = `
</style>
<label class="theme-toggle" title="Change theme" tabindex="0">
<slot name="light-mode-icon">
<svg class="icon moon-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24"
height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M10 6a8 8 0 0 0 11.955 6.956C21.474 18.03 17.2 22 12 22 6.477 22 2 17.523 2 12c0-5.2 3.97-9.474 9.044-9.955A7.963 7.963 0 0 0 10 6zm-6 6a8 8 0 0 0 8 8 8.006 8.006 0 0 0 6.957-4.045c-.316.03-.636.045-.957.045-5.523 0-10-4.477-10-10 0-.321.015-.64.045-.957A8.006 8.006 0 0 0 4 12zm14.164-9.709L19 2.5v1l-.836.209a2 2 0 0 0-1.455 1.455L16.5 6h-1l-.209-.836a2 2 0 0 0-1.455-1.455L13 3.5v-1l.836-.209A2 2 0 0 0 15.29.836L15.5 0h1l.209.836a2 2 0 0 0 1.455 1.455zm5 5L24 7.5v1l-.836.209a2 2 0 0 0-1.455 1.455L21.5 11h-1l-.209-.836a2 2 0 0 0-1.455-1.455L18 8.5v-1l.836-.209a2 2 0 0 0 1.455-1.455L20.5 5h1l.209.836a2 2 0 0 0 1.455 1.455z" />
<svg xmlns="http://www.w3.org/2000/svg" class="icon moon-icon" viewBox="0 0 20 20" fill="currentColor">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>
</slot>
<slot name="dark-mode-icon">
<svg class="icon sun-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z" />
<svg xmlns="http://www.w3.org/2000/svg" class="icon sun-icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd" />
</svg>
</slot>
</label>
@ -1688,4 +1683,354 @@ customElements.define('sm-copy',
disconnectedCallback() {
this.copyButton.removeEventListener('click', this.copy)
}
})
})
const stripSelect = document.createElement('template')
stripSelect.innerHTML = `
<style>
*{
padding: 0;
margin: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
:host{
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--gap: 0.5rem;
padding: 1rem 0;
}
.hide{
display: none !important;
}
input[type="radio"]{
display: none;
}
.scrolling-container{
position: relative;
display: flex;
align-items: center;
}
.strip-select{
position: relative;
}
:host([multiline]) .strip-select{
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
overflow: auto hidden;
}
:host(:not([multiline])) .strip-select{
display: grid;
grid-auto-flow: column;
gap: var(--gap);
max-width: 100%;
align-items: center;
overflow: auto hidden;
}
.nav-button{
display: flex;
top: 50%;
z-index: 2;
border: none;
padding: 0.3rem;
cursor: pointer;
position: absolute;
align-items: center;
background: rgba(var(--background-color), 1);
transform: translateY(-50%);
}
.nav-button--right{
right: 0;
}
.cover{
position: absolute;
z-index: 1;
width: 5rem;
height: 100%;
pointer-events: none;
}
.nav-button--right::before{
background-color: red;
}
.icon{
height: 1.5rem;
width: 1.5rem;
fill: rgba(var(--text-color), .8);
}
@media (hover: none){
.nav-button{
display: none;
}
.strip-select{
overflow: auto hidden;
}
.cover{
width: 2rem;
}
.cover--left{
background: linear-gradient(90deg, rgba(var(--background-color), 1), transparent);
}
.cover--right{
right: 0;
background: linear-gradient(90deg, transparent, rgba(var(--background-color), 1));
}
}
@media (hover: hover){
::-webkit-scrollbar-track {
background-color: transparent !important;
}
::-webkit-scrollbar {
height: 0;
background-color: transparent;
}
.strip-select{
overflow: hidden;
}
.cover--left{
background: linear-gradient(90deg, rgba(var(--background-color), 1) 60%, transparent);
}
.cover--right{
right: 0;
background: linear-gradient(90deg, transparent 0%, rgba(var(--background-color), 1) 40%);
}
}
</style>
<section class="scrolling-container">
<div class="cover cover--left hide"></div>
<button class="nav-button nav-button--left hide">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10.828 12l4.95 4.95-1.414 1.414L8 12l6.364-6.364 1.414 1.414z"/></svg>
</button>
<section class="strip-select">
<slot></slot>
</section>
<button class="nav-button nav-button--right hide">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z"/></svg>
</button>
<div class="cover cover--right hide"></div>
</section>
`
customElements.define('strip-select', class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).append(stripSelect.content.cloneNode(true))
this.stripSelect = this.shadowRoot.querySelector('.strip-select')
this.slottedOptions
this._value
this.scrollDistance
this.scrollLeft = this.scrollLeft.bind(this)
this.scrollRight = this.scrollRight.bind(this)
this.fireEvent = this.fireEvent.bind(this)
}
get value() {
return this._value
}
scrollLeft() {
this.stripSelect.scrollBy({
left: -this.scrollDistance,
behavior: 'smooth'
})
}
scrollRight() {
this.stripSelect.scrollBy({
left: this.scrollDistance,
behavior: 'smooth'
})
}
fireEvent() {
this.dispatchEvent(
new CustomEvent("change", {
bubbles: true,
composed: true,
detail: {
value: this._value
}
})
)
}
connectedCallback() {
this.setAttribute('role', 'listbox')
const slot = this.shadowRoot.querySelector('slot')
const coverLeft = this.shadowRoot.querySelector('.cover--left')
const coverRight = this.shadowRoot.querySelector('.cover--right')
const navButtonLeft = this.shadowRoot.querySelector('.nav-button--left')
const navButtonRight = this.shadowRoot.querySelector('.nav-button--right')
slot.addEventListener('slotchange', e => {
const assignedElements = slot.assignedElements()
assignedElements.forEach(elem => {
if (elem.hasAttribute('selected')) {
elem.setAttribute('active', '')
this._value = elem.value
}
})
if (!this.hasAttribute('multiline')) {
if (assignedElements.length > 0) {
firstOptionObserver.observe(slot.assignedElements()[0])
lastOptionObserver.observe(slot.assignedElements()[slot.assignedElements().length - 1])
}
else {
navButtonLeft.classList.add('hide')
navButtonRight.classList.add('hide')
coverLeft.classList.add('hide')
coverRight.classList.add('hide')
firstOptionObserver.disconnect()
lastOptionObserver.disconnect()
}
}
})
const resObs = new ResizeObserver(entries => {
entries.forEach(entry => {
if (entry.contentBoxSize) {
// Firefox implements `contentBoxSize` as a single content rect, rather than an array
const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;
this.scrollDistance = contentBoxSize.inlineSize * 0.6
} else {
this.scrollDistance = entry.contentRect.width * 0.6
}
})
})
resObs.observe(this)
this.stripSelect.addEventListener('option-clicked', e => {
if (this._value !== e.target.value) {
this._value = e.target.value
slot.assignedElements().forEach(elem => elem.removeAttribute('active'))
e.target.setAttribute('active', '')
e.target.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" })
this.fireEvent()
}
})
const firstOptionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
navButtonLeft.classList.add('hide')
coverLeft.classList.add('hide')
}
else {
navButtonLeft.classList.remove('hide')
coverLeft.classList.remove('hide')
}
})
},
{
threshold: 0.9,
root: this
})
const lastOptionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
navButtonRight.classList.add('hide')
coverRight.classList.add('hide')
}
else {
navButtonRight.classList.remove('hide')
coverRight.classList.remove('hide')
}
})
},
{
threshold: 0.9,
root: this
})
navButtonLeft.addEventListener('click', this.scrollLeft)
navButtonRight.addEventListener('click', this.scrollRight)
}
disconnectedCallback() {
navButtonLeft.removeEventListener('click', this.scrollLeft)
navButtonRight.removeEventListener('click', this.scrollRight)
}
})
//Strip option
const stripOption = document.createElement('template')
stripOption.innerHTML = `
<style>
*{
padding: 0;
margin: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
:host{
--border-radius: 2rem;
--background-color: inherit;
--active-option-color: inherit;
--active-option-backgroud-color: rgba(var(--text-color), .2);
}
.strip-option{
display: flex;
flex-shrink: 0;
cursor: pointer;
white-space: nowrap;
padding: 0.5rem 0.8rem;
transition: background 0.3s;
border-radius: var(--border-radius);
-webkit-tap-highlight-color: transparent;
}
:host([active]) .strip-option{
color: var(--active-option-color);
background-color: var(--active-option-backgroud-color);
}
:host(:focus-within){
outline: none;
}
:host(:focus-within) .strip-option{
box-shadow: 0 0 0 0.1rem var(--accent-color) inset;
}
:host(:hover:not([active])) .strip-option{
background-color: rgba(var(--text-color), 0.06);
}
</style>
<label class="strip-option">
<slot></slot>
</label>
`
customElements.define('strip-option', class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).append(stripOption.content.cloneNode(true))
this._value
this.radioButton = this.shadowRoot.querySelector('input')
this.fireEvent = this.fireEvent.bind(this)
this.handleKeyDown = this.handleKeyDown.bind(this)
}
get value() {
return this._value
}
fireEvent() {
this.dispatchEvent(
new CustomEvent("option-clicked", {
bubbles: true,
composed: true,
detail: {
value: this._value
}
})
)
}
handleKeyDown(e) {
if (e.key === 'Enter' || e.key === 'Space') {
this.fireEvent()
}
}
connectedCallback() {
this.setAttribute('role', 'option')
this.setAttribute('tabindex', '0')
this._value = this.getAttribute('value')
this.addEventListener('click', this.fireEvent)
this.addEventListener('keydown', this.handleKeyDown)
}
disconnectedCallback() {
this.removeEventListener('click', this.fireEvent)
this.removeEventListener('keydown', this.handleKeyDown)
}
})

View File

@ -91,11 +91,11 @@ button,
}
.button {
padding: 0.4rem 0.6rem;
padding: 0.6rem 1rem;
border-radius: 0.3rem;
font-weight: 500;
font-size: 0.8rem;
border: solid thin rgba(var(--text-color), 0.5);
background-color: rgba(var(--text-color), 0.06);
}
button:disabled {
@ -148,11 +148,6 @@ ul {
display: none !important;
}
.no-transformations {
-webkit-transform: none !important;
transform: none !important;
}
.overflow-ellipsis {
width: 100%;
overflow: hidden;
@ -316,15 +311,6 @@ ul {
width: 100%;
}
.ripple {
position: absolute;
border-radius: 50%;
-webkit-transform: scale(0);
transform: scale(0);
background: rgba(var(--text-color), 0.16);
pointer-events: none;
}
.interact {
position: relative;
cursor: pointer;
@ -369,29 +355,24 @@ ul {
fill: var(--accent-color);
}
#confirmation_popup,
#prompt_popup {
#confirmation_popup {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
#confirmation_popup h4,
#prompt_popup h4 {
#confirmation_popup h4 {
font-weight: 500;
margin-bottom: 0.5rem;
}
#confirmation_popup sm-button,
#prompt_popup sm-button {
#confirmation_popup sm-button {
margin: 0;
}
#confirmation_popup .flex,
#prompt_popup .flex {
#confirmation_popup .flex {
padding: 0;
margin-top: 1rem;
}
#confirmation_popup .flex sm-button:first-of-type,
#prompt_popup .flex sm-button:first-of-type {
#confirmation_popup .flex sm-button:first-of-type {
margin-right: 0.6rem;
margin-left: auto;
}
@ -607,10 +588,41 @@ details[open] > summary .icon {
font-weight: 500;
}
#recent_transactions_container {
display: grid;
margin: 1.5rem 0;
padding-bottom: 5rem;
strip-select {
--gap: 0;
background-color: rgba(var(--text-color), 0.06);
border-radius: 0.3rem;
}
#accounts_empty_state {
margin-top: 3rem;
justify-items: center;
text-align: center;
}
#accounts_empty_state .empty-state__icon {
-webkit-filter: drop-shadow(0 0.5rem 0.3rem rgba(0, 0, 0, 0.1));
filter: drop-shadow(0 0.5rem 0.3rem rgba(0, 0, 0, 0.1));
height: 12rem;
width: 12rem;
padding: 3rem;
border-radius: 50%;
margin-bottom: 1.5rem;
background-color: rgba(var(--text-color), 0.06);
}
strip-option {
text-transform: uppercase;
font-weight: 500;
letter-spacing: 0.05em;
font-size: 0.7rem;
--active-option-color: rgba(var(--background-color), 1);
--active-option-backgroud-color: var(--accent-color);
}
strip-option:first-of-type {
--border-radius: 0.3rem 0 0 0.3rem;
}
strip-option:last-of-type {
--border-radius: 0 0.3rem 0.3rem 0;
}
.activity-card {
@ -663,12 +675,11 @@ details[open] > summary .icon {
padding: 1rem 1.5rem;
}
#user_accounts {
#user_accounts:not(:empty) {
margin-top: 1.5rem;
display: grid;
gap: 1rem;
padding-bottom: 5rem;
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}
.activity-card--account {
@ -677,24 +688,25 @@ details[open] > summary .icon {
-ms-user-select: none;
user-select: none;
gap: 1.5rem;
padding: 1.5rem;
background-color: var(--foreground-color);
padding: 1rem 1.5rem;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border: solid thin rgba(var(--text-color), 0.2);
grid-template-columns: minmax(0, 1fr);
}
.activity-card--account .activity-card__icon {
padding: 0;
margin-bottom: 0.5rem;
background-color: transparent;
}
.activity-card--account .activity-card__type {
text-transform: capitalize;
font-size: 0.9rem;
color: rgba(var(--text-color), 0.6);
color: rgba(var(--text-color), 0.8);
font-weight: 500;
}
.activity-card--account .activity-card__amount {
margin-top: 0.3rem;
font-size: 1.3rem;
font-size: 1.1rem;
}
.activity-card--request {
@ -887,6 +899,10 @@ details[open] > summary .icon {
font-weight: 700;
}
.page__header button {
padding: 0.5rem 0;
}
#transaction,
#account {
grid-template-rows: auto 1fr;
@ -898,13 +914,9 @@ details[open] > summary .icon {
#transaction section,
#account_details {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
display: grid;
gap: 2rem;
grid-template-rows: auto 1fr;
}
#transaction_top,
@ -948,10 +960,8 @@ details[open] > summary .icon {
font-weight: 700;
}
#transaction_detail__time {
font-size: 0.8rem;
color: rgba(var(--text-color), 0.8);
margin-right: 1rem;
#transaction__cta {
margin-top: 2rem;
}
#account_process {
@ -1075,6 +1085,7 @@ details[open] > summary .icon {
align-items: center;
}
#result__icon {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@ -1084,6 +1095,12 @@ details[open] > summary .icon {
-webkit-animation: pop-in 1s forwards cubic-bezier(0.175, 0.885, 0.32, 1.275);
animation: pop-in 1s forwards cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
#result__icon.pending {
background-color: rgba(255, 252, 75, 0.1);
}
#result__icon.failed {
background-color: rgba(255, 75, 75, 0.1);
}
#result__icon .icon {
height: 1.8rem;
width: 1.8rem;
@ -1128,6 +1145,14 @@ details[open] > summary .icon {
transform: none;
}
}
#settings {
padding: 0 1.5rem;
}
#settings sm-copy {
font-size: 0.9rem;
margin: 0.3rem 0 1.5rem 0;
}
@media screen and (max-width: 640px) {
sm-button {
--padding: 1rem;
@ -1167,13 +1192,13 @@ details[open] > summary .icon {
margin-top: auto;
}
#account_process {
margin-top: 3rem;
#transaction_top,
#account_top {
margin-top: 1rem;
}
}
@media screen and (min-width: 640px) {
#confirmation_popup,
#prompt_popup {
#confirmation_popup {
--width: 24rem;
}
@ -1225,15 +1250,16 @@ details[open] > summary .icon {
#transaction_top,
#account_top,
#account_process {
#account_process,
#transaction__steps {
overflow: hidden;
padding: 1.8rem;
border-radius: 0.5rem;
border: solid thin rgba(var(--text-color), 0.2);
}
#transaction_detail__status {
justify-self: flex-start;
background-color: var(--foreground-color);
-webkit-box-shadow: 0 0 0.1rem rgba(0, 0, 0, 0.1), 0 1rem 1.5rem -0.8rem rgba(0, 0, 0, 0.1);
box-shadow: 0 0 0.1rem rgba(0, 0, 0, 0.1), 0 1rem 1.5rem -0.8rem rgba(0, 0, 0, 0.1);
-ms-flex-item-align: start;
align-self: flex-start;
}
#transaction_detail__icon {
@ -1255,7 +1281,7 @@ details[open] > summary .icon {
}
.card {
padding: 2rem;
padding: 1.5rem;
}
#homepage {
@ -1274,8 +1300,6 @@ details[open] > summary .icon {
#transaction section,
#account_details {
display: grid;
gap: 1.5rem;
grid-template-columns: 18rem minmax(0, 1fr);
}
}

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -85,11 +85,11 @@ button,
transition: transform 0.3s;
}
.button {
padding: 0.4rem 0.6rem;
padding: 0.6rem 1rem;
border-radius: 0.3rem;
font-weight: 500;
font-size: 0.8rem;
border: solid thin rgba(var(--text-color), 0.5);
background-color: rgba(var(--text-color), 0.06);
}
button:disabled {
@ -137,10 +137,6 @@ ul {
display: none !important;
}
.no-transformations {
transform: none !important;
}
.overflow-ellipsis {
width: 100%;
overflow: hidden;
@ -288,14 +284,6 @@ ul {
}
}
.ripple {
position: absolute;
border-radius: 50%;
transform: scale(0);
background: rgba(var(--text-color), 0.16);
pointer-events: none;
}
.interact {
position: relative;
cursor: pointer;
@ -338,8 +326,7 @@ ul {
fill: var(--accent-color);
}
}
#confirmation_popup,
#prompt_popup {
#confirmation_popup {
flex-direction: column;
h4 {
@ -532,10 +519,38 @@ details {
font-weight: 500;
}
}
#recent_transactions_container {
display: grid;
margin: 1.5rem 0;
padding-bottom: 5rem;
strip-select {
--gap: 0;
background-color: rgba(var(--text-color), 0.06);
border-radius: 0.3rem;
}
#accounts_empty_state {
margin-top: 3rem;
justify-items: center;
text-align: center;
.empty-state__icon {
filter: drop-shadow(0 0.5rem 0.3rem rgba(0, 0, 0, 0.1));
height: 12rem;
width: 12rem;
padding: 3rem;
border-radius: 50%;
margin-bottom: 1.5rem;
background-color: rgba(var(--text-color), 0.06);
}
}
strip-option {
text-transform: uppercase;
font-weight: 500;
letter-spacing: 0.05em;
font-size: 0.7rem;
--active-option-color: rgba(var(--background-color), 1);
--active-option-backgroud-color: var(--accent-color);
&:first-of-type {
--border-radius: 0.3rem 0 0 0.3rem;
}
&:last-of-type {
--border-radius: 0 0.3rem 0.3rem 0;
}
}
.activity-card {
display: grid;
@ -577,33 +592,31 @@ details {
padding: 1rem 1.5rem;
}
}
#user_accounts {
#user_accounts:not(:empty) {
margin-top: 1.5rem;
display: grid;
gap: 1rem;
padding-bottom: 5rem;
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}
.activity-card--account {
user-select: none;
gap: 1.5rem;
padding: 1.5rem;
background-color: var(--foreground-color);
padding: 1rem 1.5rem;
align-items: center;
border: solid thin rgba(var(--text-color), 0.2);
grid-template-columns: minmax(0, 1fr);
.activity-card__icon {
padding: 0;
margin-bottom: 0.5rem;
background-color: transparent;
}
.activity-card__type {
text-transform: capitalize;
font-size: 0.9rem;
color: rgba(var(--text-color), 0.6);
color: rgba(var(--text-color), 0.8);
font-weight: 500;
}
.activity-card__amount {
margin-top: 0.3rem;
font-size: 1.3rem;
font-size: 1.1rem;
}
}
.activity-card--request {
@ -770,6 +783,13 @@ details {
font-weight: 700;
}
}
.page__header {
button {
padding: 0.5rem 0;
}
}
#transaction,
#account {
grid-template-rows: auto 1fr;
@ -779,8 +799,9 @@ details {
}
#transaction section,
#account_details {
display: flex;
flex-direction: column;
display: grid;
gap: 2rem;
grid-template-rows: auto 1fr;
}
#transaction_top,
#account_top {
@ -809,10 +830,8 @@ details {
font-size: 1.8rem;
font-weight: 700;
}
#transaction_detail__time {
font-size: 0.8rem;
color: rgba(var(--text-color), 0.8);
margin-right: 1rem;
#transaction__cta {
margin-top: 2rem;
}
#account_process {
@ -906,10 +925,17 @@ details {
align-items: center;
}
&__icon {
position: relative;
display: flex;
border-radius: 50%;
padding: 1rem;
margin: -5rem 0 1.5rem 0;
&.pending {
background-color: rgba(255, 252, 75, 0.1);
}
&.failed {
background-color: rgb(255, 75, 75, 0.1);
}
animation: pop-in 1s forwards cubic-bezier(0.175, 0.885, 0.32, 1.275);
.icon {
height: 1.8rem;
@ -936,6 +962,13 @@ details {
transform: none;
}
}
#settings {
padding: 0 1.5rem;
sm-copy {
font-size: 0.9rem;
margin: 0.3rem 0 1.5rem 0;
}
}
@media screen and (max-width: 640px) {
sm-button {
--padding: 1rem;
@ -963,13 +996,13 @@ details {
#deposit_button {
margin-top: auto;
}
#account_process {
margin-top: 3rem;
#transaction_top,
#account_top {
margin-top: 1rem;
}
}
@media screen and (min-width: 640px) {
#confirmation_popup,
#prompt_popup {
#confirmation_popup {
--width: 24rem;
}
.page-layout {
@ -1015,16 +1048,15 @@ details {
}
#transaction_top,
#account_top,
#account_process {
#account_process,
#transaction__steps {
overflow: hidden;
padding: 1.8rem;
border-radius: 0.5rem;
border: solid thin rgba(var(--text-color), 0.2);
// background-color: var(--foreground-color);
// box-shadow: 0 0 0.1rem rgba(0, 0, 0, 0.1), 0 1rem 1.5rem -0.8rem rgba(0, 0, 0, 0.1);
}
#transaction_detail__status {
justify-self: flex-start;
background-color: var(--foreground-color);
box-shadow: 0 0 0.1rem rgba(0, 0, 0, 0.1),
0 1rem 1.5rem -0.8rem rgba(0, 0, 0, 0.1);
align-self: flex-start;
}
#transaction_detail__icon {
justify-self: flex-start;
@ -1043,7 +1075,7 @@ details {
grid-template-columns: 1fr 80vw 1fr;
}
.card {
padding: 2rem;
padding: 1.5rem;
}
#homepage {
grid-template-columns: 14rem minmax(0, 1fr) 24rem;
@ -1059,8 +1091,6 @@ details {
}
#transaction section,
#account_details {
display: grid;
gap: 1.5rem;
grid-template-columns: 18rem minmax(0, 1fr);
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240"><defs><style>.a{fill:#d1d3d4;}.b{fill:#f1f2f2;}</style></defs><path class="a" d="M211.65,182.16a34.91,34.91,0,0,1-34.91,34.9v-34.9Z"/><path class="a" d="M176.74,220H173.8V179.22h40.79v2.94A37.89,37.89,0,0,1,176.74,220Zm2.95-34.9V214a32,32,0,0,0,28.88-28.89Z"/><path class="b" d="M189.07,214.82a44.91,44.91,0,0,1-12.33-30.9V28.82a5.88,5.88,0,0,0-5.88-5.88H34.23a5.88,5.88,0,0,0-5.88,5.88V182.16a34.91,34.91,0,0,0,34.91,34.9H177.6a30.43,30.43,0,0,0,11.47-2.24ZM51.47,70.48V56.24a1.47,1.47,0,0,1,1.47-1.47h15.5a1.47,1.47,0,0,1,1.47,1.47V70.48A1.47,1.47,0,0,1,68.44,72H52.94A1.47,1.47,0,0,1,51.47,70.48ZM112.7,115.1a1.47,1.47,0,0,1-1.47,1.47H56.6a1.47,1.47,0,0,1-1.47-1.47V100.87A1.47,1.47,0,0,1,56.6,99.4h54.63a1.47,1.47,0,0,1,1.47,1.47Zm3.66-44.62A1.47,1.47,0,0,1,114.89,72H99.39a1.47,1.47,0,0,1-1.47-1.47V56.24a1.47,1.47,0,0,1,1.47-1.47h15.5a1.47,1.47,0,0,1,1.47,1.47Z"/><path class="a" d="M177.6,220H63.26a37.89,37.89,0,0,1-37.85-37.84V28.82A8.83,8.83,0,0,1,34.23,20H170.86a8.84,8.84,0,0,1,8.83,8.82V183.93a41.74,41.74,0,0,0,11.52,28.86l3,3.13-4,1.62A33.25,33.25,0,0,1,177.6,220ZM34.23,25.88a2.94,2.94,0,0,0-2.94,2.94V182.16a32,32,0,0,0,32,32H177.6a27.5,27.5,0,0,0,6.35-.74,47.62,47.62,0,0,1-10.15-29.45V28.82a2.94,2.94,0,0,0-2.94-2.94Zm77,93.63H56.6a4.42,4.42,0,0,1-4.41-4.41V100.87a4.42,4.42,0,0,1,4.41-4.41h54.63a4.42,4.42,0,0,1,4.41,4.41V115.1A4.42,4.42,0,0,1,111.23,119.51Zm-53.16-5.88h51.69V102.34H58.07Zm56.82-38.74H99.39A4.42,4.42,0,0,1,95,70.48V56.24a4.42,4.42,0,0,1,4.41-4.41h15.5a4.41,4.41,0,0,1,4.41,4.41V70.48A4.41,4.41,0,0,1,114.89,74.89Zm-14-5.88h12.56V57.71H100.86ZM68.44,74.89H52.94a4.42,4.42,0,0,1-4.41-4.41V56.24a4.42,4.42,0,0,1,4.41-4.41h15.5a4.42,4.42,0,0,1,4.41,4.41V70.48A4.42,4.42,0,0,1,68.44,74.89ZM54.41,69H67V57.71H54.41Z"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240"><defs><style>.a{fill:#d1d3d4;}.b{fill:#fff;}</style></defs><path class="a" d="M173.83,179.28V220c24.71.41,42.29-17.71,40.7-40.7Z"/><path class="b" d="M208.86,202.38c-11.52,12.13-30.77,5.3-29.21-18.46V28.82A8.82,8.82,0,0,0,170.83,20H34.2a8.82,8.82,0,0,0-8.83,8.82V182.16A37.85,37.85,0,0,0,63.22,220H177.57C197.23,220.07,208.6,203.64,208.86,202.38Z"/><rect class="a" x="55.11" y="99.42" width="57.57" height="17.17" rx="1"/><rect class="a" x="48.51" y="51.85" width="24.32" height="23.05" rx="4.41"/><rect class="a" x="94.96" y="51.85" width="24.32" height="23.05" rx="4.41"/></svg>

After

Width:  |  Height:  |  Size: 642 B

View File

@ -56,15 +56,6 @@
<sm-button variant="no-outline" class="submit-btn">OK</sm-button>
</div>
</sm-popup>
<sm-popup id="prompt_popup">
<h4 id="prompt_title"></h4>
<p id="prompt_message"></p>
<sm-input id="prompt_input"></sm-input>
<div class="flex align-center">
<sm-button variant="no-outline" class="cancel-btn">Cancel</sm-button>
<sm-button variant="no-outline" class="submit-btn" type="submit">OK</sm-button>
</div>
</sm-popup>
<article id="sign_in" class="page page-layout hide-completely">
<section>
<h1 class="h2">Sign In</h1>
@ -206,14 +197,42 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon button__icon--left" viewBox="0 0 20 20"
fill="currentColor">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z"
d="M10.496 2.132a1 1 0 00-.992 0l-7 4A1 1 0 003 8v7a1 1 0 100 2h14a1 1 0 100-2V8a1 1 0 00.496-1.868l-7-4zM6 9a1 1 0 00-1 1v3a1 1 0 102 0v-3a1 1 0 00-1-1zm3 1a1 1 0 012 0v3a1 1 0 11-2 0v-3zm5-1a1 1 0 00-1 1v3a1 1 0 102 0v-3a1 1 0 00-1-1z"
clip-rule="evenodd" />
</svg>
Accounts
</h4>
<strip-select id="accounts_status_selector">
<strip-option value="active" selected>Active</strip-option>
<strip-option value="closed">Closed</strip-option>
</strip-select>
</div>
<div id="user_accounts" class="observe-empty-state"></div>
<p class="empty-state">No accounts so far.</p>
<div id="accounts_empty_state" class="empty-state grid justify-center gap-0-5">
<div class="empty-state__icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
<defs>
<style>
.a {
fill: #d1d3d4;
}
.b {
fill: #fff;
}
</style>
</defs>
<path class="a" d="M173.83,179.28V220c24.71.41,42.29-17.71,40.7-40.7Z" />
<path class="b"
d="M208.86,202.38c-11.52,12.13-30.77,5.3-29.21-18.46V28.82A8.82,8.82,0,0,0,170.83,20H34.2a8.82,8.82,0,0,0-8.83,8.82V182.16A37.85,37.85,0,0,0,63.22,220H177.57C197.23,220.07,208.6,203.64,208.86,202.38Z" />
<rect class="a" x="55.11" y="99.42" width="57.57" height="17.17" rx="1" />
<rect class="a" x="48.51" y="51.85" width="24.32" height="23.05" rx="4.41" />
<rect class="a" x="94.96" y="51.85" width="24.32" height="23.05" rx="4.41" />
</svg>
</div>
<h4>Nothing to see here</h4>
<p>Make a deposit or take a loan and it'll appear here.</h4>
</div>
</section>
</div>
<div id="notifications" class="sub-page hide-completely">
@ -225,6 +244,8 @@
<p class="empty-state">No notifications so far.</p>
</div>
<div id="settings" class="sub-page hide-completely">
<h5>My FLO ID</h5>
<sm-copy id="user_flo_id"></sm-copy>
<sm-button onclick="signOut()">Sign out</sm-button>
</div>
</section>
@ -310,13 +331,13 @@
</section>
</article>
<article id="deposit" class="page hide-completely page-layout">
<button class="icon-button justify-self-start" onclick="history.back()">
<a class="button icon-button justify-self-start" href="#/homepage/dashboard">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
clip-rule="evenodd" />
</svg>
</button>
</a>
<sm-form>
<div id="deposit__icon">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
@ -339,13 +360,13 @@
</sm-form>
</article>
<article id="loan" class="page hide-completely page-layout">
<button class="icon-button justify-self-start" onclick="history.back()">
<a class="button icon-button justify-self-start" href="#/homepage/dashboard">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
clip-rule="evenodd" />
</svg>
</button>
</a>
<sm-form>
<div id="deposit__icon">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
@ -367,20 +388,23 @@
</article>
<article id="result" class="page hide-completely page-layout">
<section class="flex direction-column">
<div id="result__icon" class="pending"></div>
<div id="result__icon"></div>
<h4 id="result__title"></h4>
<p id="result__description"></p>
<a id="result__back_button" href="" class="button">Done</a>
</section>
</article>
<article id="transaction" class="page hide-completely page-layout">
<button class="icon-button justify-self-start" onclick="history.back()">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
clip-rule="evenodd" />
</svg>
</button>
<div class="flex align-center page__header">
<button class="justify-self-start button__icon--left" onclick="history.back()">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
clip-rule="evenodd" />
</svg>
</button>
<h4>Transaction</h4>
</div>
<section>
<div id="transaction_top" class="grid gap-1-5">
<div id="transaction_detail__icon"></div>
@ -388,21 +412,21 @@
<div id="transaction_detail__type"></div>
<h3 id="transaction_detail__amount"></h3>
</div>
<div class="flex align-center space-between">
<time id="transaction_detail__time"></time>
<div id="transaction_detail__status"></div>
</div>
</div>
<div id="transaction__steps"></div>
</section>
</article>
<article id="account" class="page hide-completely page-layout">
<button class="icon-button justify-self-start" onclick="history.back()">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
clip-rule="evenodd" />
</svg>
</button>
<div class="flex align-center page__header">
<button class="justify-self-start button__icon--left" onclick="history.back()">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z"
clip-rule="evenodd" />
</svg>
</button>
<h4>Account</h4>
</div>
<section id="account_details">
<div id="account_top" class="grid gap-1-5">
<div class="flex align-center space-between">
@ -439,15 +463,12 @@
</template>
<template id="account_template">
<a class="activity-card activity-card--account interact">
<div class="flex align-start space-between">
<div class="activity-card__icon"></div>
<span class="activity-card__status status-tag"></span>
</div>
<div class="grid">
<div class="activity-card__icon"></div>
<div class="grid gap-0-5">
<div class="activity-card__type"></div>
<h4 class="activity-card__amount"></h4>
<time class="activity-card__time"></time>
</div>
<time class="activity-card__time"></time>
<h4 class="activity-card__amount"></h4>
</a>
</template>
<template id="account_step_template">
@ -601,33 +622,6 @@
})
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (isPassword)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = cancelText;
buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
return;
}
buttons[1].onclick = () => {
let value = input.value;
hidePopup()
resolve(value)
}
})
}
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound = false } = options
@ -785,6 +779,9 @@
case 'account':
showAccountDetails(params)
break;
case 'result':
showActionResult(params)
break;
}
document.querySelector('.page:not(.hide-completely)')?.classList.add('hide-completely')
getRef(pageId)?.classList.remove('hide-completely')
@ -809,7 +806,7 @@
if (pagesData.openedSubPages.includes(subPageId)) {
accountLoader.reset()
} else {
accountLoader = new LazyLoader('#user_accounts', bank_app.accounts.reverse(), render.accountCard, { batchSize: 10 })
accountLoader = new LazyLoader('#user_accounts', getAccounts(), render.accountCard, { batchSize: 10 })
accountLoader.init()
}
break;
@ -869,6 +866,7 @@
this.lazyContainer = document.querySelector(container)
this.update = this.update.bind(this)
this.render = this.render.bind(this)
this.init = this.init.bind(this)
this.clear = this.clear.bind(this)
@ -897,7 +895,10 @@
childList: true,
})
this.render()
console.log(this.arrayOfElements.length)
}
update(arrayOfElements) {
this.arrayOfElements = arrayOfElements
this.render()
}
render(options = {}) {
let { lazyLoad = false } = options
@ -912,7 +913,7 @@
this.updateEndIndex = this.arrayOfElements.length > this.batchSize ? this.batchSize : this.arrayOfElements.length
}
for (let index = this.updateStartIndex; index < this.updateEndIndex; index++) {
frag.append(this.renderFn(this.arrayOfElements[index], index))
frag.append(this.renderFn(this.arrayOfElements[index]))
}
this.lazyContainer.append(frag)
}
@ -928,7 +929,7 @@
</script>
<script id="ui_functions">
const utils = {
getArrayOfObj(obj) {
getArrayOfObj(obj = {}) {
const arrayOfObj = []
for (key in obj) {
arrayOfObj.push({ id: key, ...obj[key] });
@ -1016,9 +1017,9 @@
},
responseCard(responseDetails) {
const { id, requestID, reason = 'none', rtype, status = 'pending' } = responseDetails
let { amount = undefined, index = undefined } = bank_app.viewAllRequests()[requestID]
let { amount, index = undefined } = bank_app.viewAllRequests()[requestID]
if (!amount) {
amount = bank_app.accounts[index].amount
amount = bank_app.getUserDetails(myFloID).accounts[index].amount
}
const timestamp = id.split('_')[0]
const card = getRef('response_template').content.cloneNode(true).firstElementChild
@ -1041,21 +1042,24 @@
card.querySelector('.activity-card__icon').innerHTML = icon
card.querySelector('.activity-card__icon').classList.add(status)
card.querySelector('.activity-card__title').textContent = `${action} ${status === 'success' ? 'approved' : 'failed'}`
card.querySelector('.activity-card__description').textContent = `Your request for ${action} of ${amount} was ${status === 'success' ? 'successful' : 'rejected'}`
if (status === 'success') {
card.querySelector('.activity-card__description').textContent = `Your request for ${action} of ${amount.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR' })} was successful`
} else {
card.querySelector('.activity-card__description').textContent = `Reason: ${reason}`
}
card.querySelector('.activity-card__time').textContent = getFormattedTime(timestamp, true)
return card
},
accountCard(accountDetails = {}, index) {
accountCard(accountDetails = {}) {
const { type, status, openTime, closeTime = 0, amount, netAmt } = accountDetails
let index = bank_app.getUserDetails(myFloID).accounts.findIndex(({ openTime: ot }) => ot == openTime)
const card = getRef('account_template').content.cloneNode(true).firstElementChild
const icon = utils.getRelatedIcon(type)
card.setAttribute('href', `#/account?index=${index}`)
card.querySelector('.activity-card__icon').innerHTML = icon
card.querySelector('.activity-card__type').textContent = type
card.querySelector('.activity-card__time').textContent = getFormattedTime(parseInt(openTime))
card.querySelector('.activity-card__time').textContent = getFormattedTime(parseInt(status === 'active' ? openTime : closeTime))
card.querySelector('.activity-card__amount').textContent = netAmt.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR' })
card.querySelector('.activity-card__status').classList.add(status)
card.querySelector('.activity-card__status').textContent = status
return card
},
accountProgressStep(type, title, description = '') {
@ -1091,6 +1095,10 @@
.then(async (res) => {
if (res) {
await floDapps.clearCredentials()
compactIDB.clearData('requests')
compactIDB.clearData('responses')
compactIDB.removeData('appendix', 'lastRequest')
compactIDB.removeData('appendix', 'lastResponse')
onLoadStartUp()
}
})
@ -1106,65 +1114,121 @@
}
function getRequestDetails(requestID) {
let { amount, rtype, index } = bank_app.viewAllRequests()[requestID]
if (!amount) {
amount = bank_app.accounts[index].amount
if (!amount && bank_app.getUserDetails(myFloID).accounts[index]) {
amount = bank_app.getUserDetails(myFloID).accounts[index].amount
}
const transactionDetails = {
index,
amount,
rtype,
requestID: requestID,
timestamp: requestID.split('_')[0],
status: requestResponsePairs[requestID] ? bank_app.viewAllResponses()[requestResponsePairs[requestID]].status : 'pending'
if (amount) {
const transactionDetails = {
index,
amount,
rtype,
requestID: requestID,
timestamp: requestID.split('_')[0],
status: requestResponsePairs[requestID] ? bank_app.viewAllResponses()[requestResponsePairs[requestID]].status : 'pending'
}
return transactionDetails
}
return transactionDetails
}
function getRequests() {
const transactions = bank_app.viewAllRequests()
const responses = bank_app.viewAllResponses()
const requests = []
for (const key in transactions) {
requests.push(getRequestDetails(key))
const details = getRequestDetails(key)
if (details)
requests.push(details)
}
return requests.reverse()
}
function renderRecentTransactions() {
const activityFrag = document.createDocumentFragment()
const recentRequests = getRequests().splice(0, 5)
recentRequests.forEach(request => {
activityFrag.append(render.requestCard(request))
})
getRef('recent_transactions_container').innerHTML = ''
getRef('recent_transactions_container').append(activityFrag)
}
function showTransactionDetails(params) {
const { requestID } = params
const { amount, rtype, timestamp, status, index } = getRequestDetails(requestID)
let type = (rtype === 'openDeposit' || rtype === 'closeDeposit') ? 'deposit' : 'loan'
let type
switch (rtype) {
case 'openDeposit':
type = 'deposit'
break;
case 'closeDeposit':
type = 'withdraw'
break;
case 'openLoan':
type = 'loan'
break;
case 'closeLoan':
type = 'repay'
break;
}
const icon = utils.getRelatedIcon(rtype)
const statusIcon = utils.getRelatedIcon(status)
getRef('transaction_detail__icon').innerHTML = icon
getRef('transaction_detail__status').innerHTML = `${statusIcon} ${status === 'success' ? 'completed' : status}`
getRef('transaction_detail__status').className = `status-tag flex align-center ${status}`
getRef('transaction_detail__type').textContent = type
getRef('transaction_detail__amount').textContent = amount.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR' })
getRef('transaction_detail__time').textContent = getFormattedTime(timestamp)
getRef('transaction__steps').innerHTML = ''
getRef('transaction__steps').append(render.accountProgressStep('success', `Sent ${type} request`, getFormattedTime(timestamp)))
if (requestResponsePairs[requestID]) {
const { status, reason } = bank_app.viewAllResponses()[requestResponsePairs[requestID]]
// Check if response is positive or not
if (status === 'success') {
let action
switch (rtype) {
case 'openDeposit':
action = 'Deposit successful'
break;
case 'closeDeposit':
action = 'Withdraw successful'
break;
case 'openLoan':
type = 'Loan approved'
break;
case 'closeLoan':
type = 'loan repayment complete'
break;
}
getRef('transaction__steps').append(render.accountProgressStep(status, action, getFormattedTime(timestamp)))
getRef('transaction__steps').append(createElement('a', {
textContent: `View ${type} account`,
attributes: { id: 'transaction__cta', href: `#/account?index=${index}` },
className: 'button'
}))
} else {
let action
switch (rtype) {
case 'openDeposit':
action = 'deposit'
break;
case 'closeDeposit':
action = 'withdraw'
break;
case 'openLoan':
type = 'get loan approved'
break;
case 'closeLoan':
type = 'repay loan'
break;
}
getRef('transaction__steps').append(render.accountProgressStep(status, `Failed to ${action}`, reason))
}
} else {
getRef('transaction__steps').append(render.accountProgressStep('pending', `Waiting for ${type} request confirmation`, `You can continue using the app, you will get in-app notification once your request is processed.`))
}
}
function getAccountStatus(index) {
const { status } = bank_app.accounts[index]
const { status } = bank_app.getUserDetails(myFloID).accounts[index]
const allRequests = bank_app.viewAllRequests()
const filteredRequests = {}
const details = {}
// Filter requests related to given index
for (const requestKey in allRequests) {
const { index: requestIndex } = allRequests[requestKey]
if (index == requestIndex) {
filteredRequests[requestKey] = allRequests[requestKey]
}
}
// Remove requests with response
const allResponses = bank_app.viewAllResponses()
for (const responseKey in allResponses) {
const { requestID } = allResponses[responseKey]
@ -1184,7 +1248,7 @@
}
function renderAccountProgress(index) {
const { type, status, openTime, closeTime = 0, amount, netAmt } = bank_app.accounts[index]
const { type, status, openTime, closeTime = 0, amount, netAmt } = bank_app.getUserDetails(myFloID).accounts[index]
getRef('account_process__steps').innerHTML = ''
getRef('account_process__steps').append(render.accountProgressStep('success', type === "deposit" ? 'Deposited' : 'Got loan', getFormattedTime(openTime)))
const { isPending, pendingRequest } = getAccountStatus(index)
@ -1205,9 +1269,18 @@
}
}
getRef('accounts_status_selector').addEventListener('change', e => {
accountLoader.update(getAccounts())
})
function getAccounts() {
const currentStatus = getRef('accounts_status_selector').value
return bank_app.getUserDetails(myFloID).accounts.filter(({ status }) => status === currentStatus).reverse()
}
function showAccountDetails(params) {
const { index } = params
const { type, status, openTime, closeTime = 0, amount, netAmt } = bank_app.accounts[index]
const { type, status, openTime, closeTime = 0, amount, netAmt } = bank_app.getUserDetails(myFloID).accounts[index]
const icon = utils.getRelatedIcon(type)
getRef('account_detail__icon').innerHTML = icon
@ -1227,7 +1300,7 @@
async function processAccount() {
const { index } = pagesData.params
const { type, netAmt } = bank_app.accounts[index]
const { type, netAmt } = bank_app.getUserDetails(myFloID).accounts[index]
let ans
if (type === 'deposit') {
ans = await getConfirmation('Withdraw deposit?', 'Are you sure to withdraw this deposit now?')
@ -1353,14 +1426,16 @@
function showActionResult(details = {}) {
const { type, amount, status, reason = '' } = details
getRef('result__icon').innerHTML = utils.getRelatedIcon(status)
if (type === 'deposit') {
getRef('result__title').textContent = 'Sent deposit request'
getRef('result__description').textContent = 'Waiting for deposit confirmation. Meanwhile you can go back and continue using app.'
} else if (type === 'loan') {
getRef('result__title').textContent = 'Sent loan request'
getRef('result__description').textContent = 'Waiting for loan confirmation. Meanwhile you can go back and continue using app.'
getRef('result__icon').className = status
getRef('result__back_button').href = `#/${type}`
if (status === 'pending') {
getRef('result__title').textContent = `Sent ${type} request`
getRef('result__description').textContent = `Waiting for ${type} confirmation. Meanwhile you can go back and continue using app.`
} else if (status === 'failed') {
getRef('result__title').textContent = `Failed to send ${type} request`
getRef('result__description').textContent = reason
}
showPage('result')
getRef(`get_${type}_amount`).value = ''
}
async function initDeposit() {
@ -1369,19 +1444,10 @@
if (confirm) {
bank_app.makeDeposit(amount)
.then(() => {
showActionResult({
type: 'deposit',
amount,
status: 'pending'
})
window.location.hash = `#/result?type=deposit&amount=${amount}&status=pending`
})
.catch(err => {
showActionResult({
type: 'deposit',
amount,
status: 'failed',
reason: err
})
window.location.hash = `#/result?type=deposit&amount=${amount}&status=failed&reason=${err}`
})
}
}
@ -1391,19 +1457,10 @@
if (confirm) {
bank_app.requestLoan(amount)
.then(() => {
showActionResult({
type: 'loan',
amount,
status: 'pending'
})
window.location.hash = `#/result?type=loan&amount=${amount}&status=pending`
})
.catch(err => {
showActionResult({
type: 'loan',
amount,
status: 'failed',
reason: err
})
window.location.hash = `#/result?type=loan&amount=${amount}&status=failed&reason=${err}`
})
}
}
@ -1425,6 +1482,7 @@
delete floDapps.util.startUpFunctions.loadDataFromAppIDB;
floDapps.launchStartUp().then(result => {
console.log(result);
getRef('user_flo_id').value = myFloID
// alert(`Welcome FLO_ID: ${myFloID}`);
//App functions....
bank_app.launchApp(DummyCallBack, DummyCallBack)
@ -11375,27 +11433,29 @@
},
getUserDetails: function (floID) {
let accList = this.accMap[floID]
let result = {
const result = {
accounts: [],
depositTotal: 0,
loanTotal: 0
}
accList.forEach(i => {
let acc = this.accounts[i]
result.accounts.push(acc)
if (acc.status === "active")
switch (acc.type) {
case "deposit":
result.depositTotal += acc.netAmt;
break;
case "loan":
result.loanTotal += acc.netAmt;
break;
}
})
//Might need to add net interest calculations
result.netTotal = result.depositTotal - result.loanTotal;
if (this.accMap[floID]) {
let accList = this.accMap[floID]
accList.forEach(i => {
let acc = this.accounts[i]
result.accounts.push(acc)
if (acc.status === "active")
switch (acc.type) {
case "deposit":
result.depositTotal += acc.netAmt;
break;
case "loan":
result.loanTotal += acc.netAmt;
break;
}
})
//Might need to add net interest calculations
result.netTotal = result.depositTotal - result.loanTotal;
}
return result
},