Upload the base files
This commit is contained in:
parent
47514bf3fd
commit
dabcb10d71
548
css/main.css
Normal file
548
css/main.css
Normal file
@ -0,0 +1,548 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: "Roboto", sans-serif;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
:root {
|
||||
font-size: clamp(1rem, 1.2vmax, 3rem);
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgba(var(--text-color), 1);
|
||||
background: rgba(var(--background-color), 1);
|
||||
}
|
||||
body,
|
||||
body * {
|
||||
--accent-color: #0D7377;
|
||||
--text-color: 17, 17, 17;
|
||||
--background-color: 255, 255, 255;
|
||||
--danger-color: red;
|
||||
}
|
||||
|
||||
body[data-theme=dark],
|
||||
body[data-theme=dark] * {
|
||||
--accent-color: #32E0C4;
|
||||
--text-color: 240, 240, 240;
|
||||
--text-color-light: 170, 170, 170;
|
||||
--background-color: 10, 10, 10;
|
||||
--danger-color: rgb(255, 106, 106);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 5em;
|
||||
height: 0em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
li > div > div:nth-of-type(1) {
|
||||
text-align: right;
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 0.8;
|
||||
max-width: 65ch;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 1.5rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
p:not(:last-of-type) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:focus-visible {
|
||||
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-flex;
|
||||
border: none;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
a:any-link:focus-visible {
|
||||
outline: rgba(var(--text-color), 1) 0.1rem solid;
|
||||
}
|
||||
|
||||
sm-button {
|
||||
--border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 5px;
|
||||
border: 1px solid rgba(var(--text-color), 1);
|
||||
}
|
||||
|
||||
.profile {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: #64b5f6;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.last-tx {
|
||||
padding: 1em 0em;
|
||||
}
|
||||
|
||||
.last-tx > div:nth-of-type(1) {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.last-tx-content {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
flex-flow: column nowrap;
|
||||
}
|
||||
|
||||
|
||||
.last-tx-content > div:nth-of-type(1) {
|
||||
padding: 0.5em;
|
||||
margin: 0.5em 0em;
|
||||
border-radius: 1rem;
|
||||
background: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.last-tx-content > div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.app {
|
||||
padding: 0.5em;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
.search-wrapper {
|
||||
opacity: 0;
|
||||
transition: visiblity 0s, opacity 0.1s ease-in;
|
||||
}
|
||||
|
||||
.search-wrapper:not(.open) {
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.search-wrapper.open {
|
||||
visibility: visible;
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 1;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.search-overlay {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin: 0em auto;
|
||||
width: 50%;
|
||||
margin-top: 4rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 4px 7px 3px rgb(0 0 0 / 20%);
|
||||
background: rgba(var(--background-color), 1);
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hide-completely {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.no-transformations {
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.overflow-ellipsis {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.breakable {
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
-ms-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
.full-bleed {
|
||||
grid-column: 1/4;
|
||||
}
|
||||
|
||||
.h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.h3 {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.h4 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.h5 {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.capitalize {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.grid-3 {
|
||||
grid-template-columns: 1fr auto auto;
|
||||
}
|
||||
|
||||
.flow-column {
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
.gap-0-5 {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.gap-1 {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.gap-1-5 {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.gap-3 {
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.text-align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.justify-start {
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.justify-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.align-self-center {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.justify-self-center {
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.justify-self-start {
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.justify-self-end {
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.direction-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.space-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.color-0-8 {
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
|
||||
.weight-400 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.weight-500 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ripple {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
transform: scale(0);
|
||||
background: rgba(var(--text-color), 0.16);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.interact {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.observe-empty-state:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.observe-empty-state:not(:empty) ~ .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
fill: rgba(var(--text-color), 0.9);
|
||||
}
|
||||
|
||||
.button__icon {
|
||||
height: 1.2rem;
|
||||
width: 1.2rem;
|
||||
}
|
||||
.button__icon--left {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.button__icon--right {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
#loading {
|
||||
text-align: center;
|
||||
amimation: load 1s infinite;
|
||||
}
|
||||
|
||||
#searchToggle {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@keyframes load {
|
||||
0% {
|
||||
color: red;
|
||||
}
|
||||
50% {
|
||||
color: white;
|
||||
}
|
||||
100% {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
#confirmation_popup,
|
||||
#prompt_popup {
|
||||
flex-direction: column;
|
||||
}
|
||||
#confirmation_popup h4,
|
||||
#prompt_popup h4 {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#confirmation_popup sm-button,
|
||||
#prompt_popup sm-button {
|
||||
margin: 0;
|
||||
}
|
||||
#confirmation_popup .flex,
|
||||
#prompt_popup .flex {
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#confirmation_popup .flex sm-button:first-of-type,
|
||||
#prompt_popup .flex sm-button:first-of-type {
|
||||
margin-right: 0.6rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#main_header {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
position: sticky;
|
||||
padding: 0.5rem 1.5rem;
|
||||
background: rgba(var(--background-color), 1);
|
||||
border-bottom: solid 1px rgba(var(--text-color), 0.16);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#logo {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 0 0.5rem;
|
||||
margin-right: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
#logo h4 {
|
||||
text-transform: capitalize;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
#logo h5 {
|
||||
font-size: 0.8rem;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-weight: 400;
|
||||
}
|
||||
#logo #main_logo {
|
||||
height: 1.4rem;
|
||||
width: 1.4rem;
|
||||
fill: rgba(var(--text-color), 1);
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
sm-tab-header {
|
||||
padding: 0 1.5rem;
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
}
|
||||
|
||||
sm-tab {
|
||||
padding: 0.5rem 0.8rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 3rem;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
.section:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.section__header {
|
||||
display: flex;
|
||||
padding: 1rem 0;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/*width: 100%;*/
|
||||
/*min-width: 20rem;*/
|
||||
border-radius: 0.5rem;
|
||||
margin: 1rem 0.5em;
|
||||
margin-bottom: 0.4em;
|
||||
flex: 1 0;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
}
|
||||
|
||||
.card > a > div:nth-of-type(3) {
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
padding: 0.5em;
|
||||
border-radius: 1rem;
|
||||
background-color: rgba(var(--background-color));
|
||||
}
|
||||
|
||||
.card > a > h3 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
sm-popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.search {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12066
index.html
Normal file
12066
index.html
Normal file
File diff suppressed because it is too large
Load Diff
9
js/components.min.js
vendored
Normal file
9
js/components.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
618
js/main.js
Normal file
618
js/main.js
Normal file
@ -0,0 +1,618 @@
|
||||
const main = (ready) => {
|
||||
if (ready) {
|
||||
document.body.addEventListener("keydown", (e) => {
|
||||
if (e.key === "/") {
|
||||
e.preventDefault();
|
||||
searchWrapper.classList.add("open");
|
||||
let el = document.getElementById("input");
|
||||
el.focusIn();
|
||||
}
|
||||
});
|
||||
let _input = document.querySelector("#input");
|
||||
let _backBtn = document.querySelector("#logo");
|
||||
let home = document.getElementById("home");
|
||||
let searchToggle = document.getElementById("searchToggle");
|
||||
let searchOverlay = document.querySelector(".search-overlay");
|
||||
let searchWrapper = document.querySelector(".search-wrapper");
|
||||
let _getTemplate = document.getElementById("myTemplate");
|
||||
let _cardTemplate = document.getElementById("cardTemplate");
|
||||
let internRating = {};
|
||||
function getDate(time) {
|
||||
let stringTime = time + "000";
|
||||
let newTime = new Date(+stringTime).toDateString();
|
||||
return newTime;
|
||||
}
|
||||
searchToggle.addEventListener("click", () => {
|
||||
searchWrapper.classList.add("open");
|
||||
_input.focus();
|
||||
});
|
||||
searchOverlay.addEventListener("click", () => {
|
||||
searchWrapper.classList.remove("open");
|
||||
});
|
||||
/**
|
||||
* On changing the search input
|
||||
* - Update the DOM and fill the result
|
||||
* - if there is nothing set all the element to the DOM
|
||||
*/
|
||||
_input.addEventListener("input", (e) => {
|
||||
// @ts-ignore
|
||||
let val = e.target.value;
|
||||
window.location.hash = "";
|
||||
if (finalList.length !== 0) {
|
||||
const list = finalList.filter((element) => {
|
||||
let newUserName = element.name.slice(0, val.length);
|
||||
return newUserName.toLowerCase() === val.toLowerCase();
|
||||
});
|
||||
if (list.length) {
|
||||
_rootDiv.innerHTML = renderList(list);
|
||||
}
|
||||
else {
|
||||
_rootDiv.innerHTML = renderList(finalList);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return `
|
||||
<h1 style="
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 50vh;
|
||||
">Loading...</h1>
|
||||
`;
|
||||
}
|
||||
});
|
||||
// intern Data "const internList = []"
|
||||
//
|
||||
// Data from distributer "const distributerData = []"
|
||||
//
|
||||
// filter the transaction of interns from the distributer
|
||||
const receiverList = [];
|
||||
const internList = [];
|
||||
let finalList = [];
|
||||
customElements.define("my-card", class MyCard extends HTMLElement {
|
||||
displayUsername;
|
||||
displayUserId;
|
||||
// look all the value we have to look on change
|
||||
static get observedAttributes() {
|
||||
return ["username", "userid"];
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
// attach the shadow DOM
|
||||
this.attachShadow({ mode: "open" });
|
||||
}
|
||||
get username() {
|
||||
return this.getAttribute("username");
|
||||
}
|
||||
get userid() {
|
||||
return this.getAttribute("userid");
|
||||
}
|
||||
set username(val) {
|
||||
this.setAttribute("username", val);
|
||||
}
|
||||
set userid(val) {
|
||||
this.setAttribute("userid", val);
|
||||
}
|
||||
// @ts-ignore
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (oldValue !== newValue && this.displayUsername) {
|
||||
this.displayUsername.innerText = this.username;
|
||||
this.displayUserId.innerText = this.userid;
|
||||
}
|
||||
}
|
||||
// run when the element attached to the DOM
|
||||
connectedCallback() {
|
||||
const template = document.createElement("template");
|
||||
template.innerHTML = this.render();
|
||||
const node = document.importNode(template.content, true);
|
||||
this.shadowRoot.append(node);
|
||||
// select the element from the shadow DOM and set the value
|
||||
this.displayUsername = this.shadowRoot.querySelector(".username");
|
||||
this.displayUserId = this.shadowRoot.querySelector(".userid");
|
||||
this.shadowRoot
|
||||
.querySelector("span")
|
||||
.addEventListener("click", (e) => {
|
||||
// back to the home page
|
||||
window.location.hash = "";
|
||||
_rootDiv.innerHTML = renderList();
|
||||
});
|
||||
}
|
||||
// render the element to the DOM
|
||||
render() {
|
||||
if (finalList.length) {
|
||||
let el = document.createElement("div");
|
||||
let backBtn = document.createElement("div");
|
||||
let username = document.createElement("h2");
|
||||
let floId = document.createElement("h3");
|
||||
let projectName = document.createElement("h4");
|
||||
let profile = document.createElement("div");
|
||||
let totalMoneyEarned = document.createElement("div");
|
||||
let totalNumberOfTransaction = document.createElement("div");
|
||||
const myResult = finalList.filter((l) => {
|
||||
return this.userid.slice(1) === l.floId;
|
||||
});
|
||||
myResult.forEach((r) => {
|
||||
let txData = document.createElement("ul");
|
||||
let red = document.createElement("span");
|
||||
let totalAmount = 0;
|
||||
profile.classList.add("profile");
|
||||
username.innerText = r.name;
|
||||
floId.innerText = this.userid.slice(1);
|
||||
projectName.innerText = `Project - ${r.projectName || "Intern Inactive"}`;
|
||||
totalNumberOfTransaction.innerText = `Total Number of transactions - ${r.transactions.length}`;
|
||||
username.style.textAlign = "left";
|
||||
red.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M9.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L7.414 9H15a1 1 0 110 2H7.414l2.293 2.293a1 1 0 010 1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
`;
|
||||
backBtn.classList.add("back-btn");
|
||||
backBtn.append(red);
|
||||
if (r.transactions.length) {
|
||||
r.transactions.forEach((t) => {
|
||||
let amount = t.transaction.floData.match(/([0-9]+)/);
|
||||
let num = Number(amount[0]);
|
||||
let senderAddress = t.transaction.vin[0].addr;
|
||||
let time = getDate(t.transaction.time);
|
||||
let li = document.createElement("li");
|
||||
li.style.margin = "1em 0em";
|
||||
totalAmount += num;
|
||||
li.innerHTML = `
|
||||
<div class="card">
|
||||
<div>₹${amount[0]}/-</div>
|
||||
<div>${time}</div>
|
||||
<h3>Transaction Detail</h3>
|
||||
<div>Message - ${t.transaction.floData}</div>
|
||||
<div>Sent from - RanchiMall Distribution Address "${senderAddress}"</div>
|
||||
<a target="_blank" href="${t.transaction.blockChainLink}">${t.transaction.blockChainLink}</a>
|
||||
</div>
|
||||
`;
|
||||
txData.appendChild(li);
|
||||
});
|
||||
}
|
||||
else {
|
||||
let li = document.createElement("div");
|
||||
li.innerText = "No Transaction Found";
|
||||
txData.appendChild(li);
|
||||
}
|
||||
totalMoneyEarned.classList.add("totalAmount");
|
||||
totalMoneyEarned.innerHTML = `
|
||||
<div>₹${totalAmount}</div>
|
||||
<div style="font-size: xx-small; text-align: right;">Total Amount Paid</div>
|
||||
`;
|
||||
let styling = document.createElement("style");
|
||||
styling.innerHTML = `
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
ul {
|
||||
padding: 0em;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-bottom: 2.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 1em 0em;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 1em 0em;
|
||||
color: #64b5f6;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.profile {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: #64b5f6;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
background: rgba(var(--background-color), 1);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 4em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.totalAmount {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-width: 20rem;
|
||||
border-radius: 0.5rem;
|
||||
flex: 1 0;
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
}
|
||||
|
||||
.card > div:nth-of-type(1) {
|
||||
margin: 0.5em 0em;
|
||||
font-size: 3.5em;
|
||||
}
|
||||
|
||||
.card > div:nth-of-type(2) {
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
width: max-content;
|
||||
background: rgba(var(--background-color), 1);
|
||||
padding: 0.4em;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
`;
|
||||
el.appendChild(backBtn);
|
||||
el.appendChild(styling);
|
||||
//el.appendChild(profile);
|
||||
el.appendChild(username);
|
||||
el.appendChild(floId);
|
||||
el.appendChild(projectName);
|
||||
el.appendChild(totalMoneyEarned);
|
||||
el.appendChild(totalNumberOfTransaction);
|
||||
el.appendChild(txData);
|
||||
});
|
||||
return el.innerHTML;
|
||||
}
|
||||
}
|
||||
});
|
||||
let path = {
|
||||
current: window.location.hash || "#",
|
||||
printPath: () => { },
|
||||
};
|
||||
const _rootDiv = document.getElementById("uInfo");
|
||||
// render all the list of the use on to the DOM
|
||||
/*function renderList() {
|
||||
|
||||
if (finalList.length !== 0) {
|
||||
let el: HTMLDivElement = document.createElement("div");
|
||||
let heading: HTMLHeadElement = document.createElement("h2");
|
||||
heading.innerText = "RanchiMall Internship Blockchain Contract";
|
||||
heading.style.textAlign = "center";
|
||||
heading.style.width = "100%";
|
||||
heading.style.padding = "2em 0.5em";
|
||||
|
||||
el.appendChild(heading);
|
||||
|
||||
for (let i of finalList) {
|
||||
let card: HTMLAnchorElement = document.createElement("div");
|
||||
let link = document.createElement("a");
|
||||
|
||||
link.innerText =
|
||||
i.transactions[0].transaction.blockChainLink;
|
||||
link.href = i.transactions[0].transaction.blockChainLink;
|
||||
link.target = "_blank";
|
||||
link.style.marginTop = "0em";
|
||||
|
||||
card.classList.add("card");
|
||||
card.href = `#${i.floId}`;
|
||||
let amount = i.transactions[0].transaction.floData.match(
|
||||
/([0-9]+)/
|
||||
);
|
||||
card.innerHTML = `
|
||||
<a href="#${i.floId}" style="position: relative;">
|
||||
<div class="profile"></div>
|
||||
<h3>${i.name}</h3>
|
||||
<h5>${i.floId}</h5>
|
||||
<h5>Total amount paid: ₹${i.totalMoneyEarned}</h5>
|
||||
<h5>Total no. of transaction: ${i.transactions.length
|
||||
}</h5>
|
||||
<div class="last-tx">
|
||||
<div>Last transaction </div>
|
||||
<div class="last-tx-content">
|
||||
<div>${getDate(
|
||||
i.transactions[0].transaction.time
|
||||
)}</div>
|
||||
<div style="font-size: 2em; padding: 0.5em 0em;">₹${amount[0]
|
||||
}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>${internRating[i.floId]}</div>
|
||||
</a>
|
||||
<div style="margin: 0.5em 0em;">View last payment blockchain</div>
|
||||
<a target="_blank" href="${i.transactions[0].transaction.blockChainLink
|
||||
}">${i.transactions[0].transaction.blockChainLink}</a>
|
||||
`;
|
||||
el.appendChild(card);
|
||||
}
|
||||
return el.innerHTML;
|
||||
} else {
|
||||
return `
|
||||
<h1 style="
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 50vh;
|
||||
">Loading...</h1>
|
||||
`;
|
||||
}
|
||||
}*/
|
||||
function renderList(data) {
|
||||
// check if the finallist have any length
|
||||
if (data.length !== 0) {
|
||||
// get the template from the DOM
|
||||
// get the deep copy the template
|
||||
let node = _getTemplate.content.cloneNode(true);
|
||||
for (let i of data) {
|
||||
let amount = i.transactions[0].transaction.floData.match(/([0-9]+)/);
|
||||
//
|
||||
let cardNode = _cardTemplate.content.cloneNode(true);
|
||||
cardNode.querySelector(".link").href = `#${i.floId}`;
|
||||
cardNode.querySelector(".heading-name").textContent =
|
||||
i.name;
|
||||
cardNode.querySelector(".heading-floId").textContent =
|
||||
i.floId;
|
||||
cardNode.querySelector(".total-money-earned").textContent = `Total amount paid: ₹${i.totalMoneyEarned}`;
|
||||
cardNode.querySelector(".number-of-transaction").textContent = `Total number of transactions: ${i.transactions.length}`;
|
||||
cardNode.querySelector(".last-tx-content").textContent = getDate(i.transactions[0].transaction.time);
|
||||
cardNode.querySelector(".last-tx-amount").textContent = `₹${amount[0]}/-`;
|
||||
cardNode.querySelector(".intern-rating").textContent =
|
||||
internRating[i.floId];
|
||||
cardNode.querySelector(".blockchain-link").href =
|
||||
i.transactions[0].transaction.blockChainLink;
|
||||
node.querySelector(".card-wrapper").appendChild(cardNode);
|
||||
}
|
||||
let el = document.createElement("div");
|
||||
el.appendChild(node);
|
||||
return el.innerHTML;
|
||||
}
|
||||
else {
|
||||
return `
|
||||
<h1 style="
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 50vh;
|
||||
">Loading...</h1>
|
||||
`;
|
||||
}
|
||||
}
|
||||
// render the details page
|
||||
function renderDetail() {
|
||||
return `
|
||||
<my-card username="red" style="
|
||||
flex: 1;
|
||||
padding: 1em;
|
||||
position: relative;
|
||||
" userid="${window.location.hash}"></my-card>
|
||||
`;
|
||||
}
|
||||
let routes = {
|
||||
"#": renderList(finalList),
|
||||
"#detail": renderDetail(),
|
||||
};
|
||||
/**
|
||||
* Run when there is change of hash on the window
|
||||
* - get the first value from the routes object
|
||||
* - check the value is matching to the comming route value
|
||||
* - if so, render the home page otherwise detail page
|
||||
*/
|
||||
const handleRender = (route) => {
|
||||
// ...
|
||||
let val = Object.keys(routes)[0];
|
||||
if (val === route) {
|
||||
_rootDiv.innerHTML = renderList(finalList);
|
||||
}
|
||||
else {
|
||||
_rootDiv.innerHTML = renderDetail();
|
||||
}
|
||||
};
|
||||
// check the change in hash
|
||||
window.addEventListener("hashchange", (e) => {
|
||||
// get the current path
|
||||
path.current = window.location.hash || "#";
|
||||
/**
|
||||
* @param always be the path of the window
|
||||
*/
|
||||
handleRender(path.current);
|
||||
});
|
||||
// render the home page default
|
||||
_rootDiv.innerHTML = renderList(finalList);
|
||||
// Go the home page
|
||||
_backBtn.addEventListener("click", () => {
|
||||
window.location.hash = "";
|
||||
_rootDiv.innerHTML = renderList();
|
||||
});
|
||||
/**
|
||||
* Creating a list in which store all the
|
||||
* flo addresses of the receiver
|
||||
*/
|
||||
/**
|
||||
* get the intern data from the RanchiMall
|
||||
* - request the server for data
|
||||
* - loop over the response
|
||||
* - push the each data to the "finalList arrary"
|
||||
* - call the fetchInternData()
|
||||
*/
|
||||
async function getInternData() {
|
||||
try {
|
||||
let r = await floCloudAPI.requestObjectData("RIBC", {
|
||||
application: "RIBC",
|
||||
receiverID: "FMeiptdJNtYQEtzyYAVNP8fjsDJ1i4EPfE",
|
||||
senderIDs: [
|
||||
"F7TxecSPV8oFZE6Y2giVuP8hfsqfAD6erj",
|
||||
"FCja6sLv58e3RMy41T5AmWyvXEWesqBCkX",
|
||||
"FPFeL5PXzW9bGosUjQYCxTHSMHidnygvvd",
|
||||
"FS4jMAcSimRMrhoRhk5cjuJERS2otiwq4A",
|
||||
"FU2fkubqGD5ynbr7qhvaPe9DPqrNdGB6mw",
|
||||
"FUkY9k9mVVxPzYA8uUGxUuLVH6CB83Nb9r",
|
||||
],
|
||||
});
|
||||
if (r) {
|
||||
let i = floGlobals.appObjects.RIBC.internList;
|
||||
for (let key in i) {
|
||||
internList.push({
|
||||
floId: key,
|
||||
floUserName: i[key],
|
||||
});
|
||||
}
|
||||
// fetch all the data and pack together
|
||||
fetchInternData();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// ERROR HANDLING
|
||||
console.log("Error Occur while fetching the Intern Data", e);
|
||||
_rootDiv.innerHTML = `
|
||||
<div style="flex: 1; padding: 1em;">
|
||||
<h1>Something Went Wrong [keep Refreshing the page ...]</h1>
|
||||
<p style="color: red;">${e}</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
function bundleAllData() {
|
||||
// get the internList from the server
|
||||
let internList = floGlobals.appObjects.RIBC.internList;
|
||||
internRating = floGlobals.appObjects.RIBC.internRating;
|
||||
// get the intern Assigned project from the server
|
||||
// get the value of internAssigned project
|
||||
let internsAssigned = floGlobals.appObjects.RIBC.internsAssigned;
|
||||
const internsAssignedArr = Object.entries(internsAssigned);
|
||||
// get the project details from the server
|
||||
let projectDetails = floGlobals.appObjects.RIBC.projectDetails;
|
||||
// set the tragetList
|
||||
let tragetList = [];
|
||||
// loop over the intern data
|
||||
for (let internId in internList) {
|
||||
// loop over the intern assigned project so we get the
|
||||
// associated projects
|
||||
for (let [k, v] of internsAssignedArr) {
|
||||
// find the value have correct key
|
||||
let value = v.find((el) => {
|
||||
return el === internId;
|
||||
});
|
||||
// if we find a value find its project Details also
|
||||
if (value) {
|
||||
// loop over the project details
|
||||
for (let i in projectDetails) {
|
||||
// find out the key by the slicing it
|
||||
let key = k.slice(0, 14);
|
||||
// get the value
|
||||
let newVal = projectDetails[key];
|
||||
// send it ot targetList
|
||||
tragetList.push({
|
||||
internId: internId,
|
||||
project: k,
|
||||
projectName: newVal.projectName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// loop over to the finalList to attach the projectName
|
||||
for (let key in tragetList) {
|
||||
// get the internId from the tragetList
|
||||
let val = tragetList[key].internId;
|
||||
// get the index out of that
|
||||
let index = finalList.findIndex((el) => el.floId === val);
|
||||
// if it exists
|
||||
if (index > -1) {
|
||||
finalList[index].projectName = tragetList[key].projectName;
|
||||
}
|
||||
}
|
||||
for (let index of finalList) {
|
||||
let totalAmount = 0;
|
||||
/*finalList[index].transactions.forEach((intern) => {
|
||||
let amount = intern.transaction.floData.match(/([0-9]+)/);
|
||||
let num = Number(amount[0]);
|
||||
totalAmount += num;
|
||||
});
|
||||
finalList[index].totalMoneyEarned = totalAmount;*/
|
||||
}
|
||||
/**
|
||||
* Loop over the final List to get the totalAmount
|
||||
*/
|
||||
finalList.forEach((list) => {
|
||||
let totalAmount = 0;
|
||||
list.transactions.forEach((intern) => {
|
||||
let amount = intern.transaction.floData.match(/([0-9]+)/);
|
||||
let num = Number(amount[0]);
|
||||
totalAmount += num;
|
||||
// add the blockChainLink key
|
||||
//intern.transaction.blockChainLink = `https://livenet.flocha.in/block/${intern.transaction.blockhash}`;
|
||||
intern.transaction.blockChainLink = `https://livenet.flocha.in/tx/${intern.transaction.txid}`;
|
||||
});
|
||||
const transactionsDetails = list.transactions.sort((first, second) => {
|
||||
return second.transaction.time - first.transaction.time;
|
||||
});
|
||||
list.totalMoneyEarned = totalAmount;
|
||||
list.transactions = transactionsDetails;
|
||||
});
|
||||
const myArr = finalList.sort((first, second) => {
|
||||
return (second.transactions[0].transaction.time -
|
||||
first.transactions[0].transaction.time);
|
||||
});
|
||||
finalList = myArr;
|
||||
}
|
||||
// get the internData after the 3sec I don't know why
|
||||
setTimeout(() => {
|
||||
getInternData();
|
||||
}, 1000);
|
||||
/**
|
||||
* Fetch initial transactions
|
||||
* - request the distributer transactions from the server
|
||||
* - push all these transactions to the "receiverList array"
|
||||
* - then loop over to the interList array in which we collect interns data
|
||||
* - filter out the transactions of the intern from the distributer transactions
|
||||
* - push all the data to the new called finalList array
|
||||
* - render the home page to the DOM
|
||||
*/
|
||||
function fetchInternData() {
|
||||
floBlockchainAPI
|
||||
.readAllTxs("FThgnJLcuStugLc24FJQggmp2WgaZjrBSn", "", "")
|
||||
.then((r) => {
|
||||
// loop over the response transactions
|
||||
r.forEach((user) => {
|
||||
// sending all the transaction to the new array
|
||||
receiverList.push({
|
||||
floId: user.vout[0].scriptPubKey.addresses[0],
|
||||
transaction: user,
|
||||
});
|
||||
});
|
||||
// loop over the intern data
|
||||
for (let d of internList) {
|
||||
// filter the intern transactions
|
||||
const result = receiverList.filter((i) => {
|
||||
return i.floId === d.floId;
|
||||
});
|
||||
// check if the transaction are available
|
||||
if (result.length) {
|
||||
// add all the transaction to the new Array
|
||||
finalList.push({
|
||||
name: d.floUserName,
|
||||
floId: d.floId,
|
||||
transactions: [...result],
|
||||
});
|
||||
}
|
||||
}
|
||||
bundleAllData();
|
||||
// re-render the DOM
|
||||
_rootDiv.innerHTML = renderList(finalList);
|
||||
}, console.error);
|
||||
}
|
||||
}
|
||||
};
|
||||
305
js/main_UI.js
Normal file
305
js/main_UI.js
Normal file
@ -0,0 +1,305 @@
|
||||
// Global variables
|
||||
const appPages = ['dashboard', 'settings'];
|
||||
const domRefs = {};
|
||||
let timerId;
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
//Checks for internet connection status
|
||||
if (!navigator.onLine)
|
||||
notify(
|
||||
"There seems to be a problem connecting to the internet, Please check you internet connection.",
|
||||
"error",
|
||||
{ sound: true }
|
||||
);
|
||||
window.addEventListener("offline", () => {
|
||||
notify(
|
||||
"There seems to be a problem connecting to the internet, Please check you internet connection.",
|
||||
"error",
|
||||
{ pinned: true, sound: true }
|
||||
);
|
||||
});
|
||||
window.addEventListener("online", () => {
|
||||
getRef("notification_drawer").clearAll();
|
||||
notify("We are back online.", "success");
|
||||
});
|
||||
|
||||
// Use instead of document.getElementById
|
||||
function getRef(elementId) {
|
||||
if (!domRefs.hasOwnProperty(elementId)) {
|
||||
domRefs[elementId] = {
|
||||
count: 1,
|
||||
ref: null,
|
||||
};
|
||||
return document.getElementById(elementId);
|
||||
} else {
|
||||
if (domRefs[elementId].count < 3) {
|
||||
domRefs[elementId].count = domRefs[elementId].count + 1;
|
||||
return document.getElementById(elementId);
|
||||
} else {
|
||||
if (!domRefs[elementId].ref)
|
||||
domRefs[elementId].ref = document.getElementById(elementId);
|
||||
return domRefs[elementId].ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns dom with specified element
|
||||
function createElement(tagName, options) {
|
||||
const { className, textContent, innerHTML, attributes = {} } = options
|
||||
const elem = document.createElement(tagName)
|
||||
for (let attribute in attributes) {
|
||||
elem.setAttribute(attribute, attributes[attribute])
|
||||
}
|
||||
if (className)
|
||||
elem.className = className
|
||||
if (textContent)
|
||||
elem.textContent = textContent
|
||||
if (innerHTML)
|
||||
elem.innerHTML = innerHTML
|
||||
return elem
|
||||
}
|
||||
|
||||
// Use when a function needs to be executed after user finishes changes
|
||||
const debounce = (callback, wait) => {
|
||||
let timeoutId = null;
|
||||
return (...args) => {
|
||||
window.clearTimeout(timeoutId);
|
||||
timeoutId = window.setTimeout(() => {
|
||||
callback.apply(null, args);
|
||||
}, wait);
|
||||
};
|
||||
}
|
||||
|
||||
// Limits the rate of function execution
|
||||
function throttle(func, delay) {
|
||||
// If setTimeout is already scheduled, no need to do anything
|
||||
if (timerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule a setTimeout after delay seconds
|
||||
timerId = setTimeout(function () {
|
||||
func();
|
||||
|
||||
// Once setTimeout function execution is finished, timerId = undefined so that in
|
||||
// the next scroll event function execution can be scheduled by the setTimeout
|
||||
timerId = undefined;
|
||||
}, delay);
|
||||
}
|
||||
|
||||
class Stack {
|
||||
constructor() {
|
||||
this.items = [];
|
||||
}
|
||||
push(element) {
|
||||
this.items.push(element);
|
||||
}
|
||||
pop() {
|
||||
if (this.items.length == 0)
|
||||
return "Underflow";
|
||||
return this.items.pop();
|
||||
}
|
||||
peek() {
|
||||
return this.items[this.items.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// function required for popups or modals to appear
|
||||
function showPopup(popupId, pinned) {
|
||||
zIndex++
|
||||
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
|
||||
popupStack = getRef(popupId).show({ pinned, popupStack })
|
||||
return getRef(popupId);
|
||||
}
|
||||
|
||||
// hides the popup or modal
|
||||
function hidePopup() {
|
||||
if (popupStack.peek() === undefined)
|
||||
return;
|
||||
popupStack.peek().popup.hide()
|
||||
}
|
||||
|
||||
// displays a popup for asking permission. Use this instead of JS confirm
|
||||
const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
|
||||
return new Promise(resolve => {
|
||||
showPopup('confirmation_popup', true)
|
||||
getRef('confirm_title').textContent = title;
|
||||
getRef('confirm_message').textContent = message;
|
||||
let cancelButton = getRef('confirmation_popup').children[2].children[0],
|
||||
submitButton = getRef('confirmation_popup').children[2].children[1]
|
||||
submitButton.textContent = confirmText
|
||||
cancelButton.textContent = cancelText
|
||||
submitButton.onclick = () => {
|
||||
hidePopup()
|
||||
resolve(true);
|
||||
}
|
||||
cancelButton.onclick = () => {
|
||||
hidePopup()
|
||||
resolve(false);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// displays a popup for asking user input. Use this instead of JS prompt
|
||||
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
|
||||
showPopup('prompt_popup', true)
|
||||
getRef('prompt_title').textContent = title;
|
||||
let input = getRef('prompt_input');
|
||||
input.setAttribute("placeholder", message)
|
||||
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
|
||||
if (isPassword)
|
||||
input.setAttribute("type", "text")
|
||||
else
|
||||
input.setAttribute("type", "password")
|
||||
input.focusIn()
|
||||
buttons[0].textContent = cancelText;
|
||||
buttons[1].textContent = confirmText;
|
||||
return new Promise((resolve, reject) => {
|
||||
buttons[0].onclick = () => {
|
||||
hidePopup()
|
||||
return;
|
||||
}
|
||||
buttons[1].onclick = () => {
|
||||
let value = input.value;
|
||||
hidePopup()
|
||||
resolve(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
|
||||
function notify(message, mode, options = {}) {
|
||||
const { pinned = false, sound = false } = options
|
||||
let icon
|
||||
switch (mode) {
|
||||
case 'success':
|
||||
icon = `<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>`
|
||||
break;
|
||||
case 'error':
|
||||
icon = `<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 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm0-8v6h2V7h-2z"/></svg>`
|
||||
break;
|
||||
}
|
||||
getRef("notification_drawer").push(message, { pinned, icon });
|
||||
if (navigator.onLine && sound) {
|
||||
getRef("notification_sound").currentTime = 0;
|
||||
getRef("notification_sound").play();
|
||||
}
|
||||
}
|
||||
|
||||
function getFormatedTime(time, relative) {
|
||||
try {
|
||||
if (String(time).indexOf("_")) time = String(time).split("_")[0];
|
||||
const intTime = parseInt(time);
|
||||
if (String(intTime).length < 13) time *= 1000;
|
||||
let timeFrag = new Date(intTime).toString().split(" "),
|
||||
day = timeFrag[0],
|
||||
month = timeFrag[1],
|
||||
date = timeFrag[2],
|
||||
year = timeFrag[3],
|
||||
minutes = new Date(intTime).getMinutes(),
|
||||
hours = new Date(intTime).getHours(),
|
||||
currentTime = new Date().toString().split(" ");
|
||||
|
||||
minutes = minutes < 10 ? `0${minutes}` : minutes;
|
||||
let finalHours = ``;
|
||||
if (hours > 12) finalHours = `${hours - 12}:${minutes}`;
|
||||
else if (hours === 0) finalHours = `12:${minutes}`;
|
||||
else finalHours = `${hours}:${minutes}`;
|
||||
|
||||
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`;
|
||||
if (relative) {
|
||||
return `${date} ${month} ${year}`;
|
||||
} else return `${finalHours} ${month} ${date} ${year}`;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', e => showPage(window.location.hash))
|
||||
window.addEventListener("load", () => {
|
||||
document.body.classList.remove('hide-completely')
|
||||
showPage(window.location.hash)
|
||||
// document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = validateAddr)
|
||||
document.addEventListener('keyup', (e) => {
|
||||
if (e.code === 'Escape') {
|
||||
hidePopup()
|
||||
}
|
||||
})
|
||||
document.addEventListener("pointerdown", (e) => {
|
||||
if (e.target.closest("button, sm-button:not([disabled]), .interact")) {
|
||||
createRipple(e, e.target.closest("button, sm-button, .interact"));
|
||||
}
|
||||
});
|
||||
document.addEventListener('copy', () => {
|
||||
notify('copied', 'success')
|
||||
})
|
||||
});
|
||||
|
||||
function createRipple(event, target) {
|
||||
const circle = document.createElement("span");
|
||||
const diameter = Math.max(target.clientWidth, target.clientHeight);
|
||||
const radius = diameter / 2;
|
||||
const targetDimensions = target.getBoundingClientRect();
|
||||
circle.style.width = circle.style.height = `${diameter}px`;
|
||||
circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
|
||||
circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
|
||||
circle.classList.add("ripple");
|
||||
const rippleAnimation = circle.animate(
|
||||
[
|
||||
{
|
||||
transform: "scale(3)",
|
||||
opacity: 0,
|
||||
},
|
||||
],
|
||||
{
|
||||
duration: 1000,
|
||||
fill: "forwards",
|
||||
easing: "ease-out",
|
||||
}
|
||||
);
|
||||
target.append(circle);
|
||||
rippleAnimation.onfinish = () => {
|
||||
circle.remove();
|
||||
};
|
||||
}
|
||||
|
||||
function showPage(targetPage, options = {}) {
|
||||
const { firstLoad, hashChange } = options
|
||||
let pageId
|
||||
if (targetPage === '') {
|
||||
pageId = 'overview_page'
|
||||
}
|
||||
else {
|
||||
pageId = targetPage.includes('#') ? targetPage.split('#')[1] : targetPage
|
||||
}
|
||||
if(!appPages.includes(pageId)) return
|
||||
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
|
||||
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
|
||||
getRef(pageId).classList.remove('hide-completely')
|
||||
getRef(pageId).animate([
|
||||
{
|
||||
opacity: 0,
|
||||
transform: 'translateX(-1rem)'
|
||||
},
|
||||
{
|
||||
opacity: 1,
|
||||
transform: 'none'
|
||||
},
|
||||
],
|
||||
{
|
||||
duration: 300,
|
||||
easing: 'ease'
|
||||
})
|
||||
const targetListItem = document.querySelector(`.nav-list__item[href="#${pageId}"]`)
|
||||
targetListItem.classList.add('nav-list__item--active')
|
||||
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
|
||||
getRef('side_nav').scrollTo({
|
||||
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}
|
||||
if (hashChange && window.innerWidth < 640) {
|
||||
getRef('side_nav').close()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user