From a1388539c1518214226adf9b22924b6d941a7d59 Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Thu, 14 Aug 2025 18:53:12 +0800 Subject: [PATCH 1/4] Fix: improve offer fulfillment detection in ClaimView - Remove outdated fulfillsType logic that was checking for non-PlanAction items - Keep only the new offer fulfillment extraction from fullClaim.fulfills array - Apply consistent changes to both ClaimView and ConfirmGiftView This ensures that "Fulfills Offer..." links appear correctly when gives are created from offers, by directly parsing the fulfills array instead of relying on API-processed fields that only capture the first relationship. --- src/views/ClaimView.vue | 57 +++++++++++++++++++++++++++-------- src/views/ConfirmGiftView.vue | 48 +++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue index f594dc9b..76b283f9 100644 --- a/src/views/ClaimView.vue +++ b/src/views/ClaimView.vue @@ -119,25 +119,17 @@ Fulfills a bigger plan... - -
+ +
Fulfills {{ capitalizeAndInsertSpacesBeforeCaps( - detailsForGive.fulfillsType, + offerFulfillment.offerType || "Offer", ) }}... @@ -556,6 +548,17 @@ export default class ClaimView extends Vue { fulfillsPlanHandleId?: string; fulfillsType?: string; fulfillsHandleId?: string; + fullClaim?: { + fulfills?: Array<{ + "@type": string; + identifier?: string; + }>; + }; + } | null = null; + // Additional offer information extracted from the fulfills array + offerFulfillment: { + offerHandleId?: string; + offerType?: string; } | null = null; detailsForOffer: { fulfillsPlanHandleId?: string } | null = null; // Project information for fulfillsPlanHandleId @@ -689,6 +692,7 @@ export default class ClaimView extends Vue { this.confsVisibleToIdList = []; this.detailsForGive = null; this.detailsForOffer = null; + this.offerFulfillment = null; this.projectInfo = null; this.fullClaim = null; this.fullClaimDump = ""; @@ -701,6 +705,33 @@ export default class ClaimView extends Vue { this.veriClaimDidsVisible = {}; } + /** + * Extract offer fulfillment information from the fulfills array + */ + extractOfferFulfillment() { + if (!this.detailsForGive?.fullClaim?.fulfills) { + this.offerFulfillment = null; + return; + } + + const fulfills = this.detailsForGive.fullClaim.fulfills; + if (!Array.isArray(fulfills)) { + this.offerFulfillment = null; + return; + } + + // Find the Offer in the fulfills array + const offerFulfill = fulfills.find((item) => item["@type"] === "Offer"); + if (offerFulfill) { + this.offerFulfillment = { + offerHandleId: offerFulfill.identifier, + offerType: offerFulfill["@type"], + }; + } else { + this.offerFulfillment = null; + } + } + // ================================================= // UTILITY METHODS // ================================================= @@ -821,6 +852,8 @@ export default class ClaimView extends Vue { }); if (giveResp.status === 200 && giveResp.data.data?.length > 0) { this.detailsForGive = giveResp.data.data[0]; + // Extract offer information from the fulfills array + this.extractOfferFulfillment(); } else { await this.$logError( "Error getting detailed give info: " + JSON.stringify(giveResp), diff --git a/src/views/ConfirmGiftView.vue b/src/views/ConfirmGiftView.vue index c2274dab..cf3f3a0c 100644 --- a/src/views/ConfirmGiftView.vue +++ b/src/views/ConfirmGiftView.vue @@ -113,26 +113,20 @@ />
- -
+ +
This fulfills {{ capitalizeAndInsertSpacesBeforeCapsWithAPrefix( - giveDetails?.fulfillsType || "", + offerFulfillment.offerType || "Offer", ) }} item["@type"] === "Offer"); + if (offerFulfill) { + this.offerFulfillment = { + offerHandleId: offerFulfill.identifier, + offerType: offerFulfill["@type"], + }; + } else { + this.offerFulfillment = null; + } + } + /** * Fetches confirmer information for the claim */ -- 2.30.2 From 693173f09dbd34ae5770e097546329ca51bbeeed Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Thu, 14 Aug 2025 20:12:28 +0800 Subject: [PATCH 2/4] UI: wording and spacing consistencies - Added grouped conditional spacing to ensure a top margin before fulfills links - Brought over icons and wording from ConfirmGiftView to ClaimView --- src/views/ClaimView.vue | 157 +++++++++++++++++++++------------- src/views/ConfirmGiftView.vue | 78 +++++++++-------- 2 files changed, 138 insertions(+), 97 deletions(-) diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue index 76b283f9..29895e67 100644 --- a/src/views/ClaimView.vue +++ b/src/views/ClaimView.vue @@ -106,69 +106,87 @@
+
+ +
+ + This fulfills a bigger plan + + +
- -
- - Fulfills a bigger plan... - -
- -
- - - Fulfills - {{ - capitalizeAndInsertSpacesBeforeCaps( - offerFulfillment.offerType || "Offer", - ) - }}... - -
- - -
- - Offered to a bigger plan... - -
+ +
+ + + This fulfills + {{ + capitalizeAndInsertSpacesBeforeCapsWithAPrefix( + offerFulfillment.offerType || "Offer", + ) + }} + + +
- -
- Other assistance provided by: - + + +
@@ -789,6 +807,27 @@ export default class ClaimView extends Vue { this.canShare = !!navigator.share; } + /** + * Formats type string for display by adding spaces before capitals + * Optionally adds a prefix + * + * @param text - Text to format + * @param prefix - Optional prefix to add + * @returns Formatted string + */ + capitalizeAndInsertSpacesBeforeCapsWithAPrefix(text: string): string { + const word = this.capitalizeAndInsertSpacesBeforeCaps(text); + if (word) { + // if the word starts with a vowel, use "an" instead of "a" + const firstLetter = word[0].toLowerCase(); + const vowels = ["a", "e", "i", "o", "u"]; + const particle = vowels.includes(firstLetter) ? "an" : "a"; + return particle + " " + word; + } else { + return ""; + } + } + // insert a space before any capital letters except the initial letter // (and capitalize initial letter, just in case) capitalizeAndInsertSpacesBeforeCaps(text: string): string { diff --git a/src/views/ConfirmGiftView.vue b/src/views/ConfirmGiftView.vue index cf3f3a0c..244631bc 100644 --- a/src/views/ConfirmGiftView.vue +++ b/src/views/ConfirmGiftView.vue @@ -96,44 +96,46 @@ - - -
- - This fulfills a bigger plan - - -
- -
- - - This fulfills - {{ - capitalizeAndInsertSpacesBeforeCapsWithAPrefix( - offerFulfillment.offerType || "Offer", - ) - }} - - +
+ +
+ + This fulfills a bigger plan + + +
+ + +
+ + + This fulfills + {{ + capitalizeAndInsertSpacesBeforeCapsWithAPrefix( + offerFulfillment.offerType || "Offer", + ) + }} + + +
-- 2.30.2 From 19f0c270d3966d5ae5a275af4ad77a3285aa1249 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 17 Aug 2025 14:13:50 -0600 Subject: [PATCH 3/4] chore: Rename variable for clarity --- src/views/ClaimView.vue | 26 +++++++++++++++----------- src/views/ConfirmGiftView.vue | 24 ++++++++++++++---------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue index 29895e67..55ca6744 100644 --- a/src/views/ClaimView.vue +++ b/src/views/ClaimView.vue @@ -125,16 +125,20 @@ -
+
This fulfills {{ capitalizeAndInsertSpacesBeforeCapsWithAPrefix( - offerFulfillment.offerType || "Offer", + detailsForGiveOfferFulfillment.offerType || "Offer", ) }}
- +
@@ -574,7 +578,7 @@ export default class ClaimView extends Vue { }; } | null = null; // Additional offer information extracted from the fulfills array - offerFulfillment: { + detailsForGiveOfferFulfillment: { offerHandleId?: string; offerType?: string; } | null = null; @@ -710,7 +714,7 @@ export default class ClaimView extends Vue { this.confsVisibleToIdList = []; this.detailsForGive = null; this.detailsForOffer = null; - this.offerFulfillment = null; + this.detailsForGiveOfferFulfillment = null; this.projectInfo = null; this.fullClaim = null; this.fullClaimDump = ""; @@ -728,25 +732,25 @@ export default class ClaimView extends Vue { */ extractOfferFulfillment() { if (!this.detailsForGive?.fullClaim?.fulfills) { - this.offerFulfillment = null; + this.detailsForGiveOfferFulfillment = null; return; } const fulfills = this.detailsForGive.fullClaim.fulfills; if (!Array.isArray(fulfills)) { - this.offerFulfillment = null; + this.detailsForGiveOfferFulfillment = null; return; } // Find the Offer in the fulfills array const offerFulfill = fulfills.find((item) => item["@type"] === "Offer"); if (offerFulfill) { - this.offerFulfillment = { + this.detailsForGiveOfferFulfillment = { offerHandleId: offerFulfill.identifier, offerType: offerFulfill["@type"], }; } else { - this.offerFulfillment = null; + this.detailsForGiveOfferFulfillment = null; } } @@ -815,7 +819,7 @@ export default class ClaimView extends Vue { * @param prefix - Optional prefix to add * @returns Formatted string */ - capitalizeAndInsertSpacesBeforeCapsWithAPrefix(text: string): string { + capitalizeAndInsertSpacesBeforeCapsWithAPrefix(text: string): string { const word = this.capitalizeAndInsertSpacesBeforeCaps(text); if (word) { // if the word starts with a vowel, use "an" instead of "a" diff --git a/src/views/ConfirmGiftView.vue b/src/views/ConfirmGiftView.vue index 244631bc..44d769d2 100644 --- a/src/views/ConfirmGiftView.vue +++ b/src/views/ConfirmGiftView.vue @@ -102,7 +102,9 @@ @@ -113,21 +115,23 @@ /> - + -
+
This fulfills {{ capitalizeAndInsertSpacesBeforeCapsWithAPrefix( - offerFulfillment.offerType || "Offer", + giveDetailsOfferFulfillment.offerType || "Offer", ) }} item["@type"] === "Offer"); if (offerFulfill) { - this.offerFulfillment = { + this.giveDetailsOfferFulfillment = { offerHandleId: offerFulfill.identifier, offerType: offerFulfill["@type"], }; } else { - this.offerFulfillment = null; + this.giveDetailsOfferFulfillment = null; } } -- 2.30.2 From e5ad71505c310bd55919ec37bb11b7030e46a82c Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Mon, 18 Aug 2025 17:47:33 +0800 Subject: [PATCH 4/4] Chore: move function to serverUtil - capitalizeAndInsertSpacesBeforeCapsWithAPrefix() defined in two places, unified and moved to endorserServer.ts - Use capitalizeAndInsertSpacesBeforeCaps() that's already defined in endorserServer.ts --- src/libs/endorserServer.ts | 22 ++++++++++++++++++++++ src/views/ClaimView.vue | 34 ++++------------------------------ src/views/ConfirmGiftView.vue | 29 +---------------------------- 3 files changed, 27 insertions(+), 58 deletions(-) diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index 735252f7..cdc516b1 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -1140,6 +1140,28 @@ export const capitalizeAndInsertSpacesBeforeCaps = (text: string) => { : text[0].toUpperCase() + text.substr(1).replace(/([A-Z])/g, " $1"); }; +/** + * Formats type string for display by adding spaces before capitals + * and optionally adds an appropriate article prefix (a/an) + * + * @param text - Text to format + * @returns Formatted string with article prefix + */ +export const capitalizeAndInsertSpacesBeforeCapsWithAPrefix = ( + text: string, +): string => { + const word = capitalizeAndInsertSpacesBeforeCaps(text); + if (word) { + // if the word starts with a vowel, use "an" instead of "a" + const firstLetter = word[0].toLowerCase(); + const vowels = ["a", "e", "i", "o", "u"]; + const particle = vowels.includes(firstLetter) ? "an" : "a"; + return particle + " " + word; + } else { + return ""; + } +}; + /** return readable summary of claim, or something generic diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue index 55ca6744..3653861d 100644 --- a/src/views/ClaimView.vue +++ b/src/views/ClaimView.vue @@ -24,7 +24,9 @@

{{ - capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType || "") + serverUtil.capitalizeAndInsertSpacesBeforeCaps( + veriClaim.claimType || "", + ) }}