Added search functionality

This commit is contained in:
sairaj mote 2022-12-03 19:58:44 +05:30
parent 2f74539d36
commit 969e337e9f
5 changed files with 443 additions and 242 deletions

View File

@ -2,7 +2,7 @@
padding: 0; padding: 0;
margin: 0; margin: 0;
box-sizing: border-box; box-sizing: border-box;
font-family: "Times New Roman", Times, serif; font-family: "Roboto", sans-serif;
} }
:root { :root {
@ -52,23 +52,58 @@ button {
cursor: pointer; cursor: pointer;
} }
input[type=date] { .wrap-around {
padding: 1rem 0.8rem; overflow-wrap: break-word;
font-size: inherit; word-wrap: break-word;
background-color: rgba(var(--text-color), 0.06); word-break: break-word;
border: none; -webkit-hyphens: auto;
border-radius: 0.3rem; hyphens: auto;
font-weight: 500;
} }
#details { .observe-empty-state:empty {
align-content: flex-start; display: none;
padding: 1.5rem;
display: grid;
gap: 1rem;
} }
#details * {
font-family: "Roboto", sans-serif; .observe-empty-state:not(:empty) ~ .empty-state {
display: none;
}
#home > * {
width: min(100%, 56rem);
margin: 0 auto;
}
#home h1 {
padding: 1rem;
padding-top: 10vmax;
font-size: max(1.8rem, 4vw);
text-align: center;
background: linear-gradient(135deg, #fa00ff, #00e0ff 50%, #fa00ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 200%;
animation: gradient 20s ease infinite alternate-reverse;
}
@-webkit-keyframes gradient {
0% {
background-position: 0% 50%;
}
100% {
background-position: 100% 50%;
}
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
100% {
background-position: 100% 50%;
}
}
#home header {
width: 100%;
background-color: rgba(var(--text-color), 0.06);
padding-bottom: 2rem;
margin-bottom: -2rem;
} }
#cert_sec { #cert_sec {
@ -76,11 +111,27 @@ input[type=date] {
font-family: "intern"; font-family: "intern";
} }
#search_certificates {
position: -webkit-sticky;
position: sticky;
top: 1rem;
width: min(24rem, 100% - 2rem);
margin: 0 auto;
--border-radius: 0.5rem;
border-radius: 0.5rem;
--padding: 1rem 1.2rem;
background-color: rgba(var(--foreground-color), 1);
box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.1);
border: solid thin rgba(var(--text-color), 0.2);
}
#issued_cert_list { #issued_cert_list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1rem;
padding: 1.5rem; padding: 1rem;
padding-bottom: 4rem;
margin-top: 1rem;
} }
.cert-card { .cert-card {
@ -93,12 +144,25 @@ input[type=date] {
.cert-card h4 { .cert-card h4 {
font-size: 1.2rem; font-size: 1.2rem;
} }
.cert-card > * { .cert-card p {
font-family: "Roboto", sans-serif; font-size: 0.9rem;
color: rgba(var(--text-color), 0.9);
} }
@media (min-width: 768px) { #certificate {
#main { display: flex;
display: grid; align-items: center;
} justify-content: center;
}
#certificate * {
font-family: "Times New Roman", Times, serif;
}
#certificate_svg {
flex-shrink: 0;
background-color: white;
}
.hidden {
display: none !important;
} }

2
css/main.min.css vendored
View File

