3 changed files with 748 additions and 45 deletions
			
			
		@ -0,0 +1,624 @@ | 
				
			|||||
 | 
					<template> | 
				
			||||
 | 
					  <QuickNav /> | 
				
			||||
 | 
					  <TopMessage /> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  <!-- CONTENT --> | 
				
			||||
 | 
					  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto"> | 
				
			||||
 | 
					    <!-- Back --> | 
				
			||||
 | 
					    <div | 
				
			||||
 | 
					      v-if="!hideBackButton" | 
				
			||||
 | 
					      class="text-lg text-center font-light relative px-7" | 
				
			||||
 | 
					    > | 
				
			||||
 | 
					      <h1 | 
				
			||||
 | 
					        class="text-lg text-center px-2 py-1 absolute -left-2 -top-1" | 
				
			||||
 | 
					        @click="cancelBack()" | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					        <fa icon="chevron-left" class="fa-fw"></fa> | 
				
			||||
 | 
					      </h1> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <!-- Heading --> | 
				
			||||
 | 
					    <h1 class="text-4xl text-center font-light px-4 mb-4">What Was Offered</h1> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <h1 class="text-xl font-bold text-center mb-4"> | 
				
			||||
 | 
					      <span>From {{ giverName }}</span> | 
				
			||||
 | 
					      <span> | 
				
			||||
 | 
					        to | 
				
			||||
 | 
					        {{ | 
				
			||||
 | 
					          offeredToProject | 
				
			||||
 | 
					            ? projectName | 
				
			||||
 | 
					            : offeredToRecipient | 
				
			||||
 | 
					              ? recipientName | 
				
			||||
 | 
					              : "someone unidentified" | 
				
			||||
 | 
					        }}</span | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					    </h1> | 
				
			||||
 | 
					    <textarea | 
				
			||||
 | 
					      class="block w-full rounded border border-slate-400 mb-2 px-3 py-2" | 
				
			||||
 | 
					      placeholder="What was offered" | 
				
			||||
 | 
					      v-model="description" | 
				
			||||
 | 
					    /> | 
				
			||||
 | 
					    <div class="flex flex-row justify-center"> | 
				
			||||
 | 
					      <span | 
				
			||||
 | 
					        class="rounded-l border border-r-0 border-slate-400 bg-slate-200 text-center text-blue-500 px-2 py-2 w-20" | 
				
			||||
 | 
					        @click="changeUnitCode()" | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					        {{ libsUtil.UNIT_SHORT[unitCode] || unitCode }} | 
				
			||||
 | 
					      </span> | 
				
			||||
 | 
					      <div | 
				
			||||
 | 
					        class="border border-r-0 border-slate-400 bg-slate-200 px-4 py-2" | 
				
			||||
 | 
					        @click="amountInput === '0' ? null : decrement()" | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					        <fa icon="chevron-left" /> | 
				
			||||
 | 
					      </div> | 
				
			||||
 | 
					      <input | 
				
			||||
 | 
					        type="number" | 
				
			||||
 | 
					        class="border border-r-0 border-slate-400 px-2 py-2 text-center w-20" | 
				
			||||
 | 
					        v-model="amountInput" | 
				
			||||
 | 
					      /> | 
				
			||||
 | 
					      <div | 
				
			||||
 | 
					        class="rounded-r border border-slate-400 bg-slate-200 px-4 py-2" | 
				
			||||
 | 
					        @click="increment()" | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					        <fa icon="chevron-right" /> | 
				
			||||
 | 
					      </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <div class="h-7 mt-4 flex"> | 
				
			||||
 | 
					      <input | 
				
			||||
 | 
					        v-if="projectId && !offeredToRecipient" | 
				
			||||
 | 
					        type="checkbox" | 
				
			||||
 | 
					        class="h-6 w-6 mr-2" | 
				
			||||
 | 
					        v-model="offeredToProject" | 
				
			||||
 | 
					      /> | 
				
			||||
 | 
					      <fa | 
				
			||||
 | 
					        v-else | 
				
			||||
 | 
					        icon="square" | 
				
			||||
 | 
					        class="bg-slate-500 text-slate-500 h-5 w-5 px-0.5 py-0.5 mr-2 rounded" | 
				
			||||
 | 
					        @click="notifyUserOfProject()" | 
				
			||||
 | 
					      /> | 
				
			||||
 | 
					      <label class="text-sm mt-1"> | 
				
			||||
 | 
					        {{ | 
				
			||||
 | 
					          projectId | 
				
			||||
 | 
					            ? "This was given to " + projectName | 
				
			||||
 | 
					            : "No project was chosen" | 
				
			||||
 | 
					        }} | 
				
			||||
 | 
					      </label> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <div class="h-7 mt-4 flex"> | 
				
			||||
 | 
					      <input | 
				
			||||
 | 
					        v-if="recipientDid && !offeredToProject" | 
				
			||||
 | 
					        type="checkbox" | 
				
			||||
 | 
					        class="h-6 w-6 mr-2" | 
				
			||||
 | 
					        v-model="offeredToRecipient" | 
				
			||||
 | 
					      /> | 
				
			||||
 | 
					      <fa | 
				
			||||
 | 
					        v-else | 
				
			||||
 | 
					        icon="square" | 
				
			||||
 | 
					        class="bg-slate-500 text-slate-500 h-5 w-5 px-0.5 py-0.5 mr-2 rounded" | 
				
			||||
 | 
					        @click="notifyUserOfRecipient()" | 
				
			||||
 | 
					      /> | 
				
			||||
 | 
					      <label class="text-sm mt-1"> | 
				
			||||
 | 
					        {{ | 
				
			||||
 | 
					          recipientDid | 
				
			||||
 | 
					            ? "This was given to " + recipientName | 
				
			||||
 | 
					            : "No recipient was chosen." | 
				
			||||
 | 
					        }} | 
				
			||||
 | 
					      </label> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <div class="mt-4 flex"> | 
				
			||||
 | 
					      <router-link | 
				
			||||
 | 
					        :to="{ | 
				
			||||
 | 
					          name: 'claim-add-raw', | 
				
			||||
 | 
					          query: { | 
				
			||||
 | 
					            claim: constructOfferParam(), | 
				
			||||
 | 
					          }, | 
				
			||||
 | 
					        }" | 
				
			||||
 | 
					        class="text-blue-500" | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					        Edit & Submit Raw | 
				
			||||
 | 
					      </router-link> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <p class="text-center mb-2 mt-6 italic"> | 
				
			||||
 | 
					      Sign & Send to publish to the world | 
				
			||||
 | 
					      <fa | 
				
			||||
 | 
					        icon="circle-info" | 
				
			||||
 | 
					        class="pl-2 text-blue-500 cursor-pointer" | 
				
			||||
 | 
					        @click="explainData()" | 
				
			||||
 | 
					      /> | 
				
			||||
 | 
					    </p> | 
				
			||||
 | 
					    <div class="grid grid-cols-1 sm:grid-cols-2 gap-2"> | 
				
			||||
 | 
					      <button | 
				
			||||
 | 
					        class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md" | 
				
			||||
 | 
					        @click="cancel" | 
				
			||||
 | 
					      > | 
				
			||||
 | 
					        Cancel | 
				
			||||
 | 
					      </button> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					  </section> | 
				
			||||
 | 
					</template> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					<script lang="ts"> | 
				
			||||
 | 
					import { Component, Vue } from "vue-facing-decorator"; | 
				
			||||
 | 
					import { Router } from "vue-router"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					import QuickNav from "@/components/QuickNav.vue"; | 
				
			||||
 | 
					import TopMessage from "@/components/TopMessage.vue"; | 
				
			||||
 | 
					import { NotificationIface } from "@/constants/app"; | 
				
			||||
 | 
					import { accountsDB, db } from "@/db/index"; | 
				
			||||
 | 
					import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings"; | 
				
			||||
 | 
					import { | 
				
			||||
 | 
					  createAndSubmitOffer, | 
				
			||||
 | 
					  didInfo, | 
				
			||||
 | 
					  editAndSubmitOffer, | 
				
			||||
 | 
					  GenericCredWrapper, | 
				
			||||
 | 
					  getPlanFromCache, | 
				
			||||
 | 
					  hydrateOffer, | 
				
			||||
 | 
					  OfferVerifiableCredential, | 
				
			||||
 | 
					} from "@/libs/endorserServer"; | 
				
			||||
 | 
					import * as libsUtil from "@/libs/util"; | 
				
			||||
 | 
					import { Contact } from "@/db/tables/contacts"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					@Component({ | 
				
			||||
 | 
					  components: { | 
				
			||||
 | 
					    QuickNav, | 
				
			||||
 | 
					    TopMessage, | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					}) | 
				
			||||
 | 
					export default class OfferDetails extends Vue { | 
				
			||||
 | 
					  $notify!: (notification: NotificationIface, timeout?: number) => void; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  activeDid = ""; | 
				
			||||
 | 
					  apiServer = ""; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  amountInput = "0"; | 
				
			||||
 | 
					  description = ""; | 
				
			||||
 | 
					  destinationPathAfter = ""; | 
				
			||||
 | 
					  offeredToProject = false; | 
				
			||||
 | 
					  offeredToRecipient = false; | 
				
			||||
 | 
					  giverDid: string | undefined; | 
				
			||||
 | 
					  giverName = ""; | 
				
			||||
 | 
					  hideBackButton = false; | 
				
			||||
 | 
					  isTrade = false; | 
				
			||||
 | 
					  message = ""; | 
				
			||||
 | 
					  offerId = ""; | 
				
			||||
 | 
					  prevCredToEdit?: GenericCredWrapper<OfferVerifiableCredential>; | 
				
			||||
 | 
					  projectId = ""; | 
				
			||||
 | 
					  projectName = "a project"; | 
				
			||||
 | 
					  recipientDid = ""; | 
				
			||||
 | 
					  recipientName = ""; | 
				
			||||
 | 
					  unitCode = "HUR"; | 
				
			||||
 | 
					  validThroughDate = null; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  libsUtil = libsUtil; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  async mounted() { | 
				
			||||
 | 
					    try { | 
				
			||||
 | 
					      this.prevCredToEdit = (this.$route as Router).query["prevCredToEdit"] | 
				
			||||
 | 
					        ? (JSON.parse( | 
				
			||||
 | 
					            (this.$route as Router).query["prevCredToEdit"], | 
				
			||||
 | 
					          ) as GenericCredWrapper<OfferVerifiableCredential>) | 
				
			||||
 | 
					        : undefined; | 
				
			||||
 | 
					    } catch (error) { | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "danger", | 
				
			||||
 | 
					          title: "Retrieval Error", | 
				
			||||
 | 
					          text: "The previous record isn't available for editing. If you submit, you'll create a new record.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        6000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    const prevAmount = this.prevCredToEdit?.claim?.object?.amountOfThisGood; | 
				
			||||
 | 
					    this.amountInput = | 
				
			||||
 | 
					      (this.$route as Router).query["amountInput"] || | 
				
			||||
 | 
					      (prevAmount ? String(prevAmount) : "") || | 
				
			||||
 | 
					      this.amountInput; | 
				
			||||
 | 
					    this.description = | 
				
			||||
 | 
					      (this.$route as Router).query["description"] || | 
				
			||||
 | 
					      this.prevCredToEdit?.claim?.description || | 
				
			||||
 | 
					      this.description; | 
				
			||||
 | 
					    this.destinationPathAfter = (this.$route as Router).query[ | 
				
			||||
 | 
					      "destinationPathAfter" | 
				
			||||
 | 
					    ]; | 
				
			||||
 | 
					    this.giverDid = ((this.$route as Router).query["giverDid"] || | 
				
			||||
 | 
					      this.prevCredToEdit?.claim?.agent?.identifier || | 
				
			||||
 | 
					      this.giverDid) as string; | 
				
			||||
 | 
					    this.giverName = | 
				
			||||
 | 
					      ((this.$route as Router).query["giverName"] as string) || ""; | 
				
			||||
 | 
					    this.hideBackButton = | 
				
			||||
 | 
					      (this.$route as Router).query["hideBackButton"] === "true"; | 
				
			||||
 | 
					    this.message = ((this.$route as Router).query["message"] as string) || ""; | 
				
			||||
 | 
					    // find any offer ID | 
				
			||||
 | 
					    const fulfills = this.prevCredToEdit?.claim?.fulfills; | 
				
			||||
 | 
					    const fulfillsArray = Array.isArray(fulfills) | 
				
			||||
 | 
					      ? fulfills | 
				
			||||
 | 
					      : fulfills | 
				
			||||
 | 
					        ? [fulfills] | 
				
			||||
 | 
					        : []; | 
				
			||||
 | 
					    const offer = fulfillsArray.find((rec) => rec["@type"] === "Offer"); | 
				
			||||
 | 
					    this.offerId = ((this.$route as Router).query["offerId"] || | 
				
			||||
 | 
					      offer?.identifier || | 
				
			||||
 | 
					      this.offerId) as string; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // find any project ID | 
				
			||||
 | 
					    const project = fulfillsArray.find((rec) => rec["@type"] === "PlanAction"); | 
				
			||||
 | 
					    this.projectId = ((this.$route as Router).query["projectId"] || | 
				
			||||
 | 
					      project?.identifier || | 
				
			||||
 | 
					      this.projectId) as string; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    this.recipientDid = ((this.$route as Router).query["recipientDid"] || | 
				
			||||
 | 
					      this.prevCredToEdit?.claim?.recipient?.identifier) as string; | 
				
			||||
 | 
					    this.recipientName = | 
				
			||||
 | 
					      ((this.$route as Router).query["recipientName"] as string) || ""; | 
				
			||||
 | 
					    this.unitCode = ((this.$route as Router).query["unitCode"] || | 
				
			||||
 | 
					      this.prevCredToEdit?.claim?.object?.unitCode || | 
				
			||||
 | 
					      this.unitCode) as string; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // this is an endpoint for sharing project info to highlight something given | 
				
			||||
 | 
					    // https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target | 
				
			||||
 | 
					    if ((this.$route as Router).query["shareTitle"]) { | 
				
			||||
 | 
					      this.description = | 
				
			||||
 | 
					        ((this.$route as Router).query["shareTitle"] as string) + | 
				
			||||
 | 
					        (this.description ? "\n" + this.description : ""); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    if ((this.$route as Router).query["shareText"]) { | 
				
			||||
 | 
					      this.description = | 
				
			||||
 | 
					        (this.description ? this.description + "\n" : "") + | 
				
			||||
 | 
					        ((this.$route as Router).query["shareText"] as string); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    if ((this.$route as Router).query["shareUrl"]) { | 
				
			||||
 | 
					      this.imageUrl = (this.$route as Router).query["shareUrl"] as string; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    try { | 
				
			||||
 | 
					      await db.open(); | 
				
			||||
 | 
					      const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings; | 
				
			||||
 | 
					      this.apiServer = settings?.apiServer || ""; | 
				
			||||
 | 
					      this.activeDid = settings?.activeDid || ""; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      let allContacts: Contact[] = []; | 
				
			||||
 | 
					      let allMyDids: string[] = []; | 
				
			||||
 | 
					      if ( | 
				
			||||
 | 
					        (this.giverDid && !this.giverName) || | 
				
			||||
 | 
					        (this.recipientDid && !this.recipientName) | 
				
			||||
 | 
					      ) { | 
				
			||||
 | 
					        allContacts = await db.contacts.toArray(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        await accountsDB.open(); | 
				
			||||
 | 
					        const allAccounts = await accountsDB.accounts.toArray(); | 
				
			||||
 | 
					        allMyDids = allAccounts.map((acc) => acc.did); | 
				
			||||
 | 
					        if (this.giverDid && !this.giverName) { | 
				
			||||
 | 
					          this.giverName = didInfo( | 
				
			||||
 | 
					            this.giverDid, | 
				
			||||
 | 
					            this.activeDid, | 
				
			||||
 | 
					            allMyDids, | 
				
			||||
 | 
					            allContacts, | 
				
			||||
 | 
					          ); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        if (this.recipientDid && !this.recipientName) { | 
				
			||||
 | 
					          this.recipientName = didInfo( | 
				
			||||
 | 
					            this.recipientDid, | 
				
			||||
 | 
					            this.activeDid, | 
				
			||||
 | 
					            allMyDids, | 
				
			||||
 | 
					            allContacts, | 
				
			||||
 | 
					          ); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					      this.offeredToProject = !!this.projectId; | 
				
			||||
 | 
					      this.offeredToRecipient = !this.offeredToProject && !!this.recipientDid; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
				
			||||
 | 
					    } catch (err: any) { | 
				
			||||
 | 
					      console.error("Error retrieving settings from database:", err); | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "danger", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: err.message || "There was an error retrieving your settings.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        -1, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    if (this.projectId) { | 
				
			||||
 | 
					      // console.log("Getting project name from cache", this.projectId); | 
				
			||||
 | 
					      const project = await getPlanFromCache( | 
				
			||||
 | 
					        this.projectId, | 
				
			||||
 | 
					        this.axios, | 
				
			||||
 | 
					        this.apiServer, | 
				
			||||
 | 
					        this.activeDid, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					      this.projectName = project?.name | 
				
			||||
 | 
					        ? "the project: " + project.name | 
				
			||||
 | 
					        : "a project"; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  changeUnitCode() { | 
				
			||||
 | 
					    const units = Object.keys(this.libsUtil.UNIT_SHORT); | 
				
			||||
 | 
					    const index = units.indexOf(this.unitCode); | 
				
			||||
 | 
					    this.unitCode = units[(index + 1) % units.length]; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  increment() { | 
				
			||||
 | 
					    this.amountInput = `${(parseFloat(this.amountInput) || 0) + 1}`; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  decrement() { | 
				
			||||
 | 
					    this.amountInput = `${Math.max( | 
				
			||||
 | 
					      0, | 
				
			||||
 | 
					      (parseFloat(this.amountInput) || 1) - 1, | 
				
			||||
 | 
					    )}`; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  cancel() { | 
				
			||||
 | 
					    if (this.destinationPathAfter) { | 
				
			||||
 | 
					      (this.$router as Router).push({ path: this.destinationPathAfter }); | 
				
			||||
 | 
					    } else { | 
				
			||||
 | 
					      (this.$router as Router).back(); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  cancelBack() { | 
				
			||||
 | 
					    (this.$router as Router).back(); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  async confirm() { | 
				
			||||
 | 
					    if (!this.activeDid) { | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "danger", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: "You must select an identifier before you can record a offer.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        2000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					      return; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    if (parseFloat(this.amountInput) < 0) { | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "danger", | 
				
			||||
 | 
					          text: "You may not send a negative number.", | 
				
			||||
 | 
					          title: "", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        2000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					      return; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    if (!this.description && !parseFloat(this.amountInput)) { | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "danger", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: `You must enter a description or some number of ${ | 
				
			||||
 | 
					            this.libsUtil.UNIT_LONG[this.unitCode] | 
				
			||||
 | 
					          }.`, | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        2000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					      return; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    this.$notify( | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        group: "alert", | 
				
			||||
 | 
					        type: "toast", | 
				
			||||
 | 
					        text: "Recording the give...", | 
				
			||||
 | 
					        title: "", | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					      1000, | 
				
			||||
 | 
					    ); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // this is asynchronous, but we don't need to wait for it to complete | 
				
			||||
 | 
					    await this.recordOffer(); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  notifyUserOfProject() { | 
				
			||||
 | 
					    if (!this.projectId) { | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "warning", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: "To assign to a project, you must open this dialog through a project.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        3000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } else { | 
				
			||||
 | 
					      // must be because offeredToRecipient is true | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "warning", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: "You cannot assign both to a project and to a recipient.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        3000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  notifyUserOfRecipient() { | 
				
			||||
 | 
					    if (!this.recipientDid) { | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "warning", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: "To assign to a recipient, you must open this dialog from a contact.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        3000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } else { | 
				
			||||
 | 
					      // must be because offeredToProject is true | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "warning", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: "You cannot assign both to a recipient and to a project.", | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        3000, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * | 
				
			||||
 | 
					   * @param giverDid may be null | 
				
			||||
 | 
					   * @param description may be an empty string | 
				
			||||
 | 
					   * @param amountInput may be 0 | 
				
			||||
 | 
					   * @param unitCode may be omitted, defaults to "HUR" | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  public async recordOffer() { | 
				
			||||
 | 
					    try { | 
				
			||||
 | 
					      const recipientDid = this.offeredToRecipient | 
				
			||||
 | 
					        ? this.recipientDid | 
				
			||||
 | 
					        : undefined; | 
				
			||||
 | 
					      const projectId = this.offeredToProject ? this.projectId : undefined; | 
				
			||||
 | 
					      let result; | 
				
			||||
 | 
					      if (this.prevCredToEdit) { | 
				
			||||
 | 
					        // don't create from a blank one in case some properties were set from a different interface | 
				
			||||
 | 
					        result = await editAndSubmitOffer( | 
				
			||||
 | 
					          this.axios, | 
				
			||||
 | 
					          this.apiServer, | 
				
			||||
 | 
					          this.prevCredToEdit, | 
				
			||||
 | 
					          this.activeDid, | 
				
			||||
 | 
					          this.description, | 
				
			||||
 | 
					          parseFloat(this.amountInput), | 
				
			||||
 | 
					          this.unitCode, | 
				
			||||
 | 
					          this.validThroughDate, | 
				
			||||
 | 
					          recipientDid, | 
				
			||||
 | 
					          projectId, | 
				
			||||
 | 
					        ); | 
				
			||||
 | 
					      } else { | 
				
			||||
 | 
					        result = await createAndSubmitOffer( | 
				
			||||
 | 
					          this.axios, | 
				
			||||
 | 
					          this.apiServer, | 
				
			||||
 | 
					          this.activeDid, | 
				
			||||
 | 
					          this.description, | 
				
			||||
 | 
					          parseFloat(this.amountInput), | 
				
			||||
 | 
					          this.unitCode, | 
				
			||||
 | 
					          this.validThroughDate, | 
				
			||||
 | 
					          recipientDid, | 
				
			||||
 | 
					          projectId, | 
				
			||||
 | 
					        ); | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      if (result.type === "error" || this.isCreationError(result.response)) { | 
				
			||||
 | 
					        const errorMessage = this.getCreationErrorMessage(result); | 
				
			||||
 | 
					        console.error("Error with give creation result:", result); | 
				
			||||
 | 
					        this.$notify( | 
				
			||||
 | 
					          { | 
				
			||||
 | 
					            group: "alert", | 
				
			||||
 | 
					            type: "danger", | 
				
			||||
 | 
					            title: "Error", | 
				
			||||
 | 
					            text: errorMessage || "There was an error creating the give.", | 
				
			||||
 | 
					          }, | 
				
			||||
 | 
					          -1, | 
				
			||||
 | 
					        ); | 
				
			||||
 | 
					      } else { | 
				
			||||
 | 
					        this.$notify( | 
				
			||||
 | 
					          { | 
				
			||||
 | 
					            group: "alert", | 
				
			||||
 | 
					            type: "success", | 
				
			||||
 | 
					            title: "Success", | 
				
			||||
 | 
					            text: `That ${this.isTrade ? "trade" : "gift"} was recorded.`, | 
				
			||||
 | 
					          }, | 
				
			||||
 | 
					          5000, | 
				
			||||
 | 
					        ); | 
				
			||||
 | 
					        localStorage.removeItem("imageUrl"); | 
				
			||||
 | 
					        if (this.destinationPathAfter) { | 
				
			||||
 | 
					          (this.$router as Router).push({ path: this.destinationPathAfter }); | 
				
			||||
 | 
					        } else { | 
				
			||||
 | 
					          (this.$router as Router).back(); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					      // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
				
			||||
 | 
					    } catch (error: any) { | 
				
			||||
 | 
					      console.error("Error with give recordation caught:", error); | 
				
			||||
 | 
					      const errorMessage = | 
				
			||||
 | 
					        error.userMessage || | 
				
			||||
 | 
					        error.response?.data?.error?.message || | 
				
			||||
 | 
					        "There was an error recording the give."; | 
				
			||||
 | 
					      this.$notify( | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          group: "alert", | 
				
			||||
 | 
					          type: "danger", | 
				
			||||
 | 
					          title: "Error", | 
				
			||||
 | 
					          text: errorMessage, | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        -1, | 
				
			||||
 | 
					      ); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  constructOfferParam() { | 
				
			||||
 | 
					    const recipientDid = this.offeredToRecipient | 
				
			||||
 | 
					      ? this.recipientDid | 
				
			||||
 | 
					      : undefined; | 
				
			||||
 | 
					    const projectId = this.offeredToProject ? this.projectId : undefined; | 
				
			||||
 | 
					    const giveClaim = hydrateOffer( | 
				
			||||
 | 
					      this.prevCredToEdit?.claim as OfferVerifiableCredential, | 
				
			||||
 | 
					      this.activeDid, | 
				
			||||
 | 
					      recipientDid, | 
				
			||||
 | 
					      this.description, | 
				
			||||
 | 
					      parseFloat(this.amountInput), | 
				
			||||
 | 
					      this.unitCode, | 
				
			||||
 | 
					      "", | 
				
			||||
 | 
					      projectId, | 
				
			||||
 | 
					      this.validThroughDate, | 
				
			||||
 | 
					      this.prevCredToEdit?.id as string, | 
				
			||||
 | 
					    ); | 
				
			||||
 | 
					    const claimStr = JSON.stringify(giveClaim); | 
				
			||||
 | 
					    return claimStr; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  // Helper functions for readability | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * @param result response "data" from the server | 
				
			||||
 | 
					   * @returns true if the result indicates an error | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
				
			||||
 | 
					  isCreationError(result: any) { | 
				
			||||
 | 
					    return result.status !== 201 || result.data?.error; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * @param result direct response eg. ErrorResult or SuccessResult (potentially with embedded "data") | 
				
			||||
 | 
					   * @returns best guess at an error message | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
				
			||||
 | 
					  getCreationErrorMessage(result: any) { | 
				
			||||
 | 
					    return ( | 
				
			||||
 | 
					      result.error?.userMessage || | 
				
			||||
 | 
					      result.error?.error || | 
				
			||||
 | 
					      result.response?.data?.error?.message | 
				
			||||
 | 
					    ); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  explainData() { | 
				
			||||
 | 
					    this.$notify( | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        group: "alert", | 
				
			||||
 | 
					        type: "success", | 
				
			||||
 | 
					        title: "Data Sharing", | 
				
			||||
 | 
					        text: libsUtil.PRIVACY_MESSAGE, | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					      -1, | 
				
			||||
 | 
					    ); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					</script> | 
				
			||||
					Loading…
					
					
				
		Reference in new issue