|  |  | @ -16,12 +16,13 @@ | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <!-- Display a single row with the name of "New Offers To You" with a count. --> | 
			
		
	
		
			
				
					|  |  |  |     <div class="mb-4"> | 
			
		
	
		
			
				
					|  |  |  |     <div> | 
			
		
	
		
			
				
					|  |  |  |       <span class="text-lg font-medium">{{ newOffersToUser.length }}</span> | 
			
		
	
		
			
				
					|  |  |  |       <span class="text-lg font-medium ml-4" | 
			
		
	
		
			
				
					|  |  |  |         >New Offer{{ newOffersToUser.length === 1 ? "" : "s" }} To You</span | 
			
		
	
		
			
				
					|  |  |  |       > | 
			
		
	
		
			
				
					|  |  |  |       <fa | 
			
		
	
		
			
				
					|  |  |  |         v-if="newOffersToUser.length > 0" | 
			
		
	
		
			
				
					|  |  |  |         :icon="showOffersDetails ? 'chevron-down' : 'chevron-right'" | 
			
		
	
		
			
				
					|  |  |  |         class="cursor-pointer ml-4 text-lg" | 
			
		
	
		
			
				
					|  |  |  |         @click="expandOffersToUserAndMarkRead()" | 
			
		
	
	
		
			
				
					|  |  | @ -29,11 +30,11 @@ | 
			
		
	
		
			
				
					|  |  |  |       /> | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <div v-if="showOffersDetails" class="ml-4"> | 
			
		
	
		
			
				
					|  |  |  |     <div v-if="showOffersDetails" class="ml-4 mt-4"> | 
			
		
	
		
			
				
					|  |  |  |       <ul class="list-disc ml-4"> | 
			
		
	
		
			
				
					|  |  |  |         <li | 
			
		
	
		
			
				
					|  |  |  |           v-for="offer in newOffersToUser" | 
			
		
	
		
			
				
					|  |  |  |           :key="offer.id" | 
			
		
	
		
			
				
					|  |  |  |           :key="offer.jwtId" | 
			
		
	
		
			
				
					|  |  |  |           class="mt-4 relative group" | 
			
		
	
		
			
				
					|  |  |  |         > | 
			
		
	
		
			
				
					|  |  |  |           <span>{{ | 
			
		
	
	
		
			
				
					|  |  | @ -64,6 +65,64 @@ | 
			
		
	
		
			
				
					|  |  |  |         </li> | 
			
		
	
		
			
				
					|  |  |  |       </ul> | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <!-- Display a single row with the name of "New Offers To Your Projects" with a count. --> | 
			
		
	
		
			
				
					|  |  |  |     <div class="mt-4"> | 
			
		
	
		
			
				
					|  |  |  |       <span class="text-lg font-medium">{{ | 
			
		
	
		
			
				
					|  |  |  |         newOffersToUserProjects.length | 
			
		
	
		
			
				
					|  |  |  |       }}</span> | 
			
		
	
		
			
				
					|  |  |  |       <span class="text-lg font-medium ml-4" | 
			
		
	
		
			
				
					|  |  |  |         >New Offer{{ newOffersToUserProjects.length === 1 ? "" : "s" }} To Your | 
			
		
	
		
			
				
					|  |  |  |         Projects</span | 
			
		
	
		
			
				
					|  |  |  |       > | 
			
		
	
		
			
				
					|  |  |  |       <fa | 
			
		
	
		
			
				
					|  |  |  |         v-if="newOffersToUserProjects.length > 0" | 
			
		
	
		
			
				
					|  |  |  |         :icon=" | 
			
		
	
		
			
				
					|  |  |  |           showOffersToUserProjectsDetails ? 'chevron-down' : 'chevron-right' | 
			
		
	
		
			
				
					|  |  |  |         " | 
			
		
	
		
			
				
					|  |  |  |         class="cursor-pointer ml-4 text-lg" | 
			
		
	
		
			
				
					|  |  |  |         @click="expandOffersToUserProjectsAndMarkRead()" | 
			
		
	
		
			
				
					|  |  |  |         data-testid="showOffersToUserProjects" | 
			
		
	
		
			
				
					|  |  |  |       /> | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <div v-if="showOffersToUserProjectsDetails" class="ml-4 mt-4"> | 
			
		
	
		
			
				
					|  |  |  |       <ul class="list-disc ml-4"> | 
			
		
	
		
			
				
					|  |  |  |         <li | 
			
		
	
		
			
				
					|  |  |  |           v-for="offer in newOffersToUserProjects" | 
			
		
	
		
			
				
					|  |  |  |           :key="offer.jwtId" | 
			
		
	
		
			
				
					|  |  |  |           class="mt-4 relative group" | 
			
		
	
		
			
				
					|  |  |  |         > | 
			
		
	
		
			
				
					|  |  |  |           <span>{{ | 
			
		
	
		
			
				
					|  |  |  |             didInfo(offer.offeredByDid, activeDid, allMyDids, allContacts) | 
			
		
	
		
			
				
					|  |  |  |           }}</span> | 
			
		
	
		
			
				
					|  |  |  |           offers | 
			
		
	
		
			
				
					|  |  |  |           <span v-if="offer.objectDescription">{{ | 
			
		
	
		
			
				
					|  |  |  |             offer.objectDescription | 
			
		
	
		
			
				
					|  |  |  |           }}</span | 
			
		
	
		
			
				
					|  |  |  |           >{{ offer.objectDescription && offer.amount ? ", and " : "" }} | 
			
		
	
		
			
				
					|  |  |  |           <span v-if="offer.amount">{{ | 
			
		
	
		
			
				
					|  |  |  |             displayAmount(offer.unit, offer.amount) | 
			
		
	
		
			
				
					|  |  |  |           }}</span> | 
			
		
	
		
			
				
					|  |  |  |           to | 
			
		
	
		
			
				
					|  |  |  |           <span>{{ offer.planName }}</span> | 
			
		
	
		
			
				
					|  |  |  |           <router-link | 
			
		
	
		
			
				
					|  |  |  |             :to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }" | 
			
		
	
		
			
				
					|  |  |  |             class="text-blue-500" | 
			
		
	
		
			
				
					|  |  |  |           > | 
			
		
	
		
			
				
					|  |  |  |             <fa icon="file-lines" class="pl-2 text-blue-500 cursor-pointer" /> | 
			
		
	
		
			
				
					|  |  |  |           </router-link> | 
			
		
	
		
			
				
					|  |  |  |           <!-- New line that appears on hover --> | 
			
		
	
		
			
				
					|  |  |  |           <div | 
			
		
	
		
			
				
					|  |  |  |             @click="markOffersToUserProjectsAsReadStartingWith(offer.jwtId)" | 
			
		
	
		
			
				
					|  |  |  |             class="absolute left-0 w-full text-left text-gray-500 text-sm hidden group-hover:flex cursor-pointer items-center" | 
			
		
	
		
			
				
					|  |  |  |           > | 
			
		
	
		
			
				
					|  |  |  |             <span class="inline-block w-8 h-px bg-gray-500 mr-2" /> | 
			
		
	
		
			
				
					|  |  |  |             Click to keep all above as new offers | 
			
		
	
		
			
				
					|  |  |  |           </div> | 
			
		
	
		
			
				
					|  |  |  |         </li> | 
			
		
	
		
			
				
					|  |  |  |       </ul> | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  |   </section> | 
			
		
	
		
			
				
					|  |  |  | </template> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -85,7 +144,9 @@ import { | 
			
		
	
		
			
				
					|  |  |  |   didInfo, | 
			
		
	
		
			
				
					|  |  |  |   displayAmount, | 
			
		
	
		
			
				
					|  |  |  |   getNewOffersToUser, | 
			
		
	
		
			
				
					|  |  |  |   getNewOffersToUserProjects, | 
			
		
	
		
			
				
					|  |  |  |   OfferSummaryRecord, | 
			
		
	
		
			
				
					|  |  |  |   OfferToPlanSummaryRecord, | 
			
		
	
		
			
				
					|  |  |  | } from "@/libs/endorserServer"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | @Component({ | 
			
		
	
	
		
			
				
					|  |  | @ -99,10 +160,12 @@ export default class NewActivityView extends Vue { | 
			
		
	
		
			
				
					|  |  |  |   allMyDids: string[] = []; | 
			
		
	
		
			
				
					|  |  |  |   apiServer = ""; | 
			
		
	
		
			
				
					|  |  |  |   lastAckedOfferToUserJwtId = ""; | 
			
		
	
		
			
				
					|  |  |  |   lastAckedOfferToUserProjectsJwtId = ""; | 
			
		
	
		
			
				
					|  |  |  |   newOffersToUser: Array<OfferSummaryRecord> = []; | 
			
		
	
		
			
				
					|  |  |  |   newOffersToUserProjects: Array<OfferToPlanSummaryRecord> = []; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   showOffersDetails = false; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   showOffersToUserProjectsDetails = false; | 
			
		
	
		
			
				
					|  |  |  |   didInfo = didInfo; | 
			
		
	
		
			
				
					|  |  |  |   displayAmount = displayAmount; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -112,6 +175,8 @@ export default class NewActivityView extends Vue { | 
			
		
	
		
			
				
					|  |  |  |       this.apiServer = settings.apiServer || ""; | 
			
		
	
		
			
				
					|  |  |  |       this.activeDid = settings.activeDid || ""; | 
			
		
	
		
			
				
					|  |  |  |       this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || ""; | 
			
		
	
		
			
				
					|  |  |  |       this.lastAckedOfferToUserProjectsJwtId = | 
			
		
	
		
			
				
					|  |  |  |         settings.lastAckedOfferToUserProjectsJwtId || ""; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       this.allContacts = await db.contacts.toArray(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -126,6 +191,12 @@ export default class NewActivityView extends Vue { | 
			
		
	
		
			
				
					|  |  |  |         this.activeDid, | 
			
		
	
		
			
				
					|  |  |  |         this.lastAckedOfferToUserJwtId, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |       this.newOffersToUserProjects = await getNewOffersToUserProjects( | 
			
		
	
		
			
				
					|  |  |  |         this.axios, | 
			
		
	
		
			
				
					|  |  |  |         this.apiServer, | 
			
		
	
		
			
				
					|  |  |  |         this.activeDid, | 
			
		
	
		
			
				
					|  |  |  |         this.lastAckedOfferToUserProjectsJwtId, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
			
		
	
		
			
				
					|  |  |  |     } catch (err: any) { | 
			
		
	
	
		
			
				
					|  |  | @ -144,37 +215,87 @@ export default class NewActivityView extends Vue { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async expandOffersToUserAndMarkRead() { | 
			
		
	
		
			
				
					|  |  |  |     this.showOffersDetails = !this.showOffersDetails; | 
			
		
	
		
			
				
					|  |  |  |     if (this.newOffersToUser.length > 0) { | 
			
		
	
		
			
				
					|  |  |  |     if (this.showOffersDetails) { | 
			
		
	
		
			
				
					|  |  |  |       await updateAccountSettings(this.activeDid, { | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId, | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |       // note that we don't update this.lastAckedOfferToUserJwtId in case they | 
			
		
	
		
			
				
					|  |  |  |       // later choose the last one to keep the offers as new | 
			
		
	
		
			
				
					|  |  |  |       this.$notify( | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |           group: "alert", | 
			
		
	
		
			
				
					|  |  |  |           type: "info", | 
			
		
	
		
			
				
					|  |  |  |           title: "Marked as Read", | 
			
		
	
		
			
				
					|  |  |  |           text: "The offers are marked as viewed. Click in the list to keep them as new.", | 
			
		
	
		
			
				
					|  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |         5000, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async markOffersAsReadStartingWith(jwtId: string) { | 
			
		
	
		
			
				
					|  |  |  |     const index = this.newOffersToUser.findIndex( | 
			
		
	
		
			
				
					|  |  |  |       (offer) => offer.jwtId === jwtId, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     if (index !== -1 && index < this.newOffersToUser.length - 1) { | 
			
		
	
		
			
				
					|  |  |  |       // Set to the next offer's jwtId | 
			
		
	
		
			
				
					|  |  |  |       await updateAccountSettings(this.activeDid, { | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId, | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  |       // it's the last entry (or not found), so just keep it the same | 
			
		
	
		
			
				
					|  |  |  |       await updateAccountSettings(this.activeDid, { | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId, | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |     this.$notify( | 
			
		
	
		
			
				
					|  |  |  |       { | 
			
		
	
		
			
				
					|  |  |  |         group: "alert", | 
			
		
	
		
			
				
					|  |  |  |         type: "info", | 
			
		
	
		
			
				
					|  |  |  |         title: "Marked as Read", | 
			
		
	
		
			
				
					|  |  |  |         text: "The offers are marked as viewed. Click in the list to keep them as new.", | 
			
		
	
		
			
				
					|  |  |  |         title: "Marked as Unread", | 
			
		
	
		
			
				
					|  |  |  |         text: "All offers above that one are marked as unread.", | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |       5000, | 
			
		
	
		
			
				
					|  |  |  |       3000, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async markOffersAsReadStartingWith(jwtId: string) { | 
			
		
	
		
			
				
					|  |  |  |     const index = this.newOffersToUser.findIndex( | 
			
		
	
		
			
				
					|  |  |  |   async expandOffersToUserProjectsAndMarkRead() { | 
			
		
	
		
			
				
					|  |  |  |     this.showOffersToUserProjectsDetails = | 
			
		
	
		
			
				
					|  |  |  |       !this.showOffersToUserProjectsDetails; | 
			
		
	
		
			
				
					|  |  |  |     if (this.showOffersToUserProjectsDetails) { | 
			
		
	
		
			
				
					|  |  |  |       await updateAccountSettings(this.activeDid, { | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserProjectsJwtId: | 
			
		
	
		
			
				
					|  |  |  |           this.newOffersToUserProjects[0].jwtId, | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |       // note that we don't update this.lastAckedOfferToUserProjectsJwtId in case | 
			
		
	
		
			
				
					|  |  |  |       // they later choose the last one to keep the offers as new | 
			
		
	
		
			
				
					|  |  |  |       this.$notify( | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |           group: "alert", | 
			
		
	
		
			
				
					|  |  |  |           type: "info", | 
			
		
	
		
			
				
					|  |  |  |           title: "Marked as Read", | 
			
		
	
		
			
				
					|  |  |  |           text: "The offers are marked as viewed. Click in the list to keep them as new.", | 
			
		
	
		
			
				
					|  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |         5000, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async markOffersToUserProjectsAsReadStartingWith(jwtId: string) { | 
			
		
	
		
			
				
					|  |  |  |     const index = this.newOffersToUserProjects.findIndex( | 
			
		
	
		
			
				
					|  |  |  |       (offer) => offer.jwtId === jwtId, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     if (index !== -1 && index < this.newOffersToUser.length - 1) { | 
			
		
	
		
			
				
					|  |  |  |     if (index !== -1 && index < this.newOffersToUserProjects.length - 1) { | 
			
		
	
		
			
				
					|  |  |  |       // Set to the next offer's jwtId | 
			
		
	
		
			
				
					|  |  |  |       await updateAccountSettings(this.activeDid, { | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId, | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserProjectsJwtId: | 
			
		
	
		
			
				
					|  |  |  |           this.newOffersToUserProjects[index + 1].jwtId, | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  |       // it's the last entry (or not found), so just keep it the same | 
			
		
	
		
			
				
					|  |  |  |       await updateAccountSettings(this.activeDid, { | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId, | 
			
		
	
		
			
				
					|  |  |  |         lastAckedOfferToUserProjectsJwtId: | 
			
		
	
		
			
				
					|  |  |  |           this.lastAckedOfferToUserProjectsJwtId, | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |     this.$notify( | 
			
		
	
	
		
			
				
					|  |  | 
 |