ClaimReportCertificateView

This commit is contained in:
Matthew Raymer
2025-07-08 11:41:13 +00:00
parent 1f54ffc248
commit 698bee6a27
3 changed files with 231 additions and 39 deletions

View File

@@ -161,6 +161,13 @@ export const NOTIFY_CONFIRMATIONS_ONLY_SUCCESS = {
message: "Your confirmations have been recorded.",
};
// ClaimReportCertificateView.vue specific constants
// Used in: ClaimReportCertificateView.vue (fetchClaim method - error loading claim)
export const NOTIFY_ERROR_LOADING_CLAIM = {
title: "Error",
message: "There was a problem loading the claim.",
};
// ContactsView.vue specific constants
// Used in: ContactsView.vue (processInviteJwt method - blank invite error)
export const NOTIFY_BLANK_INVITE = {

View File

@@ -12,29 +12,48 @@ import { nextTick } from "vue";
import QRCode from "qrcode";
import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import * as endorserServer from "../libs/endorserServer";
import {
GenericCredWrapper,
GenericVerifiableCredential,
} from "../interfaces/common";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@Component
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { NOTIFY_ERROR_LOADING_CLAIM } from "@/constants/notifications";
@Component({
mixins: [PlatformServiceMixin],
})
export default class ClaimReportCertificateView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
// Notification helper
notify!: ReturnType<typeof createNotifyHelpers>;
activeDid = "";
allMyDids: Array<string> = [];
apiServer = "";
claimId = "";
claimData = null;
allContacts: Contact[] = [];
endorserServer = endorserServer;
// Computed properties for canvas optimization
get CANVAS_WIDTH() {
return 1100;
}
get CANVAS_HEIGHT() {
return 850;
}
async created() {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
// Initialize notification helper
this.notify = createNotifyHelpers(this.$notify);
const settings = await this.$settings();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
const pathParams = window.location.pathname.substring(
@@ -60,12 +79,7 @@ export default class ClaimReportCertificateView extends Vue {
}
} catch (error) {
logger.error("Failed to load claim:", error);
this.$notify({
group: "alert",
type: "danger",
title: "Error",
text: "There was a problem loading the claim.",
});
this.notify.error(NOTIFY_ERROR_LOADING_CLAIM.message, TIMEOUTS.LONG);
}
}
@@ -74,22 +88,16 @@ export default class ClaimReportCertificateView extends Vue {
return;
}
const platformService = PlatformServiceFactory.getInstance();
const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
const allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
// Load contacts if not already loaded
if (this.allContacts.length === 0) {
this.allContacts = await this.$getAllContacts();
}
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;
canvas.width = this.CANVAS_WIDTH;
canvas.height = this.CANVAS_HEIGHT;
const ctx = canvas.getContext("2d");
if (ctx) {
// Load the background image
@@ -97,7 +105,13 @@ export default class ClaimReportCertificateView extends Vue {
backgroundImage.src = "/img/background/cert-frame-2.jpg";
backgroundImage.onload = async () => {
// Draw the background image
ctx.drawImage(backgroundImage, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
ctx.drawImage(
backgroundImage,
0,
0,
this.CANVAS_WIDTH,
this.CANVAS_HEIGHT,
);
// Set font and styles
ctx.fillStyle = "black";
@@ -111,8 +125,8 @@ export default class ClaimReportCertificateView extends Vue {
const claimTypeWidth = ctx.measureText(claimTypeText).width;
ctx.fillText(
claimTypeText,
(CANVAS_WIDTH - claimTypeWidth) / 2, // Center horizontally
CANVAS_HEIGHT * 0.33,
(this.CANVAS_WIDTH - claimTypeWidth) / 2, // Center horizontally
this.CANVAS_HEIGHT * 0.33,
);
if (claimData.claim.agent) {
@@ -121,19 +135,21 @@ export default class ClaimReportCertificateView extends Vue {
const presentedWidth = ctx.measureText(presentedText).width;
ctx.fillText(
presentedText,
(CANVAS_WIDTH - presentedWidth) / 2, // Center horizontally
CANVAS_HEIGHT * 0.37,
(this.CANVAS_WIDTH - presentedWidth) / 2, // Center horizontally
this.CANVAS_HEIGHT * 0.37,
);
const agentText = endorserServer.didInfoForCertificate(
claimData.claim.agent,
allContacts,
typeof claimData.claim.agent === "string"
? claimData.claim.agent
: claimData.claim.agent?.identifier,
this.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,
(this.CANVAS_WIDTH - agentWidth) / 2, // Center horizontally
this.CANVAS_HEIGHT * 0.4,
);
}
@@ -148,8 +164,8 @@ export default class ClaimReportCertificateView extends Vue {
const descriptionWidth = ctx.measureText(descriptionLine).width;
ctx.fillText(
descriptionLine,
(CANVAS_WIDTH - descriptionWidth) / 2,
CANVAS_HEIGHT * 0.45,
(this.CANVAS_WIDTH - descriptionWidth) / 2,
this.CANVAS_HEIGHT * 0.45,
);
}
@@ -160,18 +176,26 @@ export default class ClaimReportCertificateView extends Vue {
"Issued by " +
endorserServer.didInfoForCertificate(
claimData.issuer,
allContacts,
this.allContacts,
);
ctx.fillText(issuerText, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.6);
ctx.fillText(
issuerText,
this.CANVAS_WIDTH * 0.3,
this.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(
this.claimId,
this.CANVAS_WIDTH * 0.3,
this.CANVAS_HEIGHT * 0.7,
);
ctx.fillText(
"via EndorserSearch.com",
CANVAS_WIDTH * 0.3,
CANVAS_HEIGHT * 0.73,
this.CANVAS_WIDTH * 0.3,
this.CANVAS_HEIGHT * 0.73,
);
// Generate and draw QR code
@@ -184,7 +208,11 @@ export default class ClaimReportCertificateView extends Vue {
color: { light: "#0000" /* Transparent background */ },
},
);
ctx.drawImage(qrCodeCanvas, CANVAS_WIDTH * 0.6, CANVAS_HEIGHT * 0.55);
ctx.drawImage(
qrCodeCanvas,
this.CANVAS_WIDTH * 0.6,
this.CANVAS_HEIGHT * 0.55,
);
};
}
}