UI/UX and feature update

-- implemented new UI for portfolio assets deposit/withdraw/transfer and view asset specific history
-- minor bug fixes
This commit is contained in:
sairaj mote 2022-06-04 16:51:23 +05:30
parent d076a69cea
commit 2c344c4614
5 changed files with 435 additions and 291 deletions

View File

@ -22,6 +22,7 @@ body {
--background-color: 241, 243, 248; --background-color: 241, 243, 248;
--danger-color: rgb(255, 75, 75); --danger-color: rgb(255, 75, 75);
--green: #1cad59; --green: #1cad59;
--yellow: #bd7200;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-gutter: stable; scrollbar-gutter: stable;
color: rgba(var(--text-color), 1); color: rgba(var(--text-color), 1);
@ -36,6 +37,7 @@ body[data-theme=dark] {
--background-color: 21, 22, 22; --background-color: 21, 22, 22;
--danger-color: rgb(255, 106, 106); --danger-color: rgb(255, 106, 106);
--green: #00e676; --green: #00e676;
--yellow: #ffeb3b;
} }
body[data-theme=dark] sm-popup::part(popup) { body[data-theme=dark] sm-popup::part(popup) {
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
@ -1070,18 +1072,6 @@ sm-checkbox {
width: min(32rem, 100%); width: min(32rem, 100%);
} }
.portfolio_actions__wrapper {
grid-column: 1/-1;
justify-content: flex-end;
gap: 0.3rem;
padding-top: 1rem;
}
.portfolio_actions__wrapper .button {
color: var(--accent-color);
padding: 0.5rem 0.8rem;
flex-shrink: 0;
}
.label { .label {
font-size: 0.8rem; font-size: 0.8rem;
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
@ -1100,20 +1090,28 @@ sm-checkbox {
align-items: center; align-items: center;
gap: 0 0.5rem; gap: 0 0.5rem;
padding: 1rem; padding: 1rem;
padding-left: 0.6rem;
border-radius: 0.3rem; border-radius: 0.3rem;
color: inherit;
background-color: rgba(var(--text-color), 0.03); background-color: rgba(var(--text-color), 0.03);
} }
.balance-card.is-locked { .balance-card.is-locked {
grid-template-columns: auto auto 1fr auto; grid-template-columns: auto 1fr auto;
} }
.balance-card.is-locked .balance-card__icon { .balance-card.is-locked .balance-card__icon {
grid-row: span 2; grid-row: span 2;
} }
.balance-card:not(.is-locked) { .balance-card.is-locked .balance-card__right-arrow {
grid-template-columns: auto auto 1fr auto auto; grid-area: 1/3/3/4;
} }
.balance-card input { .balance-card.is-locked .balance-card__amount-wrapper {
align-self: center; grid-area: 2/2/3/3;
}
.balance-card:not(.is-locked) {
grid-template-columns: auto 1fr auto auto;
}
.balance-card:not(.is-locked) .balance-card__right-arrow {
grid-area: 1/4/2/5;
} }
.balance-card__icon { .balance-card__icon {
display: flex; display: flex;
@ -1142,6 +1140,12 @@ sm-checkbox {
.balance-card__amount-wrapper > :nth-child(even) { .balance-card__amount-wrapper > :nth-child(even) {
text-align: right; text-align: right;
} }
.balance-card__right-arrow {
background-color: rgba(var(--text-color), 0.1);
border-radius: 1rem;
padding: 0.1rem;
fill: var(--accent-color);
}
#history { #history {
padding-top: 0 !important; padding-top: 0 !important;
@ -1153,44 +1157,47 @@ sm-checkbox {
background-color: rgba(var(--background-color), 1); background-color: rgba(var(--background-color), 1);
} }
#exchange_history {
margin-top: 0.5rem;
}
.history-entry { .history-entry {
display: grid; display: grid;
grid-template-columns: 1fr auto; grid-template-columns: auto 1fr auto;
gap: 0.5rem; gap: 0.5rem 1rem;
align-items: center; align-items: center;
padding: 1rem;
background-color: rgba(var(--text-color), 0.03);
border-radius: 0.3rem;
margin-bottom: 0.5rem;
}
.history-entry:last-of-type {
margin-bottom: 2rem; margin-bottom: 2rem;
} }
.history-entry > :nth-child(2) { .history-entry[data-status=SUCCESS] .history-entry__status .icon {
text-align: right; fill: var(--green);
}
.history-entry[data-status=PENDING] .history-entry__status .icon, .history-entry[data-status=WAITING_CONFIRMATION] .history-entry__status .icon {
fill: var(--yellow);
} }
.history-entry__status { .history-entry__status {
justify-self: flex-start; display: flex;
font-size: 0.75rem; align-items: center;
background-color: rgba(var(--text-color), 0.06); justify-content: center;
padding: 0.3rem 0.5rem; grid-row: 1/3;
border-radius: 1rem; width: 2.5rem;
letter-spacing: 0.05em; height: 2.5rem;
margin-left: 0.5rem; background-color: rgba(var(--text-color), 0.03);
border-radius: 2rem;
} }
.history-entry .history-entry__amount-wrapper { .history-entry__token-action {
font-weight: 500; font-weight: 500;
} }
.history-entry[data-type=deposit] .history-entry__amount { .history-entry__amount {
font-weight: 500;
text-align: right;
}
.history-entry[data-type=deposit] .history-entry__amount:not(:empty) {
color: var(--green); color: var(--green);
} }
.history-entry[data-type=deposit] .history-entry__amount::before { .history-entry[data-type=deposit] .history-entry__amount:not(:empty)::before {
content: "+ "; content: "+ ";
} }
.history-entry[data-type=withdraw] .history-entry__amount { .history-entry[data-type=withdraw] .history-entry__amount:not(:empty)::before {
color: var(--danger-color);
}
.history-entry[data-type=withdraw] .history-entry__amount::before {
content: "- "; content: "- ";
} }
.history-entry__time { .history-entry__time {
@ -1202,6 +1209,17 @@ sm-checkbox {
font-size: 0.9rem; font-size: 0.9rem;
} }
#portfolio_asset_page .sticky {
margin-top: -1.5rem;
margin-left: -0.7rem;
padding: 1rem 0;
background-color: rgba(var(--background-color), 1);
}
#portfolio_asset__history {
margin-top: 1rem;
}
#portfolio_cards_wrapper { #portfolio_cards_wrapper {
display: grid; display: grid;
gap: 0.5rem; gap: 0.5rem;
@ -1463,10 +1481,6 @@ sm-checkbox {
align-self: center; align-self: center;
} }
#main_header {
padding: 1.5rem;
}
#user_popup_button { #user_popup_button {
width: 100%; width: 100%;
} }
@ -1664,7 +1678,8 @@ sm-checkbox {
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
} }
#history .sticky { #history .sticky,
#portfolio_asset_page .sticky {
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -22,6 +22,7 @@ body {
--background-color: 241, 243, 248; --background-color: 241, 243, 248;
--danger-color: rgb(255, 75, 75); --danger-color: rgb(255, 75, 75);
--green: #1cad59; --green: #1cad59;
--yellow: #bd7200;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-gutter: stable; scrollbar-gutter: stable;
color: rgba(var(--text-color), 1); color: rgba(var(--text-color), 1);
@ -36,6 +37,7 @@ body[data-theme="dark"] {
--background-color: 21, 22, 22; --background-color: 21, 22, 22;
--danger-color: rgb(255, 106, 106); --danger-color: rgb(255, 106, 106);
--green: #00e676; --green: #00e676;
--yellow: #ffeb3b;
sm-popup::part(popup) { sm-popup::part(popup) {
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
} }
@ -965,17 +967,6 @@ sm-checkbox {
align-content: flex-start; align-content: flex-start;
width: min(32rem, 100%); width: min(32rem, 100%);
} }
.portfolio_actions__wrapper {
grid-column: 1/-1;
justify-content: flex-end;
gap: 0.3rem;
padding-top: 1rem;
.button {
color: var(--accent-color);
padding: 0.5rem 0.8rem;
flex-shrink: 0;
}
}
.label { .label {
font-size: 0.8rem; font-size: 0.8rem;
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
@ -992,19 +983,27 @@ sm-checkbox {
align-items: center; align-items: center;
gap: 0 0.5rem; gap: 0 0.5rem;
padding: 1rem; padding: 1rem;
padding-left: 0.6rem;
border-radius: 0.3rem; border-radius: 0.3rem;
color: inherit;
background-color: rgba(var(--text-color), 0.03); background-color: rgba(var(--text-color), 0.03);
&.is-locked { &.is-locked {
grid-template-columns: auto auto 1fr auto; grid-template-columns: auto 1fr auto;
.balance-card__icon { .balance-card__icon {
grid-row: span 2; grid-row: span 2;
} }
.balance-card__right-arrow {
grid-area: 1/3/3/4;
}
.balance-card__amount-wrapper {
grid-area: 2/2/3/3;
}
} }
&:not(.is-locked) { &:not(.is-locked) {
grid-template-columns: auto auto 1fr auto auto; grid-template-columns: auto 1fr auto auto;
.balance-card__right-arrow {
grid-area: 1/4/2/5;
} }
input {
align-self: center;
} }
&__icon { &__icon {
display: flex; display: flex;
@ -1033,6 +1032,12 @@ sm-checkbox {
text-align: right; text-align: right;
} }
} }
&__right-arrow {
background-color: rgba(var(--text-color), 0.1);
border-radius: 1rem;
padding: 0.1rem;
fill: var(--accent-color);
}
} }
#history { #history {
padding-top: 0 !important; padding-top: 0 !important;
@ -1043,35 +1048,49 @@ sm-checkbox {
background-color: rgba(var(--background-color), 1); background-color: rgba(var(--background-color), 1);
} }
} }
#exchange_history {
margin-top: 0.5rem;
}
.history-entry { .history-entry {
display: grid; display: grid;
grid-template-columns: 1fr auto; grid-template-columns: auto 1fr auto;
gap: 0.5rem; gap: 0.5rem 1rem;
align-items: center; align-items: center;
padding: 1rem;
background-color: rgba(var(--text-color), 0.03);
border-radius: 0.3rem;
margin-bottom: 0.5rem;
&:last-of-type {
margin-bottom: 2rem; margin-bottom: 2rem;
&[data-status="SUCCESS"] {
.history-entry__status {
.icon {
fill: var(--green);
}
}
}
&[data-status="PENDING"],
&[data-status="WAITING_CONFIRMATION"] {
.history-entry__status {
.icon {
fill: var(--yellow);
}
} }
& > :nth-child(2) {
text-align: right;
} }
&__status { &__status {
justify-self: flex-start; display: flex;
font-size: 0.75rem; align-items: center;
background-color: rgba(var(--text-color), 0.06); justify-content: center;
padding: 0.3rem 0.5rem; grid-row: 1/3;
border-radius: 1rem; width: 2.5rem;
letter-spacing: 0.05em; height: 2.5rem;
margin-left: 0.5rem; background-color: rgba(var(--text-color), 0.03);
border-radius: 2rem;
} }
.history-entry__amount-wrapper { &__token-action {
font-weight: 500; font-weight: 500;
} }
&__amount {
font-weight: 500;
text-align: right;
}
&[data-type="deposit"] { &[data-type="deposit"] {
.history-entry__amount { .history-entry__amount:not(:empty) {
color: var(--green); color: var(--green);
&::before { &::before {
content: "+ "; content: "+ ";
@ -1079,8 +1098,7 @@ sm-checkbox {
} }
} }
&[data-type="withdraw"] { &[data-type="withdraw"] {
.history-entry__amount { .history-entry__amount:not(:empty) {
color: var(--danger-color);
&::before { &::before {
content: "- "; content: "- ";
} }
@ -1095,6 +1113,19 @@ sm-checkbox {
font-size: 0.9rem; font-size: 0.9rem;
} }
} }
#portfolio_asset_page {
.sticky {
margin-top: -1.5rem;
margin-left: -0.7rem;
padding: 1rem 0;
background-color: rgba(var(--background-color), 1);
}
}
#portfolio_asset__actions {
}
#portfolio_asset__history {
margin-top: 1rem;
}
#portfolio_cards_wrapper { #portfolio_cards_wrapper {
display: grid; display: grid;
gap: 0.5rem; gap: 0.5rem;
@ -1315,7 +1346,7 @@ sm-checkbox {
align-self: center; align-self: center;
} }
#main_header { #main_header {
padding: 1.5rem; // padding: 1.5rem;
} }
#user_popup_button { #user_popup_button {
width: 100%; width: 100%;
@ -1491,7 +1522,8 @@ sm-checkbox {
.orders_section__header { .orders_section__header {
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
} }
#history { #history,
#portfolio_asset_page {
.sticky { .sticky {
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--foreground-color), 1);
} }