@ -1 +1 @@
*{padding:0;margin:0;box-sizing:border-box;font-family:"Times New Roman",Times,serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: #3d5afe;--secondary-color: #ffac2e;--text-color: 34, 34, 34;--foreground-color: 252, 253, 255;--background-color: 241, 243, 248;--danger-color: rgb(255, 75, 75);--green: #1cad59;--yellow: rgb(220, 165, 0);color:rgba(var(--text-color), 1);background-color:rgba(var(--background-color), 1)}body[data-theme=dark]{--accent-color: #92a2ff;--secondary-color: #d60739;--text-color: 200, 200, 200;--foreground-color: 27, 28, 29;--background-color: 21, 22, 22;--danger-color: rgb(255, 106, 106);--green: #00e676;--yellow: rgb(255, 213, 5)}body[data-theme=dark] ::-webkit-calendar-picker-indicator{filter:invert(1)}button{padding:1rem;font-size:inherit;background-color:var(--accent-color);border:none;border-radius:.3rem;color:#fff;font-weight:500;cursor:pointer}input[type=date]{padding:1rem .8rem;font-size:inherit;background-color:rgba(var(--text-color), 0.06);border:none;border-radius:.3rem;font-weight:500}#details{align-content:flex-start;padding:1.5rem;display:grid;gap:1rem}#details *{font-family:"Roboto",sans-serif}#cert_sec{padding:1.5rem;font-family:"intern"}#issued_cert_list{display:flex;flex-direction:column;gap:1rem;padding:1.5rem}.cert-card{display:grid;gap:.5rem;padding:1rem;background-color:rgba(var(--text-color), 0.06);border-radius:.5rem}.cert-card h4{font-size:1.2rem}.cert-card>*{font-family:"Roboto",sans-serif}@media(min-width: 768px){#main{display:grid}} *{padding:0;margin:0;box-sizing:border-box;font-family:"Roboto",sans-serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: #3d5afe;--secondary-color: #ffac2e;--text-color: 34, 34, 34;--foreground-color: 252, 253, 255;--background-color: 241, 243, 248;--danger-color: rgb(255, 75, 75);--green: #1cad59;--yellow: rgb(220, 165, 0);color:rgba(var(--text-color), 1);background-color:rgba(var(--background-color), 1)}body[data-theme=dark]{--accent-color: #92a2ff;--secondary-color: #d60739;--text-color: 200, 200, 200;--foreground-color: 27, 28, 29;--background-color: 21, 22, 22;--danger-color: rgb(255, 106, 106);--green: #00e676;--yellow: rgb(255, 213, 5)}body[data-theme=dark] ::-webkit-calendar-picker-indicator{filter:invert(1)}button{padding:1rem;font-size:inherit;background-color:var(--accent-color);border:none;border-radius:.3rem;color:#fff;font-weight:500;cursor:pointer}.wrap-around{overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;-webkit-hyphens:auto;hyphens:auto}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}#home>*{width:min(100%,56rem);margin:0 auto}#home h1{padding:1rem;padding-top:10vmax;font-size:max(1.8rem,4vw);text-align:center;background:linear-gradient(135deg, #fa00ff, #00e0ff 50%, #fa00ff);-webkit-background-clip:text;-webkit-text-fill-color:rgba(0,0,0,0);background-size:200%;animation:gradient 20s ease infinite alternate-reverse}@-webkit-keyframes gradient{0%{background-position:0% 50%}100%{background-position:100% 50%}}@keyframes gradient{0%{background-position:0% 50%}100%{background-position:100% 50%}}#home header{width:100%;background-color:rgba(var(--text-color), 0.06);padding-bottom:2rem;margin-bottom:-2rem}#cert_sec{padding:1.5rem;font-family:"intern"}#search_certificates{position:-webkit-sticky;position:sticky;top:1rem;width:min(24rem,100% - 2rem);margin:0 auto;--border-radius: 0.5rem;border-radius:.5rem;--padding: 1rem 1.2rem;background-color:rgba(var(--foreground-color), 1);box-shadow:0 .5rem 1.5rem rgba(0,0,0,.1);border:solid thin rgba(var(--text-color), 0.2)}#issued_cert_list{display:flex;flex-direction:column;gap:1rem;padding:1rem;padding-bottom:4rem;margin-top:1rem}.cert-card{display:grid;gap:.5rem;padding:1rem;background-color:rgba(var(--text-color), 0.06);border-radius:.5rem}.cert-card h4{font-size:1.2rem}.cert-card p{font-size:.9rem;color:rgba(var(--text-color), 0.9)}#certificate{display:flex;align-items:center;justify-content:center}#certificate *{font-family:"Times New Roman",Times,serif}#certificate_svg{flex-shrink:0;background-color:#fff}.hidden{display:none !important}

View File

@ -2,7 +2,7 @@
padding: 0; padding: 0;
margin: 0; margin: 0;
box-sizing: border-box; box-sizing: border-box;
font-family: "Times New Roman", Times, serif; font-family: "Roboto", sans-serif;
} }
:root { :root {
@ -51,32 +51,74 @@ button {
font-weight: 500; font-weight: 500;
cursor: pointer; cursor: pointer;
} }
input[type="date"] { .wrap-around {
padding: 1rem 0.8rem; overflow-wrap: break-word;
font-size: inherit; word-wrap: break-word;
background-color: rgba(var(--text-color), 0.06); word-break: break-word;
border: none; hyphens: auto;
border-radius: 0.3rem;
font-weight: 500;
} }
#details {
align-content: flex-start; .observe-empty-state:empty {
padding: 1.5rem; display: none;
display: grid; }
gap: 1rem;
* { .observe-empty-state:not(:empty) ~ .empty-state {
font-family: "Roboto", sans-serif; display: none;
}
#home {
& > * {
width: min(100%, 56rem);
margin: 0 auto;
}
h1 {
padding: 1rem;
padding-top: 10vmax;
font-size: max(1.8rem, 4vw);
text-align: center;
background: linear-gradient(135deg, #fa00ff, #00e0ff 50%, #fa00ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 200%;
animation: gradient 20s ease infinite alternate-reverse;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
100% {
background-position: 100% 50%;
}
}
header {
width: 100%;
background-color: rgba(var(--text-color), 0.06);
padding-bottom: 2rem;
margin-bottom: -2rem;
} }
} }
#cert_sec { #cert_sec {
padding: 1.5rem; padding: 1.5rem;
font-family: "intern"; font-family: "intern";
} }
#search_certificates {
position: sticky;
top: 1rem;
width: min(24rem, calc(100% - 2rem));
margin: 0 auto;
--border-radius: 0.5rem;
border-radius: 0.5rem;
--padding: 1rem 1.2rem;
background-color: rgba(var(--foreground-color), 1);
box-shadow: 0 0.5rem 1.5rem rgba(0 0 0 /0.1);
border: solid thin rgba(var(--text-color), 0.2);
}
#issued_cert_list { #issued_cert_list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1rem;
padding: 1.5rem; padding: 1rem;
padding-bottom: 4rem;
margin-top: 1rem;
} }
.cert-card { .cert-card {
display: grid; display: grid;
@ -87,12 +129,26 @@ input[type="date"] {
h4 { h4 {
font-size: 1.2rem; font-size: 1.2rem;
} }
& > * { p {
font-family: "Roboto", sans-serif; font-size: 0.9rem;
color: rgba(var(--text-color), 0.9);
} }
} }
#certificate {
display: flex;
align-items: center;
justify-content: center;
* {
font-family: "Times New Roman", Times, serif;
}
}
#certificate_svg {
flex-shrink: 0;
background-color: white;
}
@media (min-width: 768px) { @media (min-width: 768px) {
#main { }
display: grid;
} .hidden {
display: none !important;
} }

View File

@ -32,11 +32,24 @@
</head> </head>
<body> <body>
<section> <section id="home" class="page">
<ul id="issued_cert_list"></ul> <header>
<h1>RanchiMall Certificates</h1>
</header>
<sm-input id="search_certificates" placeholder="Search FLO address or name" type="search">
<svg slot="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</sm-input>
<ul id="issued_cert_list" class="observe-empty-state"></ul>
<div class="empty-state">
<h2>No related certificates issued yet</h2>
</div>
</section> </section>
<main id="main"> <section id="certificate" class="page hidden">
<section>
<svg id="certificate_svg" width="1400" height="980" viewBox="0 0 1400 980" fill="none" <svg id="certificate_svg" width="1400" height="980" viewBox="0 0 1400 980" fill="none"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<g id="certificate"> <g id="certificate">
@ -63,8 +76,8 @@
font-size="18"> font-size="18">
<tspan x="490.187" y="310.073">RanchiMall, a blockchain incorporated entity certifies that </tspan> <tspan x="490.187" y="310.073">RanchiMall, a blockchain incorporated entity certifies that </tspan>
</text> </text>
<text id="issue_date" fill="#373737" xml:space="preserve" style="white-space: pre" <text id="issue_date" fill="#373737" xml:space="preserve" style="white-space: pre" font-family="Times New Roman"
font-family="Times New Roman" font-size="18"> font-size="18">
<tspan x="647.493" y="253.573">16th Dec 2020</tspan> <tspan x="647.493" y="253.573">16th Dec 2020</tspan>
</text> </text>
<g id="Frame_2" clip-path="url(#clip1_60_2)"> <g id="Frame_2" clip-path="url(#clip1_60_2)">
@ -83,8 +96,8 @@
<tspan x="506.293" y="217.646">CERTIFICATE TYPE</tspan> <tspan x="506.293" y="217.646">CERTIFICATE TYPE</tspan>
</text> </text>
<rect id="Rectangle 69" x="62" y="57" width="1277" height="865" rx="12" stroke="#5B21FF" stroke-width="8" /> <rect id="Rectangle 69" x="62" y="57" width="1277" height="865" rx="12" stroke="#5B21FF" stroke-width="8" />
<text id="cert_data" fill="#333333" xml:space="preserve" style="white-space: pre" <text id="cert_data" fill="#333333" xml:space="preserve" style="white-space: pre" font-family="Times New Roman"
font-family="Times New Roman" font-size="18"> font-size="18">
</text> </text>
<g id="Group 12"> <g id="Group 12">
<text id="FLO INCORPORATION ID" fill="#353535" xml:space="preserve" style="white-space: pre" <text id="FLO INCORPORATION ID" fill="#353535" xml:space="preserve" style="white-space: pre"
@ -133,22 +146,7 @@
</clipPath> </clipPath>
</defs> </defs>
</svg> </svg>
</section> </section>
<section id="details">
<!-- <h3>Fill the details</h3>
<sm-input id="cert_type_field" data-bind="name" placeholder="Certificate type" animate></sm-input>
<sm-input id="name_field" data-bind="name" placeholder="Name" animate></sm-input>
<input type="date" id="issue_date_field" data-bind="issue_date" placeholder="Issue date">
<sm-input id="intern_id_field" data-bind="intern_flo_id" placeholder="Intern FLO ID" animate>
</sm-input>
<sm-input id="flo_link" data-bind="intern_flo_id" placeholder="FLO trasansaction link" animate>
</sm-input>
<sm-textarea id="cert_text" placeholder="data" rows="4"></sm-textarea> -->
<button id="download_btn">Download</button>
</section>
</main>
<script> <script>
// Use instead of document.getElementById // Use instead of document.getElementById
const domRefs = {} const domRefs = {}
@ -173,7 +171,6 @@
const appState = { const appState = {
params: {}, params: {},
} }
const generalPages = ['sign_up', 'sign_in', 'loading', 'landing']
function routeTo(targetPage, options = {}) { function routeTo(targetPage, options = {}) {
const { firstLoad } = options const { firstLoad } = options
const routingAnimation = { in: slideInUp, out: slideOutUp } const routingAnimation = { in: slideInUp, out: slideOutUp }
@ -182,12 +179,8 @@
let searchParams let searchParams
let params let params
if (targetPage === '') { if (targetPage === '') {
try { pageId = 'home'
if (floDapps.user.id) history.replaceState(null, null, '#/home');
pageId = 'dashboard_page'
} catch (e) {
pageId = 'landing'
}
} else { } else {
if (targetPage.includes('/')) { if (targetPage.includes('/')) {
if (targetPage.includes('?')) { if (targetPage.includes('?')) {
@ -201,16 +194,7 @@
pageId = targetPage pageId = targetPage
} }
} }
if (!getRef(pageId)?.classList.contains('page')) return
if (!document.querySelector(`#${pageId}`)?.classList.contains('inner-page')) return
try {
if (floDapps.user.id && (generalPages.includes(pageId))) {
history.replaceState(null, null, '#/dashboard_page');
pageId = 'dashboard_page'
}
} catch (e) {
if (!(generalPages.includes(pageId))) return
}
appState.currentPage = pageId appState.currentPage = pageId
if (searchParams) { if (searchParams) {
@ -220,19 +204,14 @@
if (params) if (params)
appState.params = params appState.params = params
switch (pageId) { switch (pageId) {
case 'landing': case 'home':
renderElem(getRef('issued_cert_list'), html`${[...floGlobals.validCerts.values()].map(cert => render.issuedCertCard(cert))}`)
break; break;
} }
if (appState.lastPage !== pageId) { if (appState.lastPage !== pageId) {
if (document.querySelector('.nav-list__item--active')) if (document.querySelector('.nav-list__item--active'))
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active'); document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active');
const targetListItem = [...document.querySelectorAll(`a.nav-list__item`)].find(item => item.href.includes(pageId)) const targetListItem = [...document.querySelectorAll(`a.nav-list__item`)].find(item => item.href.includes(pageId))
if (targetListItem) {
targetListItem.classList.add('nav-list__item--active')
getRef('main_nav').classList.remove('hide-on-mobile')
} else {
getRef('main_nav').classList.add('hide-on-mobile')
}
document.querySelectorAll('.page').forEach(page => page.classList.add('hidden')) document.querySelectorAll('.page').forEach(page => page.classList.add('hidden'))
getRef(pageId).closest('.page').classList.remove('hidden') getRef(pageId).closest('.page').classList.remove('hidden')
let ogOverflow = getRef(pageId).parentNode.style.overflow let ogOverflow = getRef(pageId).parentNode.style.overflow
@ -243,10 +222,16 @@
} }
} }
getRef(pageId).classList.remove('hidden') getRef(pageId).classList.remove('hidden')
if (pageId === 'certificate') {
if (params) {
render.certificate(params.id)
}
}
getRef(pageId).animate(routingAnimation.in, { duration: floGlobals.prefersReducedMotion ? 0 : 150, fill: 'forwards', easing: 'ease' }).onfinish = (e) => { getRef(pageId).animate(routingAnimation.in, { duration: floGlobals.prefersReducedMotion ? 0 : 150, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
getRef(pageId).parentNode.style.overflow = ogOverflow; getRef(pageId).parentNode.style.overflow = ogOverflow;
switch (pageId) { switch (pageId) {
case 'sign_in': case 'certificate':
convertSvgToPdf(getRef('certificate_svg'))
break; break;
} }
appState.lastPage = pageId appState.lastPage = pageId
@ -256,6 +241,86 @@
</script> </script>
<script> <script>
const { html, render: renderElem } = uhtml; const { html, render: renderElem } = uhtml;
const slideInLeft = [
{
opacity: 0,
transform: 'translateX(1rem)'
},
{
opacity: 1,
transform: 'translateX(0)'
}
]
const slideOutLeft = [
{
opacity: 1,
transform: 'translateX(0)'
},
{
opacity: 0,
transform: 'translateX(-1rem)'
},
]
const slideInRight = [
{
opacity: 0,
transform: 'translateX(-1rem)'
},
{
opacity: 1,
transform: 'translateX(0)'
}
]
const slideOutRight = [
{
opacity: 1,
transform: 'translateX(0)'
},
{
opacity: 0,
transform: 'translateX(1rem)'
},
]
const slideInDown = [
{
opacity: 0,
transform: 'translateY(-1rem)'
},
{
opacity: 1,
transform: 'translateY(0)'
},
]
const slideOutDown = [
{
opacity: 1,
transform: 'translateY(0)'
},
{
opacity: 0,
transform: 'translateY(1rem)'
},
]
const slideInUp = [
{
opacity: 0,
transform: 'translateY(1rem)'
},
{
opacity: 1,
transform: 'translateY(0)'
},
]
const slideOutUp = [
{
opacity: 1,
transform: 'translateY(0)'
},
{
opacity: 0,
transform: 'translateY(-1rem)'
},
]
function getFormattedTime(timestamp, format) { function getFormattedTime(timestamp, format) {
try { try {
timestamp = parseInt(timestamp) timestamp = parseInt(timestamp)
@ -290,16 +355,38 @@
return timestamp; return timestamp;
} }
} }
window.addEventListener('hashchange', e => routeTo(window.location.hash))
window.onload = () => { window.onload = () => {
const { jsPDF } = window.jspdf; readTx().then(() => {
const { svg2pdf } = window.svg2pdf; routeTo(window.location.hash);
})
getRef('search_certificates').addEventListener('input', e => {
const searchQuery = e.target.value.toLowerCase();
const filteredCerts = [...floGlobals.validCerts.values()].filter(cert => {
return cert.name.toLowerCase().includes(searchQuery) || cert.floId.toLowerCase().includes(searchQuery)
})
// sort filtered by relevance
filteredCerts.sort((a, b) => {
if (a.name.toLowerCase().includes(searchQuery) && b.name.toLowerCase().includes(searchQuery)) {
return a.name.toLowerCase().indexOf(searchQuery) - b.name.toLowerCase().indexOf(searchQuery)
}
if (a.name.toLowerCase().includes(searchQuery)) {
return -1
}
if (b.name.toLowerCase().includes(searchQuery)) {
return 1
}
return 0
})
renderElem(getRef('issued_cert_list'), html`${filteredCerts.map(cert => render.issuedCertCard(cert))}`)
})
}
function convertSvgToPdf(element) { function convertSvgToPdf(element) {
const margin = 5 const margin = 5
const sizeArray = new Array(2) const sizeArray = new Array(2)
sizeArray[0] = 1400 + 2 * margin sizeArray[0] = 1400 + 2 * margin
sizeArray[1] = 980 + 2 * margin sizeArray[1] = 980 + 2 * margin
// eslint-disable-next-line no-undef,new-cap const jsPdf = new window.jspdf.jsPDF({
const jsPdf = new jsPDF({
orientation: sizeArray[0] > sizeArray[1] ? 'l' : 'p', orientation: sizeArray[0] > sizeArray[1] ? 'l' : 'p',
unit: 'pt', unit: 'pt',
format: sizeArray, format: sizeArray,
@ -315,22 +402,11 @@
}) })
.then(() => { .then(() => {
// save the created pdf // save the created pdf
jsPdf.save('myPDF.pdf') // jsPdf.save('RanchiMallCertificate.pdf')
}) })
} }
getRef('download_btn').addEventListener('click', e => {
var myPDF = convertSvgToPdf(getRef('certificate_svg'))
})
getRef('issued_cert_list').addEventListener('click', e => {
if (e.target.closest('button')) {
const txId = e.target.closest('button').getAttribute('data-txid')
render.certificate(txId)
}
})
readTx()
}
function alignTextCenter(element) { function alignTextCenter(element) {
element.setAttribute('x', `${700 - element.getBoundingClientRect().width / 2}`) element.setAttribute('x', 700 - element.getBoundingClientRect().width / 2)
} }
// return string between two strings // return string between two strings
function getBetween(str, start, end) { function getBetween(str, start, end) {
@ -340,6 +416,10 @@
function getFirstThreeWords(str) { function getFirstThreeWords(str) {
return str.split(' ').slice(0, 3).join(' ') return str.split(' ').slice(0, 3).join(' ')
} }
// get all words after given word including the word
function removeWordsBefore(str, word) {
return str.substring(str.indexOf(word));
}
// split string into lines of max characters per line without breaking words // split string into lines of max characters per line without breaking words
function splitIntoLines(str, maxChars = 132) { function splitIntoLines(str, maxChars = 132) {
let lines = [] let lines = []
@ -358,21 +438,17 @@
} }
const render = { const render = {
issuedCertCard(details) { issuedCertCard(details) {
const { floData, txid } = details const { floData, txid, name, floId } = details
const name = getBetween(floData, 'certifies that', 'FLO ID')
const floId = floData.match(/\b\w{30,36}\b/)
return html` return html`
<li class="cert-card"> <li class="cert-card">
<h4>${name}</h4> <h4>${name}</h4>
<p>${floId}</p> <p class="wrap-around">${floId}</p>
<button data-txid=${txid}>View</button> <a href=${`#/certificate?id=${txid}`}>View</a>
</li> </li>
`; `;
}, },
certificate(txid) { certificate(txid) {
const { floData, time } = floGlobals.validCerts.get(txid) const { floData, time, name, floId } = floGlobals.validCerts.get(txid)
const name = getBetween(floData, 'certifies that', 'FLO ID')
const floId = floData.match(/\b\w{30,36}\b/)
getRef('certificate_type').firstElementChild.textContent = getFirstThreeWords(floData).toUpperCase(); getRef('certificate_type').firstElementChild.textContent = getFirstThreeWords(floData).toUpperCase();
alignTextCenter(getRef('certificate_type').firstElementChild) alignTextCenter(getRef('certificate_type').firstElementChild)
getRef('main_name').firstElementChild.textContent = name.toUpperCase(); getRef('main_name').firstElementChild.textContent = name.toUpperCase();
@ -382,7 +458,7 @@
getRef('intern_flo_id').firstElementChild.textContent = floId getRef('intern_flo_id').firstElementChild.textContent = floId
alignTextCenter(getRef('intern_flo_id').firstElementChild) alignTextCenter(getRef('intern_flo_id').firstElementChild)
getRef('cert_data').innerHTML = '' getRef('cert_data').innerHTML = ''
splitIntoLines(floData).forEach((line, index) => { splitIntoLines(removeWordsBefore(floData, 'worked')).forEach((line, index) => {
let tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan') let tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')
tspan.textContent = line tspan.textContent = line
tspan.setAttribute('x', '0') tspan.setAttribute('x', '0')
@ -418,20 +494,26 @@
getRef('cert_qr').appendChild(svgNode); getRef('cert_qr').appendChild(svgNode);
} }
} }
floGlobals.validCerts = new Map() floGlobals.validCerts = new Map()
function readTx() { function readTx() {
return new Promise((resolve, reject) => {
floBlockchainAPI.readAllTxs('FFCpiaZi31TpbYw5q5VNk8qJMeDiTLgsrE').then(res => { floBlockchainAPI.readAllTxs('FFCpiaZi31TpbYw5q5VNk8qJMeDiTLgsrE').then(res => {
res.forEach(tx => { res.forEach(tx => {
const { vin, vout, time, floData } = tx const { vin, vout, time, floData } = tx
const iVerify = vin.some(i => i.addr === floGlobals.RM_CertificateIssuer_id); const iVerify = vin.some(i => i.addr === floGlobals.RM_CertificateIssuer_id);
const oVerify = vout.some(o => [floGlobals.RMincorporationID, floGlobals.RIBC_id].includes(o.scriptPubKey.addresses[0])); const oVerify = vout.some(o => [floGlobals.RMincorporationID, floGlobals.RIBC_id].includes(o.scriptPubKey.addresses[0]));
const cVerify = tx.floData.startsWith('CERTIFICATE OF') const cVerify = tx.floData.startsWith('CERTIFICATE OF')
const hasFloId = /\b\w{30,36}\b/.test(floData) const floId = floData.match(/\b\w{30,36}\b/)?.[0]
if (iVerify && oVerify && cVerify && hasFloId) { if (iVerify && oVerify && cVerify && floId) {
floGlobals.validCerts.set(tx.txid, tx) const name = getBetween(floData, 'certifies that', 'FLO ID')
floGlobals.validCerts.set(tx.txid, { name, ...tx, floId })
} }
}) })
renderElem(getRef('issued_cert_list'), html`${[...floGlobals.validCerts.values()].map(cert => render.issuedCertCard(cert))}`) resolve()
}).catch(err => {
reject(err)
})
}) })
} }
</script> </script>

File diff suppressed because one or more lines are too long