Added wallet deposit/withdraw UI
This commit is contained in:
parent
75879ca2f5
commit
5a67beb249
@ -1,11 +0,0 @@
|
||||
{
|
||||
"secret": "Secret_For_Session__Enter_A_Strong_String(Text/Password)",
|
||||
"blockchain_id": "FLO_ID_of_the_admin",
|
||||
"blockchain_private": "Private_Key_of_the_Admin",
|
||||
"port": "8080",
|
||||
|
||||
"sql_user": "mySQL_user",
|
||||
"sql_pwd": "mySQL_password",
|
||||
"sql_db": "supernode",
|
||||
"sql_host": "localhost"
|
||||
}
|
||||
@ -418,7 +418,7 @@ input{
|
||||
color: var(--accent-color)
|
||||
}
|
||||
:host([variant="outlined"]) .input {
|
||||
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 0.4) inset;
|
||||
box-shadow: 0 0 0 0.1rem var(--border-color, rgba(var(--text-color), 0.4)) inset;
|
||||
background: rgba(var(--background-color), 1);
|
||||
}
|
||||
:host([variant="outlined"]) .label {
|
||||
@ -2207,3 +2207,405 @@ class SlideButton extends HTMLElement {
|
||||
|
||||
window.customElements.define('slide-button', SlideButton);
|
||||
|
||||
const smSelect = document.createElement('template')
|
||||
smSelect.innerHTML = `
|
||||
<style>
|
||||
*{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host{
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
--accent-color: #4d2588;
|
||||
--text-color: 17, 17, 17;
|
||||
--background-color: 255, 255, 255;
|
||||
--max-height: auto;
|
||||
--min-width: 100%;
|
||||
}
|
||||
:host([disabled]) .select{
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.hide{
|
||||
display: none !important;
|
||||
}
|
||||
.select{
|
||||
position: relative;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.icon {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
fill: rgba(var(--text-color), 0.7);
|
||||
}
|
||||
.selected-option-text{
|
||||
font-size: 0.9rem;
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.selection{
|
||||
border-radius: 0.3rem;
|
||||
display: -ms-grid;
|
||||
display: grid;
|
||||
-ms-grid-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas: 'heading heading' '. .';
|
||||
padding: 0.4rem 1rem;
|
||||
background: rgba(var(--text-color), 0.06);
|
||||
border: solid 1px rgba(var(--text-color), 0.2);
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
}
|
||||
.selection:focus{
|
||||
-webkit-box-shadow: 0 0 0 0.1rem var(--accent-color);
|
||||
box-shadow: 0 0 0 0.1rem var(--accent-color)
|
||||
}
|
||||
.icon{
|
||||
margin-left: 1rem;
|
||||
}
|
||||
:host([align-select="left"]) .options{
|
||||
left: 0;
|
||||
}
|
||||
:host([align-select="right"]) .options{
|
||||
right: 0;
|
||||
}
|
||||
.options{
|
||||
top: 100%;
|
||||
margin-top: 0.2rem;
|
||||
overflow: hidden auto;
|
||||
position: absolute;
|
||||
grid-area: options;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
min-width: var(--min-width);
|
||||
max-height: var(--max-height);
|
||||
background: rgba(var(--background-color), 1);
|
||||
border: solid 1px rgba(var(--text-color), 0.2);
|
||||
border-radius: 0.3rem;
|
||||
z-index: 2;
|
||||
-webkit-box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
|
||||
box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
|
||||
}
|
||||
.rotate{
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg)
|
||||
}
|
||||
@media (any-hover: hover){
|
||||
::-webkit-scrollbar{
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb{
|
||||
background: rgba(var(--text-color), 0.3);
|
||||
border-radius: 1rem;
|
||||
&:hover{
|
||||
background: rgba(var(--text-color), 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="select" >
|
||||
<div class="selection">
|
||||
<div class="selected-option-text"></div>
|
||||
<svg class="icon toggle" 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 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"/></svg>
|
||||
</div>
|
||||
<div part="options" class="options hide">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>`;
|
||||
customElements.define('sm-select', class extends HTMLElement {
|
||||
constructor() {
|
||||
super()
|
||||
this.attachShadow({
|
||||
mode: 'open'
|
||||
}).append(smSelect.content.cloneNode(true))
|
||||
|
||||
this.reset = this.reset.bind(this)
|
||||
this.open = this.open.bind(this)
|
||||
this.collapse = this.collapse.bind(this)
|
||||
this.toggle = this.toggle.bind(this)
|
||||
this.handleOptionsNavigation = this.handleOptionsNavigation.bind(this)
|
||||
this.handleOptionSelection = this.handleOptionSelection.bind(this)
|
||||
this.handleKeydown = this.handleKeydown.bind(this)
|
||||
this.handleClickOutside = this.handleClickOutside.bind(this)
|
||||
|
||||
this.availableOptions
|
||||
this.previousOption
|
||||
this.isOpen = false;
|
||||
this.slideDown = [{
|
||||
transform: `translateY(-0.5rem)`,
|
||||
opacity: 0
|
||||
},
|
||||
{
|
||||
transform: `translateY(0)`,
|
||||
opacity: 1
|
||||
}
|
||||
]
|
||||
this.slideUp = [{
|
||||
transform: `translateY(0)`,
|
||||
opacity: 1
|
||||
},
|
||||
{
|
||||
transform: `translateY(-0.5rem)`,
|
||||
opacity: 0
|
||||
}
|
||||
]
|
||||
this.animationOptions = {
|
||||
duration: 300,
|
||||
fill: "forwards",
|
||||
easing: 'ease'
|
||||
}
|
||||
|
||||
this.optionList = this.shadowRoot.querySelector('.options')
|
||||
this.chevron = this.shadowRoot.querySelector('.toggle')
|
||||
this.selection = this.shadowRoot.querySelector('.selection')
|
||||
this.selectedOptionText = this.shadowRoot.querySelector('.selected-option-text')
|
||||
}
|
||||
static get observedAttributes() {
|
||||
return ['value', 'disabled']
|
||||
}
|
||||
get value() {
|
||||
return this.getAttribute('value')
|
||||
}
|
||||
set value(val) {
|
||||
this.setAttribute('value', val)
|
||||
}
|
||||
|
||||
reset(fire = true) {
|
||||
if (this.availableOptions[0] && this.previousOption !== this.availableOptions[0]) {
|
||||
const firstElement = this.availableOptions[0];
|
||||
if (this.previousOption) {
|
||||
this.previousOption.classList.remove('check-selected')
|
||||
}
|
||||
firstElement.classList.add('check-selected')
|
||||
this.value = firstElement.getAttribute('value')
|
||||
this.selectedOptionText.textContent = firstElement.textContent
|
||||
this.previousOption = firstElement;
|
||||
if (fire) {
|
||||
this.fireEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open() {
|
||||
this.optionList.classList.remove('hide')
|
||||
this.optionList.animate(this.slideDown, this.animationOptions)
|
||||
this.chevron.classList.add('rotate')
|
||||
this.isOpen = true
|
||||
}
|
||||
collapse() {
|
||||
this.chevron.classList.remove('rotate')
|
||||
this.optionList.animate(this.slideUp, this.animationOptions)
|
||||
.onfinish = () => {
|
||||
this.optionList.classList.add('hide')
|
||||
this.isOpen = false
|
||||
}
|
||||
}
|
||||
toggle() {
|
||||
if (!this.isOpen && !this.hasAttribute('disabled')) {
|
||||
this.open()
|
||||
} else {
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
|
||||
fireEvent() {
|
||||
this.dispatchEvent(new CustomEvent('change', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
value: this.value
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
handleOptionsNavigation(e) {
|
||||
if (e.code === 'ArrowUp') {
|
||||
e.preventDefault()
|
||||
if (document.activeElement.previousElementSibling) {
|
||||
document.activeElement.previousElementSibling.focus()
|
||||
} else {
|
||||
this.availableOptions[this.availableOptions.length - 1].focus()
|
||||
}
|
||||
}
|
||||
else if (e.code === 'ArrowDown') {
|
||||
e.preventDefault()
|
||||
if (document.activeElement.nextElementSibling) {
|
||||
document.activeElement.nextElementSibling.focus()
|
||||
} else {
|
||||
this.availableOptions[0].focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
handleOptionSelection(e) {
|
||||
if (this.previousOption !== document.activeElement) {
|
||||
this.value = document.activeElement.getAttribute('value')
|
||||
this.selectedOptionText.textContent = document.activeElement.textContent;
|
||||
this.fireEvent()
|
||||
if (this.previousOption) {
|
||||
this.previousOption.classList.remove('check-selected')
|
||||
}
|
||||
document.activeElement.classList.add('check-selected')
|
||||
this.previousOption = document.activeElement
|
||||
}
|
||||
}
|
||||
handleClick(e) {
|
||||
if (e.target === this) {
|
||||
this.toggle()
|
||||
}
|
||||
else {
|
||||
this.handleOptionSelection()
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
handleKeydown(e) {
|
||||
if (e.target === this) {
|
||||
if (this.isOpen && e.code === 'ArrowDown') {
|
||||
e.preventDefault()
|
||||
this.availableOptions[0].focus()
|
||||
this.handleOptionSelection(e)
|
||||
}
|
||||
else if (e.code === 'Enter' || e.code === 'Space') {
|
||||
e.preventDefault()
|
||||
this.toggle()
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.handleOptionsNavigation(e)
|
||||
this.handleOptionSelection(e)
|
||||
if (e.code === 'Enter' || e.code === 'Space') {
|
||||
e.preventDefault()
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
}
|
||||
handleClickOutside(e) {
|
||||
if (this.isOpen && !this.contains(e.target)) {
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
connectedCallback() {
|
||||
this.setAttribute('role', 'listbox')
|
||||
if (!this.hasAttribute('disabled')) {
|
||||
this.selection.setAttribute('tabindex', '0')
|
||||
}
|
||||
let slot = this.shadowRoot.querySelector('slot')
|
||||
slot.addEventListener('slotchange', e => {
|
||||
this.availableOptions = slot.assignedElements()
|
||||
this.reset(false)
|
||||
});
|
||||
this.addEventListener('click', this.handleClick)
|
||||
this.addEventListener('keydown', this.handleKeydown)
|
||||
document.addEventListener('mousedown', this.handleClickOutside)
|
||||
}
|
||||
disconnectedCallback() {
|
||||
this.removeEventListener('click', this.toggle)
|
||||
this.removeEventListener('keydown', this.handleKeydown)
|
||||
document.removeEventListener('mousedown', this.handleClickOutside)
|
||||
}
|
||||
attributeChangedCallback(name) {
|
||||
if (name === "disabled") {
|
||||
if (this.hasAttribute('disabled')) {
|
||||
this.selection.removeAttribute('tabindex')
|
||||
} else {
|
||||
this.selection.setAttribute('tabindex', '0')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// option
|
||||
const smOption = document.createElement('template')
|
||||
smOption.innerHTML = `
|
||||
<style>
|
||||
*{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host{
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
.option{
|
||||
display: grid;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
min-width: 100%;
|
||||
gap: 0.5rem;
|
||||
grid-template-columns: max-content minmax(0, 1fr);
|
||||
padding: 0.8rem 1.2rem;
|
||||
cursor: pointer;
|
||||
overflow-wrap: break-word;
|
||||
outline: none;
|
||||
user-select: none;
|
||||
}
|
||||
:host(:focus){
|
||||
outline: none;
|
||||
background: rgba(var(--text-color), 0.1);
|
||||
}
|
||||
.icon {
|
||||
opacity: 0;
|
||||
height: 1.2rem;
|
||||
width: 1.2rem;
|
||||
fill: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
:host(:focus) .option .icon{
|
||||
opacity: 0.4
|
||||
}
|
||||
:host(.check-selected) .icon{
|
||||
opacity: 1
|
||||
}
|
||||
@media (hover: hover){
|
||||
.option:hover{
|
||||
background: rgba(var(--text-color), 0.1);
|
||||
}
|
||||
:host(:not(.check-selected):hover) .icon{
|
||||
opacity: 0.4
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="option">
|
||||
<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 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>
|
||||
<slot></slot>
|
||||
</div>`;
|
||||
customElements.define('sm-option', class extends HTMLElement {
|
||||
constructor() {
|
||||
super()
|
||||
this.attachShadow({
|
||||
mode: 'open'
|
||||
}).append(smOption.content.cloneNode(true))
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.setAttribute('role', 'option')
|
||||
this.setAttribute('tabindex', '0')
|
||||
}
|
||||
})
|
||||
|
||||
@ -376,24 +376,29 @@ ul {
|
||||
fill: var(--accent-color);
|
||||
}
|
||||
|
||||
#confirmation_popup {
|
||||
#confirmation_popup,
|
||||
#prompt_popup {
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
#confirmation_popup h4 {
|
||||
#confirmation_popup h4,
|
||||
#prompt_popup h4 {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#confirmation_popup sm-button {
|
||||
#confirmation_popup sm-button,
|
||||
#prompt_popup sm-button {
|
||||
margin: 0;
|
||||
}
|
||||
#confirmation_popup .flex {
|
||||
#confirmation_popup .flex,
|
||||
#prompt_popup .flex {
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#confirmation_popup .flex sm-button:first-of-type {
|
||||
#confirmation_popup .flex sm-button:first-of-type,
|
||||
#prompt_popup .flex sm-button:first-of-type {
|
||||
margin-right: 0.6rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
@ -405,6 +410,22 @@ button:active,
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
padding: 0 1.5rem 0 0.5rem;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
|
||||
.popup__header__close {
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#main_page {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
@ -571,12 +592,11 @@ strip-option:last-of-type {
|
||||
#home {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
#main_header {
|
||||
padding: 1.5rem;
|
||||
padding: 1.8rem 1.5rem;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
-webkit-box-align: center;
|
||||
@ -589,7 +609,7 @@ strip-option:last-of-type {
|
||||
--width: min(24rem, 100%);
|
||||
-ms-flex-item-align: start;
|
||||
align-self: flex-start;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
#quantity_selector .button {
|
||||
@ -611,22 +631,48 @@ strip-option:last-of-type {
|
||||
min-width: 8ch;
|
||||
}
|
||||
|
||||
#orders_section {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
#user_section {
|
||||
gap: 1.5rem;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1.5rem;
|
||||
-ms-flex-line-pack: start;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.wallet_actions__wrapper {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.wallet_actions__wrapper .button {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
gap: 0.3rem 1rem;
|
||||
padding: 0.5rem 0;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.balance-card.is-locked {
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
.balance-card.is-locked .label {
|
||||
font-size: 0.8rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
.balance-card:not(.is-locked) {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
.balance-card__icon {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
@ -649,27 +695,58 @@ strip-option:last-of-type {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.balance-card__amount {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
.balance-card__amount-wrapper {
|
||||
grid-column: span 2;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.balance-card__actions {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.balance-card__actions .button {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
.balance-card__amount-wrapper > :nth-child(even) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
.loader-button-wrapper {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
position: relative;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.loader-button-wrapper sm-button,
|
||||
.loader-button-wrapper slide-button {
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
-webkit-transition: -webkit-clip-path 0.3s;
|
||||
transition: -webkit-clip-path 0.3s;
|
||||
transition: clip-path 0.3s;
|
||||
transition: clip-path 0.3s, -webkit-clip-path 0.3s;
|
||||
-webkit-clip-path: circle(100%);
|
||||
clip-path: circle(100%);
|
||||
}
|
||||
.loader-button-wrapper sm-button.clip,
|
||||
.loader-button-wrapper slide-button.clip {
|
||||
pointer-events: none;
|
||||
-webkit-clip-path: circle(0);
|
||||
clip-path: circle(0);
|
||||
}
|
||||
.loader-button-wrapper sm-spinner {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 40rem) {
|
||||
sm-button {
|
||||
--padding: 0.9rem 1.6rem;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 640px) {
|
||||
@media screen and (min-width: 40rem) {
|
||||
sm-popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
|
||||
.h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
@ -686,6 +763,10 @@ strip-option:last-of-type {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
padding: 1rem 1.5rem 0 0.5rem;
|
||||
}
|
||||
|
||||
#confirmation_popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
@ -694,25 +775,30 @@ strip-option:last-of-type {
|
||||
grid-template-columns: 1fr 90vw 1fr;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1024px) {
|
||||
@media screen and (min-width: 64rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 80vw 1fr;
|
||||
}
|
||||
|
||||
#home {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
padding: 1.5vmax 3vmax;
|
||||
grid-template-columns: 24rem minmax(0, 1fr) 20rem;
|
||||
grid-template-rows: auto 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#main_header {
|
||||
grid-column: span 3;
|
||||
#home > * {
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--foreground-color);
|
||||
border: solid thin rgba(var(--text-color), 0.1);
|
||||
}
|
||||
|
||||
.hide-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1920px) {
|
||||
@media screen and (min-width: 120rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 70vw 1fr;
|
||||
}
|
||||
|
||||
2
public/css/main.min.css
vendored
2
public/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -341,22 +341,19 @@ ul {
|
||||
fill: var(--accent-color);
|
||||
}
|
||||
}
|
||||
#confirmation_popup {
|
||||
#confirmation_popup,
|
||||
#prompt_popup {
|
||||
flex-direction: column;
|
||||
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
sm-button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.flex {
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
|
||||
sm-button:first-of-type {
|
||||
margin-right: 0.6rem;
|
||||
margin-left: auto;
|
||||
@ -370,6 +367,20 @@ button:active,
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
padding: 0 1.5rem 0 0.5rem;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
|
||||
.popup__header__close {
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#main_page {
|
||||
padding: 1.5rem;
|
||||
|
||||
@ -517,12 +528,11 @@ strip-option {
|
||||
#home {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
#main_header {
|
||||
padding: 1.5rem;
|
||||
padding: 1.8rem 1.5rem;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
@ -532,7 +542,7 @@ strip-option {
|
||||
#trade_form {
|
||||
--width: min(24rem, 100%);
|
||||
align-self: flex-start;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
#quantity_selector {
|
||||
.button {
|
||||
@ -551,19 +561,41 @@ strip-option {
|
||||
font-weight: 500;
|
||||
min-width: 8ch;
|
||||
}
|
||||
#orders_section {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
#user_section {
|
||||
gap: 1.5rem;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1.5rem;
|
||||
align-content: flex-start;
|
||||
}
|
||||
.user_section__header {
|
||||
}
|
||||
.wallet_actions__wrapper {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
.button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.balance-card {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 0.3rem 1rem;
|
||||
padding: 0.5rem 0;
|
||||
border-radius: 0.5rem;
|
||||
&.is-locked {
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 1rem;
|
||||
.label {
|
||||
font-size: 0.8rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
}
|
||||
&:not(.is-locked) {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
&__icon {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
@ -581,25 +613,44 @@ strip-option {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
&__amount {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
&__actions {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
.button {
|
||||
flex: 1;
|
||||
&__amount-wrapper {
|
||||
grid-column: span 2;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
& > :nth-child(even) {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 640px) {
|
||||
.loader-button-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
sm-button,
|
||||
slide-button {
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
transition: clip-path 0.3s;
|
||||
clip-path: circle(100%);
|
||||
&.clip {
|
||||
pointer-events: none;
|
||||
clip-path: circle(0);
|
||||
}
|
||||
}
|
||||
sm-spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 40rem) {
|
||||
sm-button {
|
||||
--padding: 0.9rem 1.6rem;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 640px) {
|
||||
@media screen and (min-width: 40rem) {
|
||||
sm-popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
.h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
@ -615,6 +666,9 @@ strip-option {
|
||||
.h4 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.popup__header {
|
||||
padding: 1rem 1.5rem 0 0.5rem;
|
||||
}
|
||||
#confirmation_popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
@ -622,24 +676,28 @@ strip-option {
|
||||
grid-template-columns: 1fr 90vw 1fr;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1024px) {
|
||||
@media screen and (max-width: 64rem) {
|
||||
}
|
||||
@media screen and (min-width: 1024px) {
|
||||
@media screen and (min-width: 64rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 80vw 1fr;
|
||||
}
|
||||
#home {
|
||||
align-items: flex-start;
|
||||
padding: 1.5vmax 3vmax;
|
||||
grid-template-columns: 24rem minmax(0, 1fr) 20rem;
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
#main_header {
|
||||
grid-column: span 3;
|
||||
gap: 1rem;
|
||||
& > * {
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--foreground-color);
|
||||
border: solid thin rgba(var(--text-color), 0.1);
|
||||
}
|
||||
}
|
||||
.hide-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1920px) {
|
||||
@media screen and (min-width: 120rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 70vw 1fr;
|
||||
}
|
||||
|
||||
@ -50,6 +50,15 @@
|
||||
<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="landing" class="page page-layout hide-completely">
|
||||
<header class="flex space-between">
|
||||
<div class="logo">
|
||||
@ -139,48 +148,58 @@
|
||||
<h4>Loading RanchiMall Market</h4>
|
||||
</article>
|
||||
<article id="home" class="page">
|
||||
<header id="main_header">
|
||||
<div class="logo">
|
||||
<svg class="main-logo" viewBox="0 0 27.25 32">
|
||||
<title>RanchiMall</title>
|
||||
<path
|
||||
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z" />
|
||||
</svg>
|
||||
<div class="grid">
|
||||
<h4>RanchiMall Market</h4>
|
||||
<section>
|
||||
<header id="main_header">
|
||||
<div class="logo">
|
||||
<svg class="main-logo" viewBox="0 0 27.25 32">
|
||||
<title>RanchiMall</title>
|
||||
<path
|
||||
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z" />
|
||||
</svg>
|
||||
<div class="grid">
|
||||
<h4>RanchiMall Market</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<theme-toggle></theme-toggle>
|
||||
</header>
|
||||
<sm-form id="trade_form">
|
||||
<theme-toggle></theme-toggle>
|
||||
</header>
|
||||
<sm-form id="trade_form">
|
||||
<div class="flex space-between align-center">
|
||||
<h4>Trade FLO</h4>
|
||||
<strip-select id="trade_type_selector">
|
||||
<strip-option value="buy" selected>Buy</strip-option>
|
||||
<strip-option value="sell">Sell</strip-option>
|
||||
</strip-select>
|
||||
</div>
|
||||
<sm-input id="get_price" variant="outlined" placeholder="Max price" type="number" step="0.00000001"
|
||||
required hiderequired animate>
|
||||
</sm-input>
|
||||
<sm-input id="get_quantity" variant="outlined" placeholder="Quantity" type="number" step="0.00000001"
|
||||
required hiderequired animate>
|
||||
</sm-input>
|
||||
<div id="quantity_selector" class="flex align-center">
|
||||
<span id="quantity_type">Rupee</span>
|
||||
<button class="button" value="25">25%</button>
|
||||
<button class="button" value="50">50%</button>
|
||||
<button class="button" value="75">75%</button>
|
||||
<button class="button" value="100">100%</button>
|
||||
</div>
|
||||
<sm-button id="trade_button" class="uppercase" variant="primary" onclick="tradeFlo()">BUY</sm-button>
|
||||
</sm-form>
|
||||
</section>
|
||||
<section id="orders_section" class="grid gap-1-5">
|
||||
<div class="flex space-between align-center">
|
||||
<h4>Trade FLO</h4>
|
||||
<strip-select id="trade_type_selector">
|
||||
<strip-option value="buy" selected>Buy</strip-option>
|
||||
<strip-option value="sell">Sell</strip-option>
|
||||
<h4>My orders</h4>
|
||||
<strip-select id="orders_scope_selector">
|
||||
<strip-option value="active" selected>Open</strip-option>
|
||||
<strip-option value="completed">Completed</strip-option>
|
||||
</strip-select>
|
||||
</div>
|
||||
<sm-input id="get_price" placeholder="Max price" type="number" step="0.00000001" required hiderequired>
|
||||
</sm-input>
|
||||
<sm-input id="get_quantity" placeholder="Quantity" type="number" step="0.0001" required hiderequired>
|
||||
</sm-input>
|
||||
<div id="quantity_selector" class="flex align-center">
|
||||
<span id="quantity_type">Rupee</span>
|
||||
<button class="button" value="25">25%</button>
|
||||
<button class="button" value="50">50%</button>
|
||||
<button class="button" value="75">75%</button>
|
||||
<button class="button" value="100">100%</button>
|
||||
</div>
|
||||
<sm-button id="trade_button" class="uppercase" variant="primary" onclick="tradeFlo()">BUY</sm-button>
|
||||
</sm-form>
|
||||
<section>
|
||||
<h4>My orders</h4>
|
||||
<div class="table" style="--table-columns: 4;">
|
||||
<div class="table__header table__row">
|
||||
<div></div>
|
||||
<div>Quantity</div>
|
||||
<div>At price</div>
|
||||
<div>Order Placed</div>
|
||||
<div>Order placed</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -195,44 +214,69 @@
|
||||
</svg>
|
||||
My wallet
|
||||
</h4>
|
||||
<div class="balance-card">
|
||||
<div class="balance-card__icon">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M16.36,15.39c1.83,0,4.26-2.49,4.36-4.74-5.65-.19-4.91.47-7.28,2.39,2.19-2.4,1.42-7.79-1.43-10V6.17c2.33,1.49,2.21,5.14,0,7.15-2.23-2-2.27-5.69,0-7.15V3c-2.83,2.26-3.62,7.66-1.44,10-2.36-1.93-1.63-2.58-7.28-2.39.1,2.26,2.55,4.73,4.36,4.74,0,0-1.93.22-2.74-2.62,2.38-.37,4.29-.14,6.28,2-.79-.11-4.89,1.13-4.38,3.26.53.06,3,.3,3.58-.83-.17.18-1.25.5-1.53.05.38-1.39,2.32-2,2.32-2-1,1.82-.48,4.63.82,5.72,1.31-1.08,1.8-3.95.82-5.72,0,0,1.95.6,2.32,2-.29.46-1.36.12-1.53-.05.58,1.14,3.06.88,3.58.83.49-2.17-3.58-3.36-4.38-3.26,2-2.17,3.92-2.39,6.28-2C18.3,15.62,16.36,15.39,16.36,15.39ZM12,19.46c-.91-.79-.5-3,0-3.59C12.5,16.45,12.91,18.66,12,19.46Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="balance-card__token">FLO</div>
|
||||
<div id="flo_balance" class="balance-card__amount"></div>
|
||||
<div class="flex balance-card__actions">
|
||||
<button class="button" onclick="UI_evt.depositFLO();">
|
||||
<div id="wallet_actions">
|
||||
<p>Select asset</p>
|
||||
<sm-select id="wallet_asset_selector">
|
||||
<sm-option value="FLO">FLO</sm-option>
|
||||
<sm-option value="Rupee">Rupee</sm-option>
|
||||
</sm-select>
|
||||
<div class="flex wallet_actions__wrapper">
|
||||
<button class="button" value="deposit">
|
||||
Deposit
|
||||
</button>
|
||||
<button class="button" onclick="UI_evt.withdrawFLO()">
|
||||
<button class="button" value="withdraw">
|
||||
Withdraw
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="balance-card">
|
||||
<div class="balance-card__icon">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M15.3,4.91a4.78,4.78,0,0,0-.39-.5l3.14,0L18.75,2H6L5.25,4.6H9a4.22,4.22,0,0,1,3.06,1,3.16,3.16,0,0,1,.75,1.24H5.93L5.25,9.22h7.62a3.15,3.15,0,0,1-.34.82,3,3,0,0,1-1.37,1.17,5.34,5.34,0,0,1-2.2.4H5.5l0,1.9,7,8.49h3.56v-.17L9.68,14l.09,0a8.07,8.07,0,0,0,3.65-1,5,5,0,0,0,2-2.09A6.29,6.29,0,0,0,16,9.22h2.1l.69-2.42H15.93A5.93,5.93,0,0,0,15.3,4.91Z" />
|
||||
</svg>
|
||||
<div class="grid gap-0-5">
|
||||
<h4>Balance</h4>
|
||||
<div class="balance-card">
|
||||
<div class="balance-card__icon">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M16.36,15.39c1.83,0,4.26-2.49,4.36-4.74-5.65-.19-4.91.47-7.28,2.39,2.19-2.4,1.42-7.79-1.43-10V6.17c2.33,1.49,2.21,5.14,0,7.15-2.23-2-2.27-5.69,0-7.15V3c-2.83,2.26-3.62,7.66-1.44,10-2.36-1.93-1.63-2.58-7.28-2.39.1,2.26,2.55,4.73,4.36,4.74,0,0-1.93.22-2.74-2.62,2.38-.37,4.29-.14,6.28,2-.79-.11-4.89,1.13-4.38,3.26.53.06,3,.3,3.58-.83-.17.18-1.25.5-1.53.05.38-1.39,2.32-2,2.32-2-1,1.82-.48,4.63.82,5.72,1.31-1.08,1.8-3.95.82-5.72,0,0,1.95.6,2.32,2-.29.46-1.36.12-1.53-.05.58,1.14,3.06.88,3.58.83.49-2.17-3.58-3.36-4.38-3.26,2-2.17,3.92-2.39,6.28-2C18.3,15.62,16.36,15.39,16.36,15.39ZM12,19.46c-.91-.79-.5-3,0-3.59C12.5,16.45,12.91,18.66,12,19.46Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="balance-card__token">FLO</div>
|
||||
<div id="flo_balance"></div>
|
||||
</div>
|
||||
<div class="balance-card__token">Rupee</div>
|
||||
<div id="rupee_balance" class="balance-card__amount">₹15402</div>
|
||||
<div class="flex balance-card__actions">
|
||||
<button class="button" onclick="UI_evt.depositRupee()">
|
||||
Deposit
|
||||
</button>
|
||||
<button class="button" onclick="UI_evt.withdrawRupee()">
|
||||
Withdraw
|
||||
</button>
|
||||
<div class="balance-card">
|
||||
<div class="balance-card__icon">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M15.3,4.91a4.78,4.78,0,0,0-.39-.5l3.14,0L18.75,2H6L5.25,4.6H9a4.22,4.22,0,0,1,3.06,1,3.16,3.16,0,0,1,.75,1.24H5.93L5.25,9.22h7.62a3.15,3.15,0,0,1-.34.82,3,3,0,0,1-1.37,1.17,5.34,5.34,0,0,1-2.2.4H5.5l0,1.9,7,8.49h3.56v-.17L9.68,14l.09,0a8.07,8.07,0,0,0,3.65-1,5,5,0,0,0,2-2.09A6.29,6.29,0,0,0,16,9.22h2.1l.69-2.42H15.93A5.93,5.93,0,0,0,15.3,4.91Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="balance-card__token">Rupee</div>
|
||||
<div id="rupee_balance"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
<sm-popup id="wallet_popup">
|
||||
<header slot="header" class="popup__header">
|
||||
<button class="popup__header__close" onclick="hidePopup()">
|
||||
<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="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z" />
|
||||
</svg>
|
||||
</button>
|
||||
<h4 id="wallet_popup__title" class="capitalize"></h4>
|
||||
</header>
|
||||
<sm-form id="wallet_form">
|
||||
<sm-input id="get_user_amount" variant="outlined" placeholder="Quantity" type="number" step="0.00000001"
|
||||
required hiderequired animate>
|
||||
</sm-input>
|
||||
<sm-input id="get_private_key" variant="outlined" placeholder="FLO private key" type="password" required
|
||||
error-text="Invalid private key" hiderequired animate>
|
||||
</sm-input>
|
||||
<div id="wallet_popup__cta_wrapper" class="loader-button-wrapper">
|
||||
<sm-button id="wallet_popup__cta" variant="primary"></sm-button>
|
||||
</div>
|
||||
</sm-form>
|
||||
</sm-popup>
|
||||
<form id="login-form">
|
||||
<fieldset>
|
||||
<legend>Login</legend>
|
||||
@ -247,8 +291,6 @@
|
||||
<fieldset>
|
||||
<legend>Profile</legend>
|
||||
<span id="user_id"></span><br />
|
||||
FLO: <span id="flo_bal"></span><br />
|
||||
Rupee: <span id="rupee_bal"></span><br />
|
||||
<button onclick="proxy.lock();">Add password lock</button><br />
|
||||
<button onclick="UI_evt.logout();">logout</button>
|
||||
<button onclick="toggle_view('my-profile');">Toggle</button>
|
||||
@ -278,7 +320,7 @@
|
||||
<th>Select</th>
|
||||
<th>Quantity</th>
|
||||
<th>Min Price</th>
|
||||
<th>Order Placed</th>
|
||||
<th>Order placed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-type="sell"></tbody>
|
||||
@ -360,6 +402,19 @@
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<template id="net_balance_template">
|
||||
<span class="available-balance"></span>
|
||||
</template>
|
||||
<template id="locked_balance_template">
|
||||
<div>
|
||||
<span class="label">Locked</span>
|
||||
<span class="locked-balance"></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Available</span>
|
||||
<span class="available-balance"></span>
|
||||
</div>
|
||||
</template>
|
||||
<script id="ui_utils">
|
||||
// Global variables
|
||||
const domRefs = {};
|
||||
@ -503,6 +558,34 @@
|
||||
})
|
||||
}
|
||||
|
||||
// displays a popup for asking user input. Use this instead of JS prompt
|
||||
async function getPromptInput(title, message = '', options = {}) {
|
||||
const { isPassword = true, cancelText = 'Cancel', confirmText = 'OK' } = options
|
||||
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
|
||||
@ -742,23 +825,23 @@
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
var user_id; //container for user ID and proxy private-key
|
||||
let user_id; //container for user ID and proxy private-key
|
||||
|
||||
const proxy = {
|
||||
private: null,
|
||||
public: null,
|
||||
lock() {
|
||||
async lock() {
|
||||
if (!this.private)
|
||||
throw "No proxy key found!";
|
||||
let pwd = prompt("Enter password: ");
|
||||
let pwd = await getPromptInput("Enter password", '', { isPassword: true });
|
||||
if (!pwd)
|
||||
alert("Password cannot be empty");
|
||||
notify("Password cannot be empty", 'error');
|
||||
else if (pwd.length < 4)
|
||||
alert("Password minimum length is 4");
|
||||
notify("Password minimum length is 4", 'error');
|
||||
else {
|
||||
let tmp = Crypto.AES.encrypt(this.private, pwd);
|
||||
localStorage.setItem("proxy_secret", "?" + tmp);
|
||||
alert("Successfully locked with Password");
|
||||
notify("Successfully locked with Password", 'success');
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
@ -777,17 +860,18 @@
|
||||
try {
|
||||
let tmp = localStorage.getItem("proxy_secret");
|
||||
if (typeof tmp === "string" && tmp.startsWith("?")) {
|
||||
let pwd = prompt("Enter password: ");
|
||||
if (!pwd)
|
||||
throw "Password Required for making transactions";
|
||||
else {
|
||||
try {
|
||||
tmp = Crypto.AES.decrypt(tmp.substring(1), pwd);
|
||||
} catch (error) {
|
||||
throw "Incorrect Password! Password Required for making transactions";
|
||||
}
|
||||
getPromptInput("Enter password", '', { isPassword: true }).then(pwd => {
|
||||
if (!pwd)
|
||||
throw "Password Required for making transactions";
|
||||
else {
|
||||
try {
|
||||
tmp = Crypto.AES.decrypt(tmp.substring(1), pwd);
|
||||
} catch (error) {
|
||||
throw "Incorrect Password! Password Required for making transactions";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
this.private = tmp;
|
||||
this.public = floCrypto.getPubKeyHex(tmp);
|
||||
@ -865,6 +949,19 @@
|
||||
account();
|
||||
}
|
||||
|
||||
function showBalance(containerId, availableBalance = 0, lockedBalance = 0) {
|
||||
getRef(containerId).innerHTML = ''
|
||||
const templateToClone = lockedBalance ? 'locked_balance_template' : 'net_balance_template';
|
||||
const card = getRef(templateToClone).content.cloneNode(true).firstElementChild
|
||||
card.querySelector('.available-balance').textContent = availableBalance
|
||||
if (lockedBalance) {
|
||||
card.querySelector('.locked-balance').textContent = lockedBalance
|
||||
}
|
||||
getRef(containerId).className = lockedBalance ? 'grid balance-card__amount-wrapper' : ''
|
||||
getRef(containerId).parentNode.className = `balance-card ${lockedBalance ? 'is-locked' : ''}`
|
||||
getRef(containerId).append(card)
|
||||
}
|
||||
|
||||
function account() {
|
||||
getAccount().then(acc => {
|
||||
console.debug(acc);
|
||||
@ -878,13 +975,14 @@
|
||||
let flo_locked = acc.sellOrders.reduce((a, x) => a + x.quantity, 0);
|
||||
let flo_net = flo_total - flo_locked;
|
||||
console.debug("FLO", flo_total, flo_locked, flo_net);
|
||||
document.getElementById("flo_bal").textContent = flo_net + "(+" + flo_locked + ")";
|
||||
|
||||
showBalance("flo_balance", flo_net, flo_locked)
|
||||
//Rupee Balance
|
||||
let rupee_total = acc.rupee_total;
|
||||
let rupee_locked = acc.buyOrders.reduce((a, x) => a + x.quantity * x.maxPrice, 0);
|
||||
let rupee_net = rupee_total - rupee_locked;
|
||||
console.debug("RUPEE", rupee_total, rupee_locked, rupee_net);
|
||||
document.getElementById("rupee_bal").textContent = rupee_net + "(+" + rupee_locked + ")";
|
||||
showBalance("rupee_balance", rupee_net, rupee_locked)
|
||||
//My buy orders
|
||||
let container = document.getElementById("my-buy-orders").getElementsByTagName("tbody")[0];
|
||||
container.innerHTML = '';
|
||||
@ -948,16 +1046,17 @@
|
||||
|
||||
const UI_evt = {};
|
||||
|
||||
UI_evt.signup = function () {
|
||||
UI_evt.signup = async function () {
|
||||
let sid = document.forms['login-form']['sid'].value;
|
||||
let privKey = prompt("Enter Private Key of floID to register: ");
|
||||
signUp(privKey, sid).then(result => {
|
||||
console.info(result);
|
||||
alert("Account registered!")
|
||||
}).catch(error => {
|
||||
console.error(error)
|
||||
alert(error);
|
||||
});
|
||||
let privKey = await getPromptInput("Register private key", "Enter the private key of floID you want to register", { isPassword: true });
|
||||
if (privKey) {
|
||||
signUp(privKey, sid).then(result => {
|
||||
console.info(result);
|
||||
notify("Account registered!", 'success')
|
||||
}).catch(error => {
|
||||
notify(error, 'error');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
UI_evt.logout = function () {
|
||||
@ -981,83 +1080,40 @@
|
||||
}).catch(error => console.error(error));
|
||||
};
|
||||
|
||||
UI_evt.sell = function () {
|
||||
let formInputs = document.forms['sell-form'];
|
||||
sell(parseFloat(formInputs["quantity"].value), parseFloat(formInputs["min-price"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
};
|
||||
|
||||
UI_evt.buy = function () {
|
||||
let formInputs = document.forms['buy-form'];
|
||||
buy(parseFloat(formInputs["quantity"].value), parseFloat(formInputs["max-price"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
};
|
||||
|
||||
UI_evt.cancelOrders = function () {
|
||||
let container = document.getElementById('my-orders');
|
||||
let cancel = [];
|
||||
let inputs = container.getElementsByTagName('input')
|
||||
let inputs = container.querySelectorAll('input[checked]')
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
if (inputs[i].type === "checkbox" && inputs[i].checked) {
|
||||
let row = inputs[i].parentElement.parentElement
|
||||
let id = row.dataset['id'];
|
||||
let type = row.parentElement.dataset['type'];
|
||||
cancel.push([type, id]);
|
||||
}
|
||||
let row = inputs[i].parentElement.parentElement
|
||||
let id = row.dataset['id'];
|
||||
let type = row.parentElement.dataset['type'];
|
||||
cancel.push([type, id]);
|
||||
}
|
||||
cancel.forEach(o => cancelOrder(o[0], o[1], proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(o, error)))
|
||||
};
|
||||
|
||||
UI_evt.depositFLO = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
let privKey = prompt("Enter private key");
|
||||
depositFLO(parseFloat(formInputs["quantity"].value), user_id, privKey, proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
UI_evt.depositRupee = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
let privKey = prompt("Enter private key");
|
||||
depositRupee(parseFloat(formInputs["quantity"].value), user_id, privKey, proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
UI_evt.withdrawFLO = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
withdrawFLO(parseFloat(formInputs["quantity"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
UI_evt.withdrawRupee = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
withdrawRupee(parseFloat(formInputs["quantity"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
refresh(true);
|
||||
</script>
|
||||
<script>
|
||||
function showProcess(id) {
|
||||
getRef(id).children[0].classList.add('clip')
|
||||
getRef(id).append(document.createElement('sm-spinner'))
|
||||
}
|
||||
function hideProcess(id) {
|
||||
getRef(id).children[0].classList.remove('clip')
|
||||
getRef(id).querySelector('sm-spinner')?.remove()
|
||||
}
|
||||
let tradeType = 'buy'
|
||||
getRef('trade_type_selector').addEventListener('change', e => {
|
||||
getRef('get_price').setAttribute('placeholder', e.detail.value === 'buy' ? 'Max price' : 'Min price')
|
||||
getRef('trade_button').textContent = e.detail.value
|
||||
getRef('quantity_type').textContent = e.detail.value === 'buy' ? `Rupee` : `FLO`
|
||||
tradeType = e.detail.value
|
||||
getRef('get_price').setAttribute('placeholder', tradeType === 'buy' ? 'Max price' : 'Min price')
|
||||
getRef('trade_button').textContent = tradeType
|
||||
getRef('quantity_type').textContent = tradeType === 'buy' ? `Rupee` : `FLO`
|
||||
})
|
||||
async function tradeFlo() {
|
||||
const tradeType = getRef('trade_type_selector').value
|
||||
const quantity = parseFloat(getRef('get_quantity').value)
|
||||
const price = parseFloat(getRef('get_price').value)
|
||||
try {
|
||||
@ -1075,6 +1131,77 @@
|
||||
getRef('trade_form').reset()
|
||||
}
|
||||
}
|
||||
const balance = {
|
||||
flo: 5.1245,
|
||||
rupee: 457.2
|
||||
}
|
||||
const rate = {
|
||||
flo: 1.487
|
||||
}
|
||||
getRef('quantity_selector').addEventListener('click', e => {
|
||||
// Get latest balance and exchange rate
|
||||
if (e.target.closest('button')) {
|
||||
const target = e.target.closest('button')
|
||||
const fraction = parseInt(target.value) / 100
|
||||
if (tradeType === 'buy') {
|
||||
getRef('get_quantity').value = parseFloat(((balance.rupee * fraction) / rate.flo).toFixed(8))
|
||||
} else {
|
||||
getRef('get_quantity').value = parseFloat((balance.flo * fraction).toFixed(8))
|
||||
}
|
||||
}
|
||||
})
|
||||
getRef('wallet_actions').addEventListener('click', e => {
|
||||
if (e.target.closest('.button')) {
|
||||
const target = e.target.closest('.button')
|
||||
showPopup('wallet_popup')
|
||||
const type = target.value
|
||||
const asset = getRef('wallet_asset_selector').value
|
||||
getRef('wallet_popup__cta').textContent = `${type}`
|
||||
getRef('wallet_popup__cta').setAttribute('value', type)
|
||||
getRef('wallet_popup__title').textContent = `${type} ${asset}`
|
||||
if (type === 'withdraw') {
|
||||
getRef('get_private_key').classList.add('hide-completely')
|
||||
getRef('get_private_key').removeAttribute('required')
|
||||
getRef('get_private_key').removeAttribute('hiderequired')
|
||||
} else {
|
||||
getRef('get_private_key').setAttribute('required', '')
|
||||
getRef('get_private_key').setAttribute('hiderequired', '')
|
||||
getRef('get_private_key').classList.remove('hide-completely')
|
||||
}
|
||||
getRef('wallet_form').elementsChanged()
|
||||
}
|
||||
})
|
||||
getRef('wallet_popup__cta').addEventListener('click', async e => {
|
||||
const asset = getRef('wallet_asset_selector').value
|
||||
const type = e.target.getAttribute('value')
|
||||
const quantity = parseFloat(getRef('get_quantity').value)
|
||||
console.log(type, asset)
|
||||
try {
|
||||
showProcess('wallet_popup__cta_wrapper')
|
||||
if (type === 'deposit') {
|
||||
const privKey = getRef('get_private_key').value;
|
||||
if (asset === 'FLO') {
|
||||
await depositFLO(quantity, user_id, privKey, proxy.secret)
|
||||
} else {
|
||||
await depositRupee(quantity, user_id, privKey, proxy.secret)
|
||||
}
|
||||
notify(`Deposited ${asset} successfully`)
|
||||
} else {
|
||||
if (asset === 'FLO') {
|
||||
await withdrawFLO(quantity, proxy.secret)
|
||||
} else {
|
||||
await withdrawRupee(quantity, proxy.secret)
|
||||
}
|
||||
notify(`Withdrawn ${asset} successfully`)
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
notify(err, 'error')
|
||||
}
|
||||
finally {
|
||||
hideProcess('wallet_popup__cta_wrapper')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user