View File

@ -20,6 +20,7 @@
<script src="scripts/floTokenAPI.js"></script> <script src="scripts/floTokenAPI.js"></script>
<script src="scripts/floExchangeAPI.js"></script> <script src="scripts/floExchangeAPI.js"></script>
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script> <script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
<script src="//unpkg.com/uhtml"></script>
<script> <script>
const DEFAULT_TRADE_PRICE_DEVIATION_BUY = 15 / 100; const DEFAULT_TRADE_PRICE_DEVIATION_BUY = 15 / 100;
const DEFAULT_TRADE_PRICE_DEVIATION_SELL = 10 / 100; const DEFAULT_TRADE_PRICE_DEVIATION_SELL = 10 / 100;
@ -74,7 +75,7 @@
</div> </div>
</div> </div>
<theme-toggle id="theme_toggle"></theme-toggle> <theme-toggle id="theme_toggle"></theme-toggle>
<button id="user_popup_button" class="hide user-content button--small" onclick="showPopup('user_popup')"> <button id="user_popup_button" class="hide user-content button--small">
<svg xmlns="http://www.w3.org/2000/svg" class="icon margin-right-0-5" height="24px" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" class="icon margin-right-0-5" height="24px" viewBox="0 0 24 24"
width="24px" fill="#000000"> width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" /> <path d="M0 0h24v24H0V0z" fill="none" />
@ -104,7 +105,7 @@
</div> </div>
<div class="grid gap-0-5"> <div class="grid gap-0-5">
<p>Don't have FLO credentials?</p> <p>Don't have FLO credentials?</p>
<sm-button onclick="showPopup('sign_up_popup')">Generate FLO credentials</sm-button> <sm-button id="sign_up_button">Generate FLO credentials</sm-button>
</div> </div>
<sm-button onclick="floExchangeAPI.clearAllLocalData()">Reset</sm-button> <sm-button onclick="floExchangeAPI.clearAllLocalData()">Reset</sm-button>
</sm-form> </sm-form>
@ -186,8 +187,7 @@
</div> </div>
<div id="trade_button_wrapper" <div id="trade_button_wrapper"
class="stateful-button-wrapper flex align-center justify-center"> class="stateful-button-wrapper flex align-center justify-center">
<sm-button id="trade_button" class="uppercase w-100" variant="primary" <sm-button id="trade_button" class="uppercase w-100" variant="primary">BUY FLO
onclick="showPopup('confirm_trade_popup')">BUY FLO
</sm-button> </sm-button>
</div> </div>
</sm-form> </sm-form>
@ -327,7 +327,8 @@
</div> </div>
</div> </div>
</div> </div>
<div id="portfolio" class="grid mobile-page hide"> <div id="portfolio" class="mobile-page hide">
<div class="grid gap-1-5">
<div class="flex align-center space-between"> <div class="flex align-center space-between">
<strip-select id="portfolio_pages_selector"> <strip-select id="portfolio_pages_selector">
<strip-option value="exchange" selected>Exchange</strip-option> <strip-option value="exchange" selected>Exchange</strip-option>
@ -362,7 +363,8 @@
d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" /> d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
</svg> </svg>
<p class="banner"> <p class="banner">
Your assets on exchange remains separate until they are withdrawn to your Your assets on exchange remains separate until they are withdrawn to
your
FLO FLO
ID. ID.
</p> </p>
@ -370,21 +372,31 @@
</div> </div>
</div> </div>
<p>Deposit rupee from your FLO ID to exchange to purchase assets.</p> <p>Deposit rupee from your FLO ID to exchange to purchase assets.</p>
<div class="grid gap-1">
<div id="exchange_rupee_balance"></div>
<div class="grid">
<div class="flex align-center space-between">
<span class="label">Tradable assets</span>
<span class="label">Quantity | value</span>
</div>
<fieldset id="my_assets" class="grid"></fieldset> <fieldset id="my_assets" class="grid"></fieldset>
</div> </div>
</div> </div>
</div>
</div>
<div class="grid gap-1 hide"> <div class="grid gap-1 hide">
<div class="flex align-center space-between"> <div class="flex align-center space-between">
<h4>Assets in <span class="my-flo-id"></span></h4> <h4>Assets in <span class="my-flo-id"></span></h4>
<div class="tooltip"> <div class="tooltip">
<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"
width="24px" fill="#000000"> viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" /> <path d="M0 0h24v24H0V0z" fill="none" />
<path <path
d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" /> d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
</svg> </svg>
<p class="banner"> <p class="banner">
You need to have rupee tokens in your FLO ID to purchase assets, which then can be You need to have rupee tokens in your FLO ID to purchase assets, which then can
be
deposited deposited
to your exchange account. to your exchange account.
</p> </p>
@ -394,8 +406,8 @@
<div class="grid gap-0-5 personal-asset-balance"> <div class="grid gap-0-5 personal-asset-balance">
<div class="flex align-center"> <div class="flex align-center">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" <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" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24"
fill="#000000"> width="24px" fill="#000000">
<g> <g>
<rect fill="none" height="24" width="24" /> <rect fill="none" height="24" width="24" />
</g> </g>
@ -423,8 +435,8 @@
</div> </div>
<div class="grid gap-0-5 personal-asset-balance"> <div class="grid gap-0-5 personal-asset-balance">
<div class="flex align-center"> <div class="flex align-center">
<svg class="icon flo-icon" width="64" height="64" viewBox="0 0 64 64" fill="none" <svg class="icon flo-icon" width="64" height="64" viewBox="0 0 64 64"
xmlns="http://www.w3.org/2000/svg"> fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="path-1-outside-1_16_6" maskUnits="userSpaceOnUse" x="3" y="3" <mask id="path-1-outside-1_16_6" maskUnits="userSpaceOnUse" x="3" y="3"
width="58" height="58"> width="58" height="58">
<rect fill="white" x="3" y="3" width="58" height="58" /> <rect fill="white" x="3" y="3" width="58" height="58" />
@ -445,6 +457,39 @@
</div> </div>
</div> </div>
</div> </div>
<div id="portfolio_asset_page" class="hide grid gap-1-5">
<div class="flex align-center sticky top-0">
<a href="#/portfolio" class="button icon-only">
<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="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path>
</svg>
</a>
<b id="portfolio_asset__name"></b>
</div>
<div id="portfolio_asset__balance" class="flex flex-direction-column gap-0-5"></div>
<fieldset id="portfolio_asset__actions" class="flex gap-0-3">
<button class="button flex-1" value="deposit">
Deposit
</button>
<button class="button flex-1" value="withdraw">
Withdraw
</button>
<button class="button flex-1" value="transfer">
Transfer
</button>
</fieldset>
<div>
<h4>History</h4>
<ul id="portfolio_asset__history" class="observe-empty-state"></ul>
<div class="empty-state">
<p>No transactions to see</p>
</div>
</div>
</div>
</div>
<div id="history" class="mobile-page hide"> <div id="history" class="mobile-page hide">
<div class="flex align-center sticky top-0"> <div class="flex align-center sticky top-0">
<a href="#/portfolio" class="button icon-only"> <a href="#/portfolio" class="button icon-only">
@ -688,7 +733,7 @@
<sm-popup id="confirm_trade_popup"> <sm-popup id="confirm_trade_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()"> <button class="popup__header__close">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <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 fill="none" d="M0 0h24v24H0z" />
<path <path
@ -704,7 +749,7 @@
</sm-popup> </sm-popup>
<sm-popup id="user_popup"> <sm-popup id="user_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()"> <button class="popup__header__close">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <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 fill="none" d="M0 0h24v24H0z" />
<path <path
@ -733,7 +778,7 @@
</sm-popup> </sm-popup>
<sm-popup id="sign_up_popup"> <sm-popup id="sign_up_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()"> <button class="popup__header__close">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <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 fill="none" d="M0 0h24v24H0z" />
<path <path
@ -761,7 +806,7 @@
</sm-popup> </sm-popup>
<sm-popup id="portfolio_popup"> <sm-popup id="portfolio_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()"> <button class="popup__header__close">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <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 fill="none" d="M0 0h24v24H0z" />
<path <path
@ -812,7 +857,7 @@
</sm-popup> </sm-popup>
<sm-popup id="transaction_info_popup"> <sm-popup id="transaction_info_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()"> <button class="popup__header__close">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <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 fill="none" d="M0 0h24v24H0z" />
<path <path
@ -847,14 +892,18 @@
</li> </li>
</template> </template>
<template id="asset_balance_card_template"> <template id="asset_balance_card_template">
<label class="balance-card interact"> <a class="balance-card interact">
<input type="radio" name="exchange-assets">
<div class="balance-card__icon"></div> <div class="balance-card__icon"></div>
<h4 class="balance-card__token"></h4> <h4 class="balance-card__token"></h4>
</label> <svg class="icon balance-card__right-arrow" 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="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path>
</svg>
</a>
</template> </template>
<template id="net_balance_template"> <template id="net_balance_template">
<span class="available-balance"></span> <span class="available-balance text-align-right"></span>
</template> </template>
<template id="locked_balance_template"> <template id="locked_balance_template">
<div class="grid balance-card__amount-wrapper"> <div class="grid balance-card__amount-wrapper">
@ -1026,19 +1075,13 @@
</template> </template>
<template id="history_entry"> <template id="history_entry">
<li class="history-entry"> <li class="history-entry">
<div class="flex align-center">
<span class="history-entry__type capitalize"></span>
<span class="history-entry__status"></span> <span class="history-entry__status"></span>
</div> <span class="history-entry__token-action capitalize"></span>
<b class="history-entry__amount-wrapper">
<span class="history-entry__amount"></span> <span class="history-entry__amount"></span>
<span class="history-entry__token"></span>
</b>
<time class="history-entry__time"></time> <time class="history-entry__time"></time>
<a class="history-entry__txid" target="_blank">See on blockchain</a> <a class="history-entry__txid" target="_blank">See on blockchain</a>
</li> </li>
</template> </template>
<script src="//unpkg.com/uhtml"></script>
<script> <script>
/** /**
@ -1126,9 +1169,26 @@
}; };
} }
// adds a class to all elements in an array
function addClass(elements, className) {
elements.forEach((element) => {
document.querySelector(element).classList.add(className);
});
}
// removes a class from all elements in an array
function removeClass(elements, className) {
elements.forEach((element) => {
document.querySelector(element).classList.remove(className);
});
}
// return querySelectorAll elements as an array
function getAllElements(selector) {
return Array.from(document.querySelectorAll(selector));
}
let zIndex = 10 let zIndex = 10
// function required for popups or modals to appear // function required for popups or modals to appear
function showPopup(popupId, pinned) { function openPopup(popupId, pinned) {
zIndex++ zIndex++
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`) getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
getRef(popupId).show({ pinned }) getRef(popupId).show({ pinned })
@ -1136,7 +1196,7 @@
} }
// hides the popup or modal // hides the popup or modal
function hidePopup() { function closePopup() {
if (popupStack.peek() === undefined) if (popupStack.peek() === undefined)
return; return;
popupStack.peek().popup.hide() popupStack.peek().popup.hide()
@ -1146,7 +1206,7 @@
const getConfirmation = (title, options = {}) => { const getConfirmation = (title, options = {}) => {
return new Promise(resolve => { return new Promise(resolve => {
const { message, cancelText = 'Cancel', confirmText = 'OK' } = options const { message, cancelText = 'Cancel', confirmText = 'OK' } = options
showPopup('confirmation_popup', true) openPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title; getRef('confirm_title').textContent = title;
getRef('confirm_message').textContent = message; getRef('confirm_message').textContent = message;
let cancelButton = getRef('confirmation_popup').children[2].children[0], let cancelButton = getRef('confirmation_popup').children[2].children[0],
@ -1154,11 +1214,11 @@
submitButton.textContent = confirmText submitButton.textContent = confirmText
cancelButton.textContent = cancelText cancelButton.textContent = cancelText
submitButton.onclick = () => { submitButton.onclick = () => {
hidePopup() closePopup()
resolve(true); resolve(true);
} }
cancelButton.onclick = () => { cancelButton.onclick = () => {
hidePopup() closePopup()
resolve(false); resolve(false);
} }
}) })
@ -1167,7 +1227,7 @@
// displays a popup for asking user input. Use this instead of JS prompt // displays a popup for asking user input. Use this instead of JS prompt
function getPromptInput(title, message = '', options = {}) { function getPromptInput(title, message = '', options = {}) {
const { isPassword = true, cancelText = 'Cancel', confirmText = 'OK' } = options const { isPassword = true, cancelText = 'Cancel', confirmText = 'OK' } = options
showPopup('prompt_popup', true) openPopup('prompt_popup', true)
getRef('prompt_title').textContent = title; getRef('prompt_title').textContent = title;
getRef('prompt_message').textContent = message; getRef('prompt_message').textContent = message;
let buttons = getRef('prompt_popup').querySelectorAll("sm-button"); let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
@ -1178,12 +1238,12 @@
buttons[1].textContent = confirmText; buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
buttons[0].onclick = () => { buttons[0].onclick = () => {
hidePopup() closePopup()
return (null); return (null);
} }
buttons[1].onclick = () => { buttons[1].onclick = () => {
const value = getRef('prompt_input').value; const value = getRef('prompt_input').value;
hidePopup() closePopup()
resolve(value) resolve(value)
} }
}) })
@ -1245,7 +1305,7 @@
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex) document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex)
document.addEventListener('keyup', (e) => { document.addEventListener('keyup', (e) => {
if (e.key === 'Escape') { if (e.key === 'Escape') {
hidePopup() closePopup()
} }
}) })
document.addEventListener('copy', () => { document.addEventListener('copy', () => {
@ -1256,6 +1316,11 @@
createRipple(e, e.target.closest("button, sm-button, .interact")); createRipple(e, e.target.closest("button, sm-button, .interact"));
} }
}); });
document.querySelectorAll('.popup__header__close, .close-popup-on-click').forEach(elem => {
elem.addEventListener('click', () => {
closePopup()
})
})
}); });
function createRipple(event, target) { function createRipple(event, target) {
const circle = document.createElement("span"); const circle = document.createElement("span");
@ -1354,18 +1419,14 @@
animateTo(getRef('main_header'), slideOutLeft, animOptions) animateTo(getRef('main_header'), slideOutLeft, animOptions)
animateTo(getRef('main_navbar'), slideOutLeft, animOptions) animateTo(getRef('main_navbar'), slideOutLeft, animOptions)
animateTo(getRef('asset_list_wrapper'), slideOutLeft, animOptions).onfinish = () => { animateTo(getRef('asset_list_wrapper'), slideOutLeft, animOptions).onfinish = () => {
getRef('main_header').classList.add('hide-on-mobile') addClass(['#main_header', '#asset_list_wrapper', '#main_navbar'], 'hide-on-mobile')
getRef('main_navbar').classList.add('hide-on-mobile') removeClass(['#asset_page'], 'hide-on-mobile')
getRef('asset_list_wrapper').classList.add('hide-on-mobile')
getRef('asset_page').classList.remove('hide-on-mobile')
animateTo(getRef('asset_page'), slideInLeft, animOptions) animateTo(getRef('asset_page'), slideInLeft, animOptions)
} }
} }
} else { } else {
getRef('main_header').classList.add('hide-on-mobile') addClass(['#main_header', '#asset_list_wrapper', '#main_navbar'], 'hide-on-mobile')
getRef('main_navbar').classList.add('hide-on-mobile') removeClass(['#asset_page'], 'hide-on-mobile')
getRef('asset_list_wrapper').classList.add('hide-on-mobile')
getRef('asset_page').classList.remove('hide-on-mobile')
} }
if (!chart) { if (!chart) {
@ -1404,6 +1465,56 @@
case 'market': case 'market':
break; break;
case 'portfolio': case 'portfolio':
if (params.asset) {
getRef('portfolio_asset__name').textContent = params.asset
const { net, locked } = allTokens[params.asset]
const lockedBalance = params.asset === 'rupee' ? formatAmount(locked, true) : toFixed(locked)
showChildElement('portfolio', 1, {
entry: slideInLeft,
exit: slideOutLeft,
})
renderElem(getRef('portfolio_asset__balance'), html`
<div class="grid">
<span class="label">Available</span>
<b style="font-size:2rem">${params.asset === 'rupee' ? formatAmount(net, true) : toFixed(net)}</b>
${params.asset !== 'rupee' ? html`<span style="font-size: 1rem; opacity:0.8">₹${toFixed(net * floGlobals.exchangeRates[params.asset], 2)}</span>` : ''}
</div>
${locked ? html`
<div class="grid">
<span class="label">Locked</span>
<b style="font-size:2rem">${lockedBalance}</b>
</div>`: ''}
`)
getRef('portfolio_asset__history').innerHTML = `
<div class="flex" style="padding: 1.5rem; justify-content: center;">
<sm-spinner></sm-spinner>
</div>`
// load asset specific blockchain txs
floBlockchainAPI.readAllTxs(accountDetails.floID).then(async transactions => {
floGlobals.allTxs = {}
transactions.forEach(({ txid, time }) => { floGlobals.allTxs[txid] = { time } })
floExchangeAPI.getUserTransacts(accountDetails.floID, await proxy.secret).then(exchangeTxs => {
exchangeTxs = exchangeTxs.filter(tx => tx.token === params.asset).sort((a, b) => floGlobals.allTxs[b.txid].time - floGlobals.allTxs[a.txid].time)
if (portfolioAssetHistoryLazyLoader) {
portfolioAssetHistoryLazyLoader.update(exchangeTxs)
} else {
portfolioAssetHistoryLazyLoader = new LazyLoader('#portfolio_asset__history', exchangeTxs, render.historyEntry)
}
portfolioAssetHistoryLazyLoader.init()
}).catch(err => {
console.error(err)
})
}).catch(err => {
console.error(err)
})
} else {
showChildElement('portfolio', 0, {
entry: slideInRight,
exit: slideOutRight,
})
if (portfolioAssetHistoryLazyLoader)
portfolioAssetHistoryLazyLoader.clear()
}
break; break;
case 'history': case 'history':
getRef('exchange_history').innerHTML = ` getRef('exchange_history').innerHTML = `
@ -1415,12 +1526,12 @@
floBlockchainAPI.readAllTxs(accountDetails.floID).then(async transactions => { floBlockchainAPI.readAllTxs(accountDetails.floID).then(async transactions => {
floGlobals.allTxs = {} floGlobals.allTxs = {}
transactions.forEach(({ txid, time }) => { floGlobals.allTxs[txid] = { time } }) transactions.forEach(({ txid, time }) => { floGlobals.allTxs[txid] = { time } })
floExchangeAPI.getUserTransacts(accountDetails.floID, await proxy.secret).then(transactions => { floExchangeAPI.getUserTransacts(accountDetails.floID, await proxy.secret).then(exchangeTxs => {
transactions = transactions.sort((a, b) => floGlobals.allTxs[b.txid].time - floGlobals.allTxs[a.txid].time) exchangeTxs = exchangeTxs.sort((a, b) => floGlobals.allTxs[b.txid].time - floGlobals.allTxs[a.txid].time)
if (historyLazyLoader) { if (historyLazyLoader) {
historyLazyLoader.update(transactions) historyLazyLoader.update(exchangeTxs)
} else { } else {
historyLazyLoader = new LazyLoader('#exchange_history', transactions, render.historyEntry) historyLazyLoader = new LazyLoader('#exchange_history', exchangeTxs, render.historyEntry)
} }
historyLazyLoader.init() historyLazyLoader.init()
}).catch(err => { }).catch(err => {
@ -1436,6 +1547,10 @@
if (historyLazyLoader) if (historyLazyLoader)
historyLazyLoader.clear() historyLazyLoader.clear()
} }
if (pageId !== 'portfolio') {
if (portfolioAssetHistoryLazyLoader)
portfolioAssetHistoryLazyLoader.clear()
}
if (pagesData.lastPage !== pageId) { if (pagesData.lastPage !== pageId) {
document.querySelectorAll('.mobile-page').forEach(elem => elem.classList.add('hide')) document.querySelectorAll('.mobile-page').forEach(elem => elem.classList.add('hide'))
getRef(pageId).classList.remove('hide') getRef(pageId).classList.remove('hide')
@ -1569,6 +1684,7 @@
if (document.visibilityState === "hidden") { if (document.visibilityState === "hidden") {
// code if page is hidden // code if page is hidden
} else { } else {
if (floGlobals.exchangeApiLoaded)
updateRate(); updateRate();
} }
} }
@ -1583,7 +1699,8 @@
{ opacity: 0 } { opacity: 0 }
] ]
function showChildElement(id, index, { mobileView = false, entry, exit }) { function showChildElement(id, index, options = {}) {
const { mobileView = false, entry, exit } = options
const animOptions = { const animOptions = {
duration: 150, duration: 150,
easing: 'ease', easing: 'ease',
@ -1739,6 +1856,7 @@
} }
let marketTradesLazyLoader let marketTradesLazyLoader
let historyLazyLoader let historyLazyLoader
let portfolioAssetHistoryLazyLoader
const render = { const render = {
listedAsset(asset, rate, countDown) { listedAsset(asset, rate, countDown) {
const clone = getRef('listed_asset_template').content.cloneNode(true).firstElementChild const clone = getRef('listed_asset_template').content.cloneNode(true).firstElementChild
@ -1813,24 +1931,22 @@
card.querySelector('.more-info').dataset.seller = seller card.querySelector('.more-info').dataset.seller = seller
return card return card
}, },
assetBalanceCard(asset, isFirst = false) { assetBalanceCard(asset) {
const { net, locked } = allTokens[asset] const { net, locked } = allTokens[asset]
const card = getRef('asset_balance_card_template').content.cloneNode(true).firstElementChild const card = getRef('asset_balance_card_template').content.cloneNode(true).firstElementChild
card.href = `#/portfolio?asset=${asset}`
card.className = `balance-card interact ${locked ? 'is-locked' : ''}` card.className = `balance-card interact ${locked ? 'is-locked' : ''}`
card.querySelector('input').value = asset
card.querySelector('.balance-card__token').textContent = asset card.querySelector('.balance-card__token').textContent = asset
card.querySelector('.balance-card__icon').innerHTML = getIcon(asset) card.querySelector('.balance-card__icon').innerHTML = getIcon(asset)
const templateToClone = locked ? 'locked_balance_template' : 'net_balance_template'; const templateToClone = locked ? 'locked_balance_template' : 'net_balance_template';
const assetBalance = getRef(templateToClone).content.cloneNode(true) const assetBalance = getRef(templateToClone).content.cloneNode(true)
assetBalance.querySelector('.available-balance').textContent = asset === 'rupee' ? formatAmount(net) : parseFloat(net.toFixed(4)) const availableBalance = asset === 'rupee' ? formatAmount(net, true) : `${toFixed(net)} | <span style="font-size: 0.8rem">₹${toFixed(net * floGlobals.exchangeRates[asset], 2)}</span>`
const lockedBalance = asset === 'rupee' ? formatAmount(locked, true) : toFixed(locked)
assetBalance.querySelector('.available-balance').innerHTML = availableBalance
if (locked) { if (locked) {
assetBalance.querySelector('.locked-balance').textContent = asset === 'rupee' ? formatAmount(locked) : parseFloat(locked.toFixed(4)) assetBalance.querySelector('.locked-balance').textContent = lockedBalance
} }
card.appendChild(assetBalance) card.appendChild(assetBalance)
if (isFirst) {
card.querySelector('input').checked = true
card.append(getRef('asset_balance_actions').content.cloneNode(true))
}
return card return card
}, },
chart(asset = 'FLO', duration = '48 weeks') { chart(asset = 'FLO', duration = '48 weeks') {
@ -1964,10 +2080,13 @@
const entry = getRef('history_entry').content.cloneNode(true).firstElementChild const entry = getRef('history_entry').content.cloneNode(true).firstElementChild
entry.dataset.status = status entry.dataset.status = status
entry.dataset.type = type entry.dataset.type = type
entry.querySelector('.history-entry__token').textContent = token if (status === 'SUCCESS') {
entry.querySelector('.history-entry__type').textContent = type entry.querySelector('.history-entry__status').innerHTML = `<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="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>`
} else {
entry.querySelector('.history-entry__status').innerHTML = `<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"><g><rect fill="none" height="24" width="24" x="0"/></g><g><g><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.41,0-8-3.59-8-8s3.59-8,8-8s8,3.59,8,8 S16.41,20,12,20z M12.5,7H11v6l5.2,3.2l0.8-1.3l-4.5-2.7V7z"/></g></g></svg>`
}
entry.querySelector('.history-entry__token-action').textContent = `${type} ${token}`
entry.querySelector('.history-entry__amount').textContent = amount entry.querySelector('.history-entry__amount').textContent = amount
entry.querySelector('.history-entry__status').textContent = status === 'SUCCESS' ? 'Success' : 'Pending'
entry.querySelector('.history-entry__time').textContent = floGlobals.allTxs.hasOwnProperty(txid) ? getFormattedTime(floGlobals.allTxs[txid].time * 1000) : '' entry.querySelector('.history-entry__time').textContent = floGlobals.allTxs.hasOwnProperty(txid) ? getFormattedTime(floGlobals.allTxs[txid].time * 1000) : ''
entry.querySelector('.history-entry__txid').href = `https://flosight.duckdns.org/tx/${txid}` entry.querySelector('.history-entry__txid').href = `https://flosight.duckdns.org/tx/${txid}`
return entry; return entry;
@ -2073,15 +2192,15 @@
render.chart(pagesData.params.asset, e.detail.value === 'hour' ? '48 weeks' : 'all-time') render.chart(pagesData.params.asset, e.detail.value === 'hour' ? '48 weeks' : 'all-time')
}) })
async function tradeAsset() { async function tradeAsset() {
hidePopup() closePopup()
const asset = pagesData.params.asset; const asset = pagesData.params.asset;
const quantity = parseFloat(getRef('get_quantity').value) const quantity = parseFloat(getRef('get_quantity').value)
const price = getSuggestedPrice() const price = getSuggestedPrice()
if (tradeType === 'buy' && accountDetails.sellOrders.some(order => order.asset === asset)) { if (tradeType === 'buy' && accountDetails.sellOrders.some(order => order.asset === asset)) {
hidePopup() closePopup()
return notify('You have an open sell order for this asset. Please close it before buying.', 'error') return notify('You have an open sell order for this asset. Please close it before buying.', 'error')
} else if (tradeType === 'sell' && accountDetails.buyOrders.some(order => order.asset === asset)) { } else if (tradeType === 'sell' && accountDetails.buyOrders.some(order => order.asset === asset)) {
hidePopup() closePopup()
return notify('You have an open buy order for this asset. Please close it before selling.', 'error') return notify('You have an open buy order for this asset. Please close it before selling.', 'error')
} }
showProcess('trade_button_wrapper') showProcess('trade_button_wrapper')
@ -2163,40 +2282,11 @@
} }
}) })
getRef('my_assets').addEventListener('change', e => { getRef('portfolio_asset__actions').addEventListener('click', e => {
const animOptions = {
duration: 150,
easing: 'ease',
fill: 'forwards'
}
const previousActionButton = getRef('my_assets').querySelector('.portfolio_actions__wrapper')
if (previousActionButton) {
previousActionButton.remove()
}
const actionButtons = getRef('asset_balance_actions').content.cloneNode(true)
e.target.closest('.balance-card').append(actionButtons)
const height = e.target.closest('.balance-card').lastElementChild.offsetHeight
e.target.closest('.balance-card').lastElementChild.animate([
{
transform: 'translateY(-0.5rem)',
opacity: 0.5
},
{
transform: 'translateY(0)',
opacity: 1
},
], animOptions)
})
function getPortfolioSelectedAsset() {
return getRef('my_assets').querySelector(':checked').value
}
getRef('my_assets').addEventListener('click', e => {
if (e.target.closest('.button')) { if (e.target.closest('.button')) {
const target = e.target.closest('.button') const target = e.target.closest('.button')
const type = target.value const type = target.value
const asset = getPortfolioSelectedAsset() const asset = pagesData.params.asset
getRef('portfolio_quantity_type').textContent = getRef('quantity_type').textContent = asset === 'rupee' ? formatAmount(allTokens.rupee.net, true) : `${toFixed(allTokens[asset].net)} ${asset}` getRef('portfolio_quantity_type').textContent = getRef('quantity_type').textContent = asset === 'rupee' ? formatAmount(allTokens.rupee.net, true) : `${toFixed(allTokens[asset].net)} ${asset}`
getRef('portfolio_popup__cta').textContent = `${type} ${asset}` getRef('portfolio_popup__cta').textContent = `${type} ${asset}`
@ -2225,7 +2315,7 @@
break; break;
} }
getRef('portfolio_form').elementsChanged() getRef('portfolio_form').elementsChanged()
showPopup('portfolio_popup') openPopup('portfolio_popup')
} }
}) })
function showWalletResult(status, title, description, cta = '') { function showWalletResult(status, title, description, cta = '') {
@ -2283,17 +2373,17 @@
// Get latest balance and exchange rate // Get latest balance and exchange rate
if (e.target.closest('button')) { if (e.target.closest('button')) {
const target = e.target.closest('button') const target = e.target.closest('button')
const asset = getPortfolioSelectedAsset() const asset = pagesData.params.asset
const fraction = parseFloat(target.value) const fraction = parseFloat(target.value)
let total = toFixed(allTokens[asset].net * fraction); let total = toFixed(allTokens[asset].net * fraction);
if (asset == 'FLO' && fraction === 1 & total > 0.1) { if (asset == 'FLO' && fraction === 1 & total > 0.1) {
total -= 0.1; total -= 0.1;
} }
getRef('get_user_amount').value = total getRef('get_user_amount').value = toFixed(total)
} }
}) })
getRef('portfolio_popup__cta').addEventListener('click', async e => { getRef('portfolio_popup__cta').addEventListener('click', async e => {
const asset = getPortfolioSelectedAsset() const asset = pagesData.params.asset
const type = e.target.getAttribute('value') const type = e.target.getAttribute('value')
const quantity = parseFloat(getRef('get_user_amount').value) const quantity = parseFloat(getRef('get_user_amount').value)
try { try {
@ -2450,7 +2540,7 @@
function showMoreDetails(e) { function showMoreDetails(e) {
const target = e.target.closest('.more-info') const target = e.target.closest('.more-info')
showPopup('transaction_info_popup') openPopup('transaction_info_popup')
renderElem(getRef('transaction_details'), html` renderElem(getRef('transaction_details'), html`
${target.dataset.buyer !== 'undefined' ? html`<div class="grid"> ${target.dataset.buyer !== 'undefined' ? html`<div class="grid">
<h5 class="label capitalize">Buyer</h5> <h5 class="label capitalize">Buyer</h5>
@ -2791,6 +2881,8 @@
document.body.classList.add('is-signed-in'); document.body.classList.add('is-signed-in');
getRef('market_asset_rates').parentNode.remove() getRef('market_asset_rates').parentNode.remove()
getRef("login_form").classList.add('hide') getRef("login_form").classList.add('hide')
getRef('user_popup_button').addEventListener('click', () => openPopup('user_popup'));
getRef('trade_button').addEventListener('click', () => openPopup('confirm_trade_popup'));
accountDetails = acc accountDetails = acc
console.debug(acc); console.debug(acc);
//Element display //Element display
@ -2831,11 +2923,14 @@
const frag = document.createDocumentFragment(); const frag = document.createDocumentFragment();
let totalPortfolio = 0; let totalPortfolio = 0;
Object.entries(allTokens).sort((a, b) => b[1].net - a[1].net).forEach(([asset], index) => { Object.entries(allTokens).sort((a, b) => b[1].net - a[1].net).forEach(([asset], index) => {
frag.append(render.assetBalanceCard(asset, index === 0)) if (asset !== floGlobals.currency) {
if (asset !== floGlobals.currency)
totalPortfolio += allTokens[asset].net * floGlobals.exchangeRates[asset] totalPortfolio += allTokens[asset].net * floGlobals.exchangeRates[asset]
else frag.append(render.assetBalanceCard(asset))
totalPortfolio += allTokens[asset].net }
else {
getRef('exchange_rupee_balance').innerHTML = ``
getRef('exchange_rupee_balance').append(render.assetBalanceCard(asset))
}
}) })
getRef('my_assets').innerHTML = '' getRef('my_assets').innerHTML = ''
getRef('my_assets').append(frag) getRef('my_assets').append(frag)
@ -2903,7 +2998,9 @@
}; };
window.addEventListener('load', e => { window.addEventListener('load', e => {
getRef('sign_up_button').addEventListener('click', () => openPopup('sign_up_popup'))
floExchangeAPI.init().then(nodes => { floExchangeAPI.init().then(nodes => {
floGlobals.exchangeApiLoaded = true
console.log(nodes); console.log(nodes);
refresh(true); refresh(true);
}).catch(error => console.error(error)) }).catch(error => console.error(error))

View File

@ -1272,7 +1272,7 @@ customElements.define('sm-popup', class extends HTMLElement {
this.popupContainer = this.shadowRoot.querySelector('.popup-container'); this.popupContainer = this.shadowRoot.querySelector('.popup-container');
this.backdrop = this.shadowRoot.querySelector('.background'); this.backdrop = this.shadowRoot.querySelector('.background');
this.popup = this.shadowRoot.querySelector('.popup'); this.dialogBox = this.shadowRoot.querySelector('.popup');
this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot'); this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot');
this.popupHeader = this.shadowRoot.querySelector('.popup-top'); this.popupHeader = this.shadowRoot.querySelector('.popup-top');
@ -1317,7 +1317,7 @@ customElements.define('sm-popup', class extends HTMLElement {
easing: 'ease' easing: 'ease'
} }
const initialAnimation = (window.innerWidth > 640) ? 'scale(1.1)' : `translateY(${this.offset ? `${this.offset}px` : '100%'})` const initialAnimation = (window.innerWidth > 640) ? 'scale(1.1)' : `translateY(${this.offset ? `${this.offset}px` : '100%'})`
this.animateTo(this.popup, [ this.animateTo(this.dialogBox, [
{ {
opacity: this.offset ? 1 : 0, opacity: this.offset ? 1 : 0,
transform: initialAnimation transform: initialAnimation
@ -1382,7 +1382,7 @@ customElements.define('sm-popup', class extends HTMLElement {
{ opacity: 1 }, { opacity: 1 },
{ opacity: 0 } { opacity: 0 }
], animOptions) ], animOptions)
this.animateTo(this.popup, [ this.animateTo(this.dialogBox, [
{ {
opacity: 1, opacity: 1,
transform: (window.innerWidth > 640) ? 'none' : `translateY(${this.offset ? `${this.offset}px` : '0'})` transform: (window.innerWidth > 640) ? 'none' : `translateY(${this.offset ? `${this.offset}px` : '0'})`
@ -1394,7 +1394,7 @@ customElements.define('sm-popup', class extends HTMLElement {
], animOptions).finished ], animOptions).finished
.finally(() => { .finally(() => {
this.popupContainer.classList.add('hide'); this.popupContainer.classList.add('hide');
this.popup.style = '' this.dialogBox.style = ''
this.removeAttribute('open'); this.removeAttribute('open');
if (this.forms.length) { if (this.forms.length) {
@ -1434,7 +1434,7 @@ customElements.define('sm-popup', class extends HTMLElement {
if (this.touchStartY < e.changedTouches[0].clientY) { if (this.touchStartY < e.changedTouches[0].clientY) {
this.offset = e.changedTouches[0].clientY - this.touchStartY; this.offset = e.changedTouches[0].clientY - this.touchStartY;
this.touchEndAnimation = window.requestAnimationFrame(() => { this.touchEndAnimation = window.requestAnimationFrame(() => {
this.popup.style.transform = `translateY(${this.offset}px)`; this.dialogBox.style.transform = `translateY(${this.offset}px)`;
}); });
} }
} }
@ -1443,7 +1443,7 @@ customElements.define('sm-popup', class extends HTMLElement {
this.touchEndTime = e.timeStamp; this.touchEndTime = e.timeStamp;
cancelAnimationFrame(this.touchEndAnimation); cancelAnimationFrame(this.touchEndAnimation);
this.touchEndY = e.changedTouches[0].clientY; this.touchEndY = e.changedTouches[0].clientY;
this.threshold = this.popup.getBoundingClientRect().height * 0.3; this.threshold = this.dialogBox.getBoundingClientRect().height * 0.3;
if (this.touchEndTime - this.touchStartTime > 200) { if (this.touchEndTime - this.touchStartTime > 200) {
if (this.touchEndY - this.touchStartY > this.threshold) { if (this.touchEndY - this.touchStartY > this.threshold) {
if (this.pinned) { if (this.pinned) {