<template> <section id="Content"> <div v-if="claimData"> <canvas ref="claimCanvas"></canvas> </div> </section> </template> <style scoped> canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } </style> <script lang="ts"> import { Component, Vue } from "vue-facing-decorator"; import { nextTick } from "vue"; import QRCode from "qrcode"; import { APP_SERVER, NotificationIface } from "../constants/app"; import { db, retrieveSettingsForActiveAccount } from "../db/index"; import * as endorserServer from "../libs/endorserServer"; @Component export default class ClaimReportCertificateView extends Vue { $notify!: (notification: NotificationIface, timeout?: number) => void; activeDid = ""; allMyDids: Array<string> = []; apiServer = ""; claimId = ""; claimData = null; endorserServer = endorserServer; async created() { const settings = await retrieveSettingsForActiveAccount(); this.activeDid = settings.activeDid || ""; this.apiServer = settings.apiServer || ""; const pathParams = window.location.pathname.substring( "/claim-cert/".length, ); this.claimId = pathParams; await this.fetchClaim(); } async fetchClaim() { try { const response = await fetch( `${this.apiServer}/api/claim/${this.claimId}`, ); if (response.ok) { this.claimData = await response.json(); await nextTick(); // Wait for the DOM to update if (this.claimData) { this.drawCanvas(this.claimData); } } else { throw new Error(`Error fetching claim: ${response.statusText}`); } } catch (error) { console.error("Failed to load claim:", error); this.$notify({ group: "alert", type: "danger", title: "Error", text: "There was a problem loading the claim.", }); } } async drawCanvas( claimData: endorserServer.GenericCredWrapper<endorserServer.GenericVerifiableCredential>, ) { await db.open(); const allContacts = await db.contacts.toArray(); const canvas = this.$refs.claimCanvas as HTMLCanvasElement; if (canvas) { const CANVAS_WIDTH = 1100; const CANVAS_HEIGHT = 850; // size to approximate portrait of 8.5"x11" canvas.width = CANVAS_WIDTH; canvas.height = CANVAS_HEIGHT; const ctx = canvas.getContext("2d"); if (ctx) { // Load the background image const backgroundImage = new Image(); backgroundImage.src = "/img/background/cert-frame-2.jpg"; backgroundImage.onload = async () => { // Draw the background image ctx.drawImage(backgroundImage, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); // Set font and styles ctx.fillStyle = "black"; // Draw claim type ctx.font = "bold 20px Arial"; const claimTypeText = this.endorserServer.capitalizeAndInsertSpacesBeforeCaps( claimData.claimType || "", ); const claimTypeWidth = ctx.measureText(claimTypeText).width; ctx.fillText( claimTypeText, (CANVAS_WIDTH - claimTypeWidth) / 2, // Center horizontally CANVAS_HEIGHT * 0.33, ); if (claimData.claim.agent) { const presentedText = "Presented to "; ctx.font = "14px Arial"; const presentedWidth = ctx.measureText(presentedText).width; ctx.fillText( presentedText, (CANVAS_WIDTH - presentedWidth) / 2, // Center horizontally CANVAS_HEIGHT * 0.37, ); const agentText = endorserServer.didInfoForCertificate( claimData.claim.agent, allContacts, ); ctx.font = "bold 20px Arial"; const agentWidth = ctx.measureText(agentText).width; ctx.fillText( agentText, (CANVAS_WIDTH - agentWidth) / 2, // Center horizontally CANVAS_HEIGHT * 0.4, ); } const descriptionText = claimData.claim.name || claimData.claim.description; if (descriptionText) { const descriptionLine = descriptionText.length > 50 ? descriptionText.substring(0, 75) + "..." : descriptionText; ctx.font = "14px Arial"; const descriptionWidth = ctx.measureText(descriptionLine).width; ctx.fillText( descriptionLine, (CANVAS_WIDTH - descriptionWidth) / 2, CANVAS_HEIGHT * 0.45, ); } // Draw claim issuer & recipient if (claimData.issuer) { ctx.font = "14px Arial"; const issuerText = "Issued by " + endorserServer.didInfoForCertificate( claimData.issuer, allContacts, ); ctx.fillText(issuerText, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.6); } // Draw claim ID ctx.font = "14px Arial"; ctx.fillText(this.claimId, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.7); ctx.fillText( "via EndorserSearch.com", CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.73, ); // Generate and draw QR code const qrCodeCanvas = document.createElement("canvas"); await QRCode.toCanvas( qrCodeCanvas, APP_SERVER + "/claim/" + this.claimId, { width: 150, color: { light: "#0000" /* Transparent background */ }, }, ); ctx.drawImage(qrCodeCanvas, CANVAS_WIDTH * 0.6, CANVAS_HEIGHT * 0.55); }; } } } } </script>