diff --git a/css/main.css b/css/main.css index 511d177..0b52e83 100644 --- a/css/main.css +++ b/css/main.css @@ -60,6 +60,14 @@ button { display: flex; } +.flex-wrap { + flex-wrap: wrap; +} + +.gap-0-5 { + gap: 0.5rem; +} + .align-items-center { align-items: center; } @@ -76,6 +84,10 @@ button { hyphens: auto; } +.margin-left-auto { + margin-left: auto; +} + .observe-empty-state:empty { display: none; } @@ -155,6 +167,30 @@ button { margin-top: 1rem; } +.button { + display: flex; + align-items: center; + padding: 0.4rem 0.8rem; + text-decoration: none; + border-radius: 3rem; + margin-left: auto; + font-weight: 500; + color: var(--accent-color); + gap: 0.3rem; +} +.button--primary { + background-color: var(--accent-color); + color: white; +} +.button--primary .icon { + fill: white; +} +.button:disabled { + opacity: 0.5; + cursor: not-allowed; + filter: saturate(0); +} + .cert-card { display: grid; gap: 0.6rem; @@ -173,15 +209,6 @@ button { font-size: 0.9rem; color: rgba(var(--text-color), 0.9); } -.cert-card a { - padding: 0.6rem 1rem; - text-decoration: none; - background-color: var(--accent-color); - color: white; - border-radius: 3rem; - margin-left: auto; - font-weight: 500; -} .cert-card .tag { padding: 0.3rem 0.5rem; border-radius: 0.3rem; diff --git a/css/main.min.css b/css/main.min.css index 4ebb37c..7223d88 100644 --- a/css/main.min.css +++ b/css/main.min.css @@ -1 +1 @@ -*{padding:0;margin:0;box-sizing:border-box;font-family:"Roboto slab",serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: rgb(231, 44, 55);--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: rgb(91, 33, 255);--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}.capitalize{text-transform:capitalize}.flex{display:flex}.align-items-center{align-items:center}.space-between{justify-content:space-between}.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}#loader{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;gap:1rem}#home>*{width:min(100%,56rem);margin:0 auto}#home h1{padding:1rem;padding-top:10vmax;font-size:max(1.8rem,4vw);text-align:center;color:var(--accent-color)}@-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:3rem;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:.5rem;padding:1rem;padding-bottom:4rem;margin-top:1rem}.cert-card{display:grid;gap:.6rem;padding:1rem;background-color:rgba(var(--text-color), 0.03);border-radius:.5rem}.cert-card h4{font-size:1.2rem}.cert-card time{font-size:.9rem;color:rgba(var(--text-color), 0.8)}.cert-card p{font-size:.9rem;color:rgba(var(--text-color), 0.9)}.cert-card a{padding:.6rem 1rem;text-decoration:none;background-color:var(--accent-color);color:#fff;border-radius:3rem;margin-left:auto;font-weight:500}.cert-card .tag{padding:.3rem .5rem;border-radius:.3rem;font-size:.9rem;font-weight:500;color:rgba(var(--text-color), 0.9);background-color:rgba(var(--text-color), 0.06);margin-right:auto}.cert-card .tag::first-letter{text-transform:uppercase}@media(max-width: 768px){.cert-card{margin:0 -1rem;gap:1rem}}.hidden{display:none !important} \ No newline at end of file +*{padding:0;margin:0;box-sizing:border-box;font-family:"Roboto slab",serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: rgb(231, 44, 55);--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: rgb(91, 33, 255);--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}.capitalize{text-transform:capitalize}.flex{display:flex}.flex-wrap{flex-wrap:wrap}.gap-0-5{gap:.5rem}.align-items-center{align-items:center}.space-between{justify-content:space-between}.wrap-around{overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;-webkit-hyphens:auto;hyphens:auto}.margin-left-auto{margin-left:auto}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}#loader{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;gap:1rem}#home>*{width:min(100%,56rem);margin:0 auto}#home h1{padding:1rem;padding-top:10vmax;font-size:max(1.8rem,4vw);text-align:center;color:var(--accent-color)}@-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:3rem;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:.5rem;padding:1rem;padding-bottom:4rem;margin-top:1rem}.button{display:flex;align-items:center;padding:.4rem .8rem;text-decoration:none;border-radius:3rem;margin-left:auto;font-weight:500;color:var(--accent-color);gap:.3rem}.button--primary{background-color:var(--accent-color);color:#fff}.button--primary .icon{fill:#fff}.button:disabled{opacity:.5;cursor:not-allowed;filter:saturate(0)}.cert-card{display:grid;gap:.6rem;padding:1rem;background-color:rgba(var(--text-color), 0.03);border-radius:.5rem}.cert-card h4{font-size:1.2rem}.cert-card time{font-size:.9rem;color:rgba(var(--text-color), 0.8)}.cert-card p{font-size:.9rem;color:rgba(var(--text-color), 0.9)}.cert-card .tag{padding:.3rem .5rem;border-radius:.3rem;font-size:.9rem;font-weight:500;color:rgba(var(--text-color), 0.9);background-color:rgba(var(--text-color), 0.06);margin-right:auto}.cert-card .tag::first-letter{text-transform:uppercase}@media(max-width: 768px){.cert-card{margin:0 -1rem;gap:1rem}}.hidden{display:none !important} \ No newline at end of file diff --git a/css/main.scss b/css/main.scss index 4c2bebe..e75556b 100644 --- a/css/main.scss +++ b/css/main.scss @@ -57,6 +57,12 @@ button { .flex { display: flex; } +.flex-wrap { + flex-wrap: wrap; +} +.gap-0-5 { + gap: 0.5rem; +} .align-items-center { align-items: center; } @@ -69,6 +75,9 @@ button { word-break: break-word; hyphens: auto; } +.margin-left-auto { + margin-left: auto; +} .observe-empty-state:empty { display: none; @@ -136,6 +145,29 @@ button { padding-bottom: 4rem; margin-top: 1rem; } +.button { + display: flex; + align-items: center; + padding: 0.4rem 0.8rem; + text-decoration: none; + border-radius: 3rem; + margin-left: auto; + font-weight: 500; + color: var(--accent-color); + gap: 0.3rem; + &--primary { + background-color: var(--accent-color); + color: white; + .icon { + fill: white; + } + } + &:disabled { + opacity: 0.5; + cursor: not-allowed; + filter: saturate(0); + } +} .cert-card { display: grid; gap: 0.6rem; @@ -153,15 +185,6 @@ button { font-size: 0.9rem; color: rgba(var(--text-color), 0.9); } - a { - padding: 0.6rem 1rem; - text-decoration: none; - background-color: var(--accent-color); - color: white; - border-radius: 3rem; - margin-left: auto; - font-weight: 500; - } .tag { padding: 0.3rem 0.5rem; border-radius: 0.3rem; diff --git a/index.html b/index.html index 506dae4..060db80 100644 --- a/index.html +++ b/index.html @@ -260,40 +260,40 @@ } const render = { issuedCertCard(details) { - const { floData, txid, name, floId, certType, time } = details + const { floData, txid, name, floId, certType, time, verificationLink } = details return html`
  • -

    ${name.toLowerCase()}

    + ${certType.toLowerCase()}
    +

    ${name.toLowerCase()}

    ${floId}

    -
    - ${certType.toLowerCase()} - Download -
    +
    + Verify + +
  • `; }, - certificate(txid) { - const { floData, time, name, floId, certType, isNewer, certPara } = floGlobals.validCerts.get(txid) + certificate(txid, downloadButton) { + const { floData, time, name, floId, certType, isNewer, certPara, verificationLink } = floGlobals.validCerts.get(txid) let paraSplitWord let certificateVerification = '' switch (certType) { case "CERTIFICATE OF INTERNSHIP": - certificateVerification = 'internCertificate'; paraSplitWord = 'worked' break; case "CERTIFICATE OF EMPLOYMENT": - certificateVerification = 'employeeCertificate'; paraSplitWord = 'was employed' break; case "CERTIFICATE OF VOLUNTEERSHIP": - certificateVerification = 'volunteerCertificate'; paraSplitWord = 'was employed' break; case "CERTIFICATE OF PARTICIPATION": - certificateVerification = 'participationCertificate'; paraSplitWord = 'participated' break; } @@ -338,7 +338,7 @@ certPdf.text("Scan to verify this certificate", 700, 850, { align: 'center' }); // jspdf add svg let svgNode = QRCode({ - msg: `https://www.ranchimall.net/verify/?${certificateVerification}=${txid}`, + msg: verificationLink, dim: 160 }); const svgData = new XMLSerializer().serializeToString(svgNode); @@ -352,6 +352,10 @@ const imgData = canvas.toDataURL('image/png'); certPdf.addImage(imgData, 'PNG', 620, 670, 160, 160); certPdf.save(`RanchiMall ${certType.toLowerCase()} for ${name}.pdf`); + if (downloadButton) { + downloadButton.disabled = false; + downloadButton.lastChild.textContent = "Download"; + } }; } } @@ -362,7 +366,7 @@ floBlockchainAPI.readAllTxs('FFCpiaZi31TpbYw5q5VNk8qJMeDiTLgsrE').then(res => { // res.unshift({ floData: 'CERTIFICATE OF INTERNSHIP|FPFeL5PXzW9bGosUjQYCxTHSMHidnygvvd|Sairaj mote|worked as an intern on projects for RanchiMall from 11th September 2020 to 2nd February 2021: Twitter Marketing and Peer-to-Peer Content Collaboration on FLO Blockchain. She contributed mostly to Twitter marketing and also collaborated with other content writers on writing articles for RanchiMall Times. She performed well under the guidance of the RIBC team of RanchiMall.', time: Date.now() }) for (tx of res) { - const { vin, vout, time, floData } = tx + const { vin, vout, time, floData, txid } = tx if (!vin.some(i => i.addr === floGlobals.RM_CertificateIssuer_id)) continue; if (!vout.some(o => [floGlobals.RMincorporationID, floGlobals.RIBC_id].includes(o.scriptPubKey.addresses[0]))) continue; if (!floData.startsWith('CERTIFICATE OF')) continue; @@ -373,12 +377,28 @@ [certType, floId, name, certPara] = floData.split('|') } else { floId = floData.match(/\b\w{30,36}\b/)?.[0].trim() - name = getBetween(floData, 'certifies that', 'FLO ID').trim() + name = getBetween(floData, 'certifies that', 'FLO ID').replace(/(,|\s)+$/, '') certType = getFirstThreeWords(floData).trim() isNewer = false } if (!floId) continue; - floGlobals.validCerts.set(tx.txid, { name, ...tx, floId, certType, isNewer, certPara }) + let certificateVerification = '' + switch (certType) { + case "CERTIFICATE OF INTERNSHIP": + certificateVerification = 'internCertificate'; + break; + case "CERTIFICATE OF EMPLOYMENT": + certificateVerification = 'employeeCertificate'; + break; + case "CERTIFICATE OF VOLUNTEERSHIP": + certificateVerification = 'volunteerCertificate'; + break; + case "CERTIFICATE OF PARTICIPATION": + certificateVerification = 'participationCertificate'; + break; + } + const verificationLink = `https://www.ranchimall.net/verify/?${certificateVerification}=${txid}` + floGlobals.validCerts.set(txid, { name, ...tx, floId, certType, isNewer, certPara, verificationLink }) } resolve() }).catch(err => { @@ -386,6 +406,16 @@ }) }) } + getRef('issued_cert_list').addEventListener('click', e => { + if (e.target.closest('.download-button')) { + const downloadButton = e.target.closest('.download-button') + downloadButton.disabled = true; + downloadButton.lastChild.textContent = 'downloading...'; + setTimeout(() => { + render.certificate(downloadButton.dataset.txid, downloadButton) + }, 300); + } + })