Browse Source
			
			
			
			
				
		Reviewed-on: https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/pulls/103pull/104/head
				 22 changed files with 1051 additions and 127 deletions
			
			
		@ -0,0 +1,220 @@ | 
				
			|||
<template> | 
				
			|||
  <QuickNav /> | 
				
			|||
  <TopMessage /> | 
				
			|||
 | 
				
			|||
  <!-- CONTENT --> | 
				
			|||
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto"> | 
				
			|||
    <!-- Back --> | 
				
			|||
    <div 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="$router.back()" | 
				
			|||
      > | 
				
			|||
        <fa icon="chevron-left" class="fa-fw"></fa> | 
				
			|||
      </h1> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <!-- Heading --> | 
				
			|||
    <h1 id="ViewHeading" class="text-4xl text-center font-light px-4 mb-4"> | 
				
			|||
      Beginning of BVC Saturday Meeting | 
				
			|||
    </h1> | 
				
			|||
 | 
				
			|||
    <div> | 
				
			|||
      <h2 class="text-2xl m-2">You're Here</h2> | 
				
			|||
      <div class="m-2 flex"> | 
				
			|||
        <input type="checkbox" v-model="attended" class="h-6 w-6" /> | 
				
			|||
        <span class="pb-2 pl-2 pr-2">Attended</span> | 
				
			|||
      </div> | 
				
			|||
      <div class="m-2 flex"> | 
				
			|||
        <input type="checkbox" v-model="gaveTime" class="h-6 w-6" /> | 
				
			|||
        <span class="pb-2 pl-2 pr-2">Spent Time</span> | 
				
			|||
        <span v-if="gaveTime"> | 
				
			|||
          <input | 
				
			|||
            type="text" | 
				
			|||
            placeholder="How much time" | 
				
			|||
            v-model="hoursStr" | 
				
			|||
            size="1" | 
				
			|||
            class="border border-slate-400 h-6 px-2" | 
				
			|||
          /> | 
				
			|||
          hour(s) | 
				
			|||
        </span> | 
				
			|||
        <!-- This is to match input height to avoid shifting when hiding & showing. --> | 
				
			|||
        <span v-else class="h-6" /> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div | 
				
			|||
      v-if="attended || (gaveTime && hoursStr && hoursStr != '0')" | 
				
			|||
      class="flex justify-center mt-4" | 
				
			|||
    > | 
				
			|||
      <button | 
				
			|||
        @click="record()" | 
				
			|||
        class="block text-center text-md font-bold bg-blue-500 text-white px-2 py-3 rounded-md w-56" | 
				
			|||
      > | 
				
			|||
        Sign & Send | 
				
			|||
      </button> | 
				
			|||
    </div> | 
				
			|||
    <div v-else class="flex justify-center mt-4"> | 
				
			|||
      <button | 
				
			|||
        class="block text-center text-md font-bold bg-slate-500 text-white px-2 py-3 rounded-md w-56" | 
				
			|||
      > | 
				
			|||
        Select Your Actions | 
				
			|||
      </button> | 
				
			|||
    </div> | 
				
			|||
  </section> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script lang="ts"> | 
				
			|||
import axios from "axios"; | 
				
			|||
import { DateTime } from "luxon"; | 
				
			|||
import { Component, Vue } from "vue-facing-decorator"; | 
				
			|||
 | 
				
			|||
import QuickNav from "@/components/QuickNav.vue"; | 
				
			|||
import TopMessage from "@/components/TopMessage.vue"; | 
				
			|||
import { NotificationIface } from "@/constants/app"; | 
				
			|||
import { db } from "@/db/index"; | 
				
			|||
import { | 
				
			|||
  BVC_MEETUPS_PROJECT_CLAIM_ID, | 
				
			|||
  bvcMeetingJoinClaim, | 
				
			|||
  createAndSubmitClaim, | 
				
			|||
  createAndSubmitGive, | 
				
			|||
} from "@/libs/endorserServer"; | 
				
			|||
import * as libsUtil from "@/libs/util"; | 
				
			|||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings"; | 
				
			|||
 | 
				
			|||
@Component({ | 
				
			|||
  components: { | 
				
			|||
    QuickNav, | 
				
			|||
    TopMessage, | 
				
			|||
  }, | 
				
			|||
}) | 
				
			|||
export default class QuickActionBvcBeginView extends Vue { | 
				
			|||
  $notify!: (notification: NotificationIface, timeout?: number) => void; | 
				
			|||
 | 
				
			|||
  attended = true; | 
				
			|||
  gaveTime = true; | 
				
			|||
  hoursStr = "1"; | 
				
			|||
  todayOrPreviousStartDate = ""; | 
				
			|||
 | 
				
			|||
  async mounted() { | 
				
			|||
    let currentOrPreviousSat = DateTime.now().setZone("America/Denver"); | 
				
			|||
    if (currentOrPreviousSat.weekday < 6) { | 
				
			|||
      // it's not Saturday or Sunday, | 
				
			|||
      // so move back one week before setting to the Saturday | 
				
			|||
      currentOrPreviousSat = currentOrPreviousSat.minus({ week: 1 }); | 
				
			|||
    } | 
				
			|||
    const eventStartDateObj = currentOrPreviousSat | 
				
			|||
      .set({ weekday: 6 }) | 
				
			|||
      .set({ hour: 9 }) | 
				
			|||
      .startOf("hour"); | 
				
			|||
 | 
				
			|||
    // Hack, but full ISO pushes the length to 340 which crashes verifyJWT! | 
				
			|||
    this.todayOrPreviousStartDate = | 
				
			|||
      eventStartDateObj.toISO({ | 
				
			|||
        suppressMilliseconds: true, | 
				
			|||
      }) || ""; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  async record() { | 
				
			|||
    await db.open(); | 
				
			|||
    const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings; | 
				
			|||
    const activeDid = settings?.activeDid || ""; | 
				
			|||
    const apiServer = settings?.apiServer || ""; | 
				
			|||
 | 
				
			|||
    try { | 
				
			|||
      const hoursNum = libsUtil.numberOrZero(this.hoursStr); | 
				
			|||
      const identity = await libsUtil.getIdentity(activeDid); | 
				
			|||
 | 
				
			|||
      // first send the claim for time given | 
				
			|||
      let timeSuccess = false; | 
				
			|||
      if (this.gaveTime && hoursNum > 0) { | 
				
			|||
        const timeResult = await createAndSubmitGive( | 
				
			|||
          axios, | 
				
			|||
          apiServer, | 
				
			|||
          identity, | 
				
			|||
          activeDid, | 
				
			|||
          undefined, | 
				
			|||
          undefined, | 
				
			|||
          hoursNum, | 
				
			|||
          "HUR", | 
				
			|||
          BVC_MEETUPS_PROJECT_CLAIM_ID, | 
				
			|||
        ); | 
				
			|||
        if (timeResult.type === "success") { | 
				
			|||
          timeSuccess = true; | 
				
			|||
        } else { | 
				
			|||
          console.error("Error sending give:", timeResult); | 
				
			|||
          this.$notify( | 
				
			|||
            { | 
				
			|||
              group: "alert", | 
				
			|||
              type: "danger", | 
				
			|||
              title: "Error", | 
				
			|||
              text: | 
				
			|||
                timeResult?.error?.userMessage || | 
				
			|||
                "There was an error sending the time.", | 
				
			|||
            }, | 
				
			|||
            -1, | 
				
			|||
          ); | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
      // now send the claim for attendance | 
				
			|||
      let attendedSuccess = false; | 
				
			|||
      if (this.attended) { | 
				
			|||
        const attendResult = await createAndSubmitClaim( | 
				
			|||
          bvcMeetingJoinClaim(activeDid, this.todayOrPreviousStartDate), | 
				
			|||
          identity, | 
				
			|||
          apiServer, | 
				
			|||
          axios, | 
				
			|||
        ); | 
				
			|||
        if (attendResult.type === "success") { | 
				
			|||
          attendedSuccess = true; | 
				
			|||
        } else { | 
				
			|||
          console.error("Error sending give:", attendResult); | 
				
			|||
          this.$notify( | 
				
			|||
            { | 
				
			|||
              group: "alert", | 
				
			|||
              type: "danger", | 
				
			|||
              title: "Error", | 
				
			|||
              text: | 
				
			|||
                attendResult?.error?.userMessage || | 
				
			|||
                "There was an error sending the attendance.", | 
				
			|||
            }, | 
				
			|||
            -1, | 
				
			|||
          ); | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
      if (timeSuccess || attendedSuccess) { | 
				
			|||
        const actions = | 
				
			|||
          timeSuccess && attendedSuccess | 
				
			|||
            ? "attendance and time have been" | 
				
			|||
            : timeSuccess | 
				
			|||
              ? "time has been" | 
				
			|||
              : "attendance has been"; | 
				
			|||
        this.$notify( | 
				
			|||
          { | 
				
			|||
            group: "alert", | 
				
			|||
            type: "success", | 
				
			|||
            title: "Success", | 
				
			|||
            text: `Your ${actions} recorded.`, | 
				
			|||
          }, | 
				
			|||
          -1, | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
      // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
				
			|||
    } catch (error: any) { | 
				
			|||
      console.error("Error sending claims.", error); | 
				
			|||
      this.$notify( | 
				
			|||
        { | 
				
			|||
          group: "alert", | 
				
			|||
          type: "danger", | 
				
			|||
          title: "Error", | 
				
			|||
          text: error.userMessage || "There was an error sending claims.", | 
				
			|||
        }, | 
				
			|||
        -1, | 
				
			|||
      ); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,368 @@ | 
				
			|||
<template> | 
				
			|||
  <QuickNav /> | 
				
			|||
  <TopMessage /> | 
				
			|||
 | 
				
			|||
  <!-- CONTENT --> | 
				
			|||
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto"> | 
				
			|||
    <!-- Back --> | 
				
			|||
    <div 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="$router.back()" | 
				
			|||
      > | 
				
			|||
        <fa icon="chevron-left" class="fa-fw"></fa> | 
				
			|||
      </h1> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <!-- Heading --> | 
				
			|||
    <h1 id="ViewHeading" class="text-4xl text-center font-light px-4 mb-4"> | 
				
			|||
      End of BVC Saturday Meeting | 
				
			|||
    </h1> | 
				
			|||
 | 
				
			|||
    <div> | 
				
			|||
      <h2 class="text-2xl m-2">Confirm</h2> | 
				
			|||
      <div v-if="loadingConfirms" class="flex justify-center"> | 
				
			|||
        <fa icon="spinner" class="animate-spin" /> | 
				
			|||
      </div> | 
				
			|||
      <div v-else-if="claimsToConfirm.length === 0"> | 
				
			|||
        There are no claims yet today for you to confirm. | 
				
			|||
        <span v-if="claimCountWithHidden > 0"> | 
				
			|||
          {{ | 
				
			|||
            claimCountWithHidden === 1 | 
				
			|||
              ? "(There is 1 claim with hidden details.)" | 
				
			|||
              : `(There are ${claimCountWithHidden} claims with hidden details.)` | 
				
			|||
          }} | 
				
			|||
        </span> | 
				
			|||
      </div> | 
				
			|||
      <ul class="border-t border-slate-300 m-2"> | 
				
			|||
        <li | 
				
			|||
          class="border-b border-slate-300 py-2" | 
				
			|||
          v-for="record in claimsToConfirm" | 
				
			|||
          :key="record.id" | 
				
			|||
        > | 
				
			|||
          <div class="grid grid-cols-12"> | 
				
			|||
            <span class="col-span-11 justify-self-start"> | 
				
			|||
              <span> | 
				
			|||
                <input | 
				
			|||
                  type="checkbox" | 
				
			|||
                  :checked="claimsToConfirmSelected.includes(record.id)" | 
				
			|||
                  @click=" | 
				
			|||
                    claimsToConfirmSelected.includes(record.id) | 
				
			|||
                      ? claimsToConfirmSelected.splice( | 
				
			|||
                          claimsToConfirmSelected.indexOf(record.id), | 
				
			|||
                          1, | 
				
			|||
                        ) | 
				
			|||
                      : claimsToConfirmSelected.push(record.id) | 
				
			|||
                  " | 
				
			|||
                  class="mr-2 h-6 w-6" | 
				
			|||
                /> | 
				
			|||
              </span> | 
				
			|||
              {{ | 
				
			|||
                claimSpecialDescription( | 
				
			|||
                  record, | 
				
			|||
                  activeDid, | 
				
			|||
                  allMyDids, | 
				
			|||
                  allContacts, | 
				
			|||
                ) | 
				
			|||
              }} | 
				
			|||
              <a @click="onClickLoadClaim(record.id)"> | 
				
			|||
                <fa | 
				
			|||
                  icon="circle-info" | 
				
			|||
                  class="pl-2 text-blue-500 cursor-pointer" | 
				
			|||
                /> | 
				
			|||
              </a> | 
				
			|||
            </span> | 
				
			|||
          </div> | 
				
			|||
        </li> | 
				
			|||
      </ul> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div> | 
				
			|||
      <h2 class="text-2xl m-2">Anything else?</h2> | 
				
			|||
      <div class="m-2 flex"> | 
				
			|||
        <input type="checkbox" v-model="someoneGave" class="h-6 w-6" /> | 
				
			|||
        <span class="pb-2 pl-2 pr-2">Someone else gave</span> | 
				
			|||
        <span v-if="someoneGave"> | 
				
			|||
          <input | 
				
			|||
            type="text" | 
				
			|||
            v-model="description" | 
				
			|||
            size="20" | 
				
			|||
            class="border border-slate-400 h-6 px-2" | 
				
			|||
          /> | 
				
			|||
        </span> | 
				
			|||
        <!-- This is to match input height to avoid shifting when hiding & showing. --> | 
				
			|||
        <span v-else class="h-6">...</span> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div | 
				
			|||
      v-if="claimsToConfirmSelected.length || (someoneGave && description)" | 
				
			|||
      class="flex justify-center mt-4" | 
				
			|||
    > | 
				
			|||
      <button | 
				
			|||
        @click="record()" | 
				
			|||
        class="block text-center text-md font-bold bg-blue-500 text-white px-2 py-3 rounded-md w-56" | 
				
			|||
      > | 
				
			|||
        Sign & Send | 
				
			|||
      </button> | 
				
			|||
    </div> | 
				
			|||
    <div v-else class="flex justify-center mt-4"> | 
				
			|||
      <button | 
				
			|||
        class="block text-center text-md font-bold bg-slate-500 text-white px-2 py-3 rounded-md w-56" | 
				
			|||
      > | 
				
			|||
        Choose What To Confirm | 
				
			|||
      </button> | 
				
			|||
    </div> | 
				
			|||
  </section> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script lang="ts"> | 
				
			|||
import axios from "axios"; | 
				
			|||
import { DateTime } from "luxon"; | 
				
			|||
import * as R from "ramda"; | 
				
			|||
import { IIdentifier } from "@veramo/core"; | 
				
			|||
import { Component, Vue } from "vue-facing-decorator"; | 
				
			|||
 | 
				
			|||
import QuickNav from "@/components/QuickNav.vue"; | 
				
			|||
import TopMessage from "@/components/TopMessage.vue"; | 
				
			|||
import { NotificationIface } from "@/constants/app"; | 
				
			|||
import { accountsDB, db } from "@/db/index"; | 
				
			|||
import { Account } from "@/db/tables/accounts"; | 
				
			|||
import { Contact } from "@/db/tables/contacts"; | 
				
			|||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings"; | 
				
			|||
import { accessToken } from "@/libs/crypto"; | 
				
			|||
import { | 
				
			|||
  BVC_MEETUPS_PROJECT_CLAIM_ID, | 
				
			|||
  claimSpecialDescription, | 
				
			|||
  containsHiddenDid, | 
				
			|||
  createAndSubmitConfirmation, | 
				
			|||
  createAndSubmitGive, | 
				
			|||
  ErrorResult, | 
				
			|||
  GenericServerRecord, | 
				
			|||
  GenericVerifiableCredential, | 
				
			|||
} from "@/libs/endorserServer"; | 
				
			|||
import * as libsUtil from "@/libs/util"; | 
				
			|||
 | 
				
			|||
@Component({ | 
				
			|||
  methods: { claimSpecialDescription }, | 
				
			|||
  components: { | 
				
			|||
    QuickNav, | 
				
			|||
    TopMessage, | 
				
			|||
  }, | 
				
			|||
}) | 
				
			|||
export default class QuickActionBvcBeginView extends Vue { | 
				
			|||
  $notify!: (notification: NotificationIface, timeout?: number) => void; | 
				
			|||
 | 
				
			|||
  activeDid = ""; | 
				
			|||
  allContacts: Array<Contact> = []; | 
				
			|||
  allMyDids: Array<string> = []; | 
				
			|||
  apiServer = ""; | 
				
			|||
  claimCountWithHidden = 0; | 
				
			|||
  claimsToConfirm: GenericServerRecord[] = []; | 
				
			|||
  claimsToConfirmSelected: string[] = []; | 
				
			|||
  description = "breakfast"; | 
				
			|||
  loadingConfirms = true; | 
				
			|||
  someoneGave = false; | 
				
			|||
 | 
				
			|||
  async created() { | 
				
			|||
    await db.open(); | 
				
			|||
    const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings; | 
				
			|||
    this.apiServer = settings?.apiServer || ""; | 
				
			|||
    this.activeDid = settings?.activeDid || ""; | 
				
			|||
    this.allContacts = await db.contacts.toArray(); | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  async mounted() { | 
				
			|||
    this.loadingConfirms = true; | 
				
			|||
    let currentOrPreviousSat = DateTime.now().setZone("America/Denver"); | 
				
			|||
    if (currentOrPreviousSat.weekday < 6) { | 
				
			|||
      // it's not Saturday or Sunday, | 
				
			|||
      // so move back one week before setting to the Saturday | 
				
			|||
      currentOrPreviousSat = currentOrPreviousSat.minus({ week: 1 }); | 
				
			|||
    } | 
				
			|||
    const eventStartDateObj = currentOrPreviousSat | 
				
			|||
      .set({ weekday: 6 }) | 
				
			|||
      .set({ hour: 9 }) | 
				
			|||
      .startOf("hour"); | 
				
			|||
 | 
				
			|||
    // Hack, but full ISO pushes the length to 340 which crashes verifyJWT! | 
				
			|||
    const todayOrPreviousStartDate = | 
				
			|||
      eventStartDateObj.toISO({ | 
				
			|||
        suppressMilliseconds: true, | 
				
			|||
      }) || ""; | 
				
			|||
 | 
				
			|||
    await accountsDB.open(); | 
				
			|||
    const allAccounts = await accountsDB.accounts.toArray(); | 
				
			|||
    this.allMyDids = allAccounts.map((acc) => acc.did); | 
				
			|||
    const account: Account | undefined = await accountsDB.accounts | 
				
			|||
      .where("did") | 
				
			|||
      .equals(this.activeDid) | 
				
			|||
      .first(); | 
				
			|||
    const identity: IIdentifier = JSON.parse( | 
				
			|||
      (account?.identity as string) || "null", | 
				
			|||
    ); | 
				
			|||
    const headers = { | 
				
			|||
      Authorization: "Bearer " + (await accessToken(identity)), | 
				
			|||
    }; | 
				
			|||
    try { | 
				
			|||
      const response = await fetch( | 
				
			|||
        this.apiServer + | 
				
			|||
          "/api/claim/?" + | 
				
			|||
          "issuedAt_greaterThanOrEqualTo=" + | 
				
			|||
          encodeURIComponent(todayOrPreviousStartDate) + | 
				
			|||
          "&excludeConfirmations=true", | 
				
			|||
        { headers }, | 
				
			|||
      ); | 
				
			|||
 | 
				
			|||
      if (!response.ok) { | 
				
			|||
        console.log("Bad response", response); | 
				
			|||
        throw new Error("Bad response when retrieving claims."); | 
				
			|||
      } | 
				
			|||
      await response.json().then((data) => { | 
				
			|||
        const dataByOthers = R.reject( | 
				
			|||
          (claim: GenericServerRecord) => claim.issuer === this.activeDid, | 
				
			|||
          data, | 
				
			|||
        ); | 
				
			|||
        const dataByOthersWithoutHidden = R.reject( | 
				
			|||
          containsHiddenDid, | 
				
			|||
          dataByOthers, | 
				
			|||
        ); | 
				
			|||
        this.claimsToConfirm = dataByOthersWithoutHidden; | 
				
			|||
        this.claimCountWithHidden = | 
				
			|||
          dataByOthers.length - dataByOthersWithoutHidden.length; | 
				
			|||
      }); | 
				
			|||
    } catch (error) { | 
				
			|||
      console.error("Error:", error); | 
				
			|||
      this.$notify( | 
				
			|||
        { | 
				
			|||
          group: "alert", | 
				
			|||
          type: "danger", | 
				
			|||
          title: "Error", | 
				
			|||
          text: "There was an error retrieving today's claims to confirm.", | 
				
			|||
        }, | 
				
			|||
        -1, | 
				
			|||
      ); | 
				
			|||
    } | 
				
			|||
    this.loadingConfirms = false; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  onClickLoadClaim(jwtId: string) { | 
				
			|||
    const route = { | 
				
			|||
      path: "/claim/" + encodeURIComponent(jwtId), | 
				
			|||
    }; | 
				
			|||
    this.$router.push(route); | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  async record() { | 
				
			|||
    try { | 
				
			|||
      const identity = await libsUtil.getIdentity(this.activeDid); | 
				
			|||
 | 
				
			|||
      // in parallel, make a confirmation for each selected claim and send them all to the server | 
				
			|||
      const confirmResults = await Promise.allSettled( | 
				
			|||
        this.claimsToConfirmSelected.map(async (jwtId) => { | 
				
			|||
          const record = this.claimsToConfirm.find( | 
				
			|||
            (claim) => claim.id === jwtId, | 
				
			|||
          ); | 
				
			|||
          if (!record) { | 
				
			|||
            return { type: "error", error: "Record not found." }; | 
				
			|||
          } | 
				
			|||
          const identity = await libsUtil.getIdentity(this.activeDid); | 
				
			|||
          return createAndSubmitConfirmation( | 
				
			|||
            identity, | 
				
			|||
            record.claim as GenericVerifiableCredential, | 
				
			|||
            record.id, | 
				
			|||
            record.handleId, | 
				
			|||
            this.apiServer, | 
				
			|||
            axios, | 
				
			|||
          ); | 
				
			|||
        }), | 
				
			|||
      ); | 
				
			|||
      // check for any rejected confirmations | 
				
			|||
      const confirmsSucceeded = confirmResults.filter( | 
				
			|||
        (result) => | 
				
			|||
          result.status === "fulfilled" && result.value.type === "success", | 
				
			|||
      ); | 
				
			|||
      if (confirmsSucceeded.length < this.claimsToConfirmSelected.length) { | 
				
			|||
        console.error("Error sending confirmations:", confirmResults); | 
				
			|||
        const howMany = confirmsSucceeded.length === 0 ? "all" : "some"; | 
				
			|||
        this.$notify( | 
				
			|||
          { | 
				
			|||
            group: "alert", | 
				
			|||
            type: "danger", | 
				
			|||
            title: "Error", | 
				
			|||
            text: `There was an error sending ${howMany} of the confirmations.`, | 
				
			|||
          }, | 
				
			|||
          -1, | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
      // now send the give for the description | 
				
			|||
      let giveSucceeded = false; | 
				
			|||
      if (this.someoneGave) { | 
				
			|||
        const giveResult = await createAndSubmitGive( | 
				
			|||
          axios, | 
				
			|||
          this.apiServer, | 
				
			|||
          identity, | 
				
			|||
          undefined, | 
				
			|||
          this.activeDid, | 
				
			|||
          this.description, | 
				
			|||
          undefined, | 
				
			|||
          undefined, | 
				
			|||
          BVC_MEETUPS_PROJECT_CLAIM_ID, | 
				
			|||
        ); | 
				
			|||
        giveSucceeded = giveResult.type === "success"; | 
				
			|||
        if (!giveSucceeded) { | 
				
			|||
          console.error("Error sending give:", giveResult); | 
				
			|||
          this.$notify( | 
				
			|||
            { | 
				
			|||
              group: "alert", | 
				
			|||
              type: "danger", | 
				
			|||
              title: "Error", | 
				
			|||
              text: | 
				
			|||
                (giveResult as ErrorResult)?.error?.userMessage || | 
				
			|||
                "There was an error sending the give.", | 
				
			|||
            }, | 
				
			|||
            -1, | 
				
			|||
          ); | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
      if (confirmsSucceeded.length > 0 || giveSucceeded) { | 
				
			|||
        const confirms = | 
				
			|||
          confirmsSucceeded.length === 1 ? "confirmation" : "confirmations"; | 
				
			|||
        const actions = | 
				
			|||
          confirmsSucceeded.length > 0 && giveSucceeded | 
				
			|||
            ? `${confirms} and give have been` | 
				
			|||
            : giveSucceeded | 
				
			|||
              ? "give has been" | 
				
			|||
              : confirms + | 
				
			|||
                " " + | 
				
			|||
                (confirmsSucceeded.length === 1 ? "has" : "have") + | 
				
			|||
                " been"; | 
				
			|||
        this.$notify( | 
				
			|||
          { | 
				
			|||
            group: "alert", | 
				
			|||
            type: "success", | 
				
			|||
            title: "Success", | 
				
			|||
            text: `Your ${actions} recorded.`, | 
				
			|||
          }, | 
				
			|||
          -1, | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
      // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
				
			|||
    } catch (error: any) { | 
				
			|||
      console.error("Error sending claims.", error); | 
				
			|||
      this.$notify( | 
				
			|||
        { | 
				
			|||
          group: "alert", | 
				
			|||
          type: "danger", | 
				
			|||
          title: "Error", | 
				
			|||
          text: error.userMessage || "There was an error sending claims.", | 
				
			|||
        }, | 
				
			|||
        -1, | 
				
			|||
      ); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,52 @@ | 
				
			|||
<template> | 
				
			|||
  <QuickNav /> | 
				
			|||
  <TopMessage /> | 
				
			|||
 | 
				
			|||
  <!-- CONTENT --> | 
				
			|||
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto"> | 
				
			|||
    <!-- Back --> | 
				
			|||
    <div 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="$router.back()" | 
				
			|||
      > | 
				
			|||
        <fa icon="chevron-left" class="fa-fw"></fa> | 
				
			|||
      </h1> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <!-- Heading --> | 
				
			|||
    <h1 id="ViewHeading" class="text-4xl text-center font-light px-4 mb-4"> | 
				
			|||
      Bountiful Voluntaryist Community Actions | 
				
			|||
    </h1> | 
				
			|||
 | 
				
			|||
    <div> | 
				
			|||
      <router-link | 
				
			|||
        :to="{ name: 'quick-action-bvc-begin' }" | 
				
			|||
        class="block text-center text-md font-bold uppercase bg-blue-500 text-white mt-2 px-2 py-3 rounded-md" | 
				
			|||
      > | 
				
			|||
        Beginning of Meeting | 
				
			|||
      </router-link> | 
				
			|||
      <router-link | 
				
			|||
        :to="{ name: 'quick-action-bvc-end' }" | 
				
			|||
        class="block text-center text-md font-bold uppercase bg-blue-500 text-white mt-2 px-2 py-3 rounded-md" | 
				
			|||
      > | 
				
			|||
        End of Meeting | 
				
			|||
      </router-link> | 
				
			|||
    </div> | 
				
			|||
  </section> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script lang="ts"> | 
				
			|||
import { Component, Vue } from "vue-facing-decorator"; | 
				
			|||
 | 
				
			|||
import QuickNav from "@/components/QuickNav.vue"; | 
				
			|||
import TopMessage from "@/components/TopMessage.vue"; | 
				
			|||
 | 
				
			|||
@Component({ | 
				
			|||
  components: { | 
				
			|||
    QuickNav, | 
				
			|||
    TopMessage, | 
				
			|||
  }, | 
				
			|||
}) | 
				
			|||
export default class QuickActionBvcView extends Vue {} | 
				
			|||
</script> | 
				
			|||
					Loading…
					
					
				
		Reference in new issue