From 3daf1c8a5c7493f9275226c4d817aaa808d3470f Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Thu, 12 Jun 2025 20:50:27 +0800 Subject: [PATCH] Feature: Project Gifting - Gifting dialog: added ability to pick a project to benefit from - Project view: modified dialog calls in Project view to toggle between giving to and benefiting from a project - Project view: removed redundant person selection - Project view: benefiting from a project locks the project selection in dialog to enforce context. --- src/components/GiftedDialog.vue | 291 ++++++++++++++++++++++++-------- src/libs/util.ts | 2 + src/views/HomeView.vue | 17 +- src/views/ProjectViewView.vue | 74 ++------ 4 files changed, 244 insertions(+), 140 deletions(-) diff --git a/src/components/GiftedDialog.vue b/src/components/GiftedDialog.vue index dccd7a09..7b3f4af8 100644 --- a/src/components/GiftedDialog.vue +++ b/src/components/GiftedDialog.vue @@ -3,63 +3,104 @@
- - - -
    -
  • - -

    + {{ showProjects ? 'Choose a project to benefit from:' : 'Choose a person to receive from:' }} + + + +
      + +
    + + +

+ +
+

{{ showProjects ? 'Benefited from:' : 'Received from:' }}

+

{{ giver?.name || 'Unnamed' }}

+
+ +

Change

+ +
+
+ + +
+ +
+

{{ showProjects ? 'Benefited from:' : 'Received from:' }}

+

{{ giver?.name || 'Unnamed' }}

+
+
= []; @@ -222,6 +314,10 @@ export default class GiftedDialog extends Vue { libsUtil = libsUtil; + projects: PlanData[] = []; + + didInfo = didInfo; + async open( giver?: libsUtil.GiverReceiverInputInfo, receiver?: libsUtil.GiverReceiverInputInfo, @@ -234,7 +330,6 @@ export default class GiftedDialog extends Vue { this.giver = giver; this.prompt = prompt || ""; this.receiver = receiver; - // if we show "given to user" selection, default checkbox to true this.amountInput = "0"; this.callbackOnSuccess = callbackOnSuccess; this.offerId = offerId || ""; @@ -269,7 +364,10 @@ export default class GiftedDialog extends Vue { this.allContacts, ); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any + + if (this.showProjects) { + await this.loadProjects(); + } } catch (err: any) { logger.error("Error retrieving settings from database:", err); this.$notify( @@ -404,7 +502,7 @@ export default class GiftedDialog extends Vue { this.axios, this.apiServer, this.activeDid, - giverDid as string, + this.showProjects ? undefined : giverDid as string, recipientDid as string, description, amount, @@ -413,7 +511,7 @@ export default class GiftedDialog extends Vue { this.offerId, false, undefined, - this.fromProjectId, + this.showProjects ? this.giver?.handleId : undefined, ); if (!result.success) { @@ -506,6 +604,49 @@ export default class GiftedDialog extends Vue { goBackToStep1() { this.currentStep = 1; } + + async loadProjects() { + try { + const response = await fetch(this.apiServer + "/api/v2/report/plans", { + method: "GET", + headers: await getHeaders(this.activeDid), + }); + + if (response.status !== 200) { + throw new Error("Failed to load projects"); + } + + const results = await response.json(); + if (results.data) { + this.projects = results.data; + } + } catch (error) { + logger.error("Error loading projects:", error); + this.$notify( + { + group: "alert", + type: "danger", + title: "Error", + text: "Failed to load projects", + }, + 3000, + ); + } + } + + selectProject(project: PlanData) { + this.giver = { + did: project.handleId, + name: project.name, + image: project.image, + handleId: project.handleId + }; + this.receiver = { + did: this.activeDid, + name: "You" + }; + this.currentStep = 2; + } } diff --git a/src/libs/util.ts b/src/libs/util.ts index 3bc86866..81d04835 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -49,6 +49,8 @@ import { insertDidSpecificSettings, parseJsonField } from "../db/databaseUtil"; export interface GiverReceiverInputInfo { did?: string; name?: string; + image?: string; + handleId?: string; } export enum OnboardPage { diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 7f91c957..1c73c7d6 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -132,7 +132,7 @@ Raymer * @version 1.0.0 */
- + @@ -439,6 +439,7 @@ export default class HomeView extends Vue { selectedImageData: Blob | null = null; isImageViewerOpen = false; imageCache: Map = new Map(); + showProjectsDialog = false; /** * Initializes the component on mount @@ -1862,5 +1863,15 @@ export default class HomeView extends Vue { this.$router.push({ name: "contact-qr" }); } } + + openDialogPerson(giver?: GiverReceiverInputInfo | "Unnamed", description?: string) { + this.showProjectsDialog = false; + this.openDialog(giver, description); + } + + openProjectDialog() { + this.showProjectsDialog = true; + (this.$refs.customDialog as any).open(); + } } diff --git a/src/views/ProjectViewView.vue b/src/views/ProjectViewView.vue index 2dfd0cbc..2015b25d 100644 --- a/src/views/ProjectViewView.vue +++ b/src/views/ProjectViewView.vue @@ -196,63 +196,7 @@ -
-
-

Record a contribution from:

-
-
    -
  • - -

    - You -

    -
  • -
  • - -

    - Unnamed/Unknown -

    -
  • -
  • - -

    - {{ contact.name || "(no name)" }} -

    -
  • -
  • - - ... or someone else... - -
  • -
-
- +
@@ -518,7 +462,7 @@
- +

Benefitted From This Project @@ -1241,21 +1185,26 @@ export default class ProjectViewView extends Vue { // Immediately select "Unnamed" and move to Step 2 (this.$refs.giveDialogToThis as GiftedDialog).selectGiver(); } else { + // Set only the project as recipient, allowing user to select giver in Step 1 (this.$refs.giveDialogToThis as GiftedDialog).open( - contact, undefined, + { did: this.issuer, name: this.name, handleId: this.projectId, image: this.imageUrl }, undefined, - (contact?.name || "Someone not named") + ` gave to this project`, + `Given to ${this.name}`, ); } } openGiftDialogFromProject() { + // Set the project as giver and the current user as recipient (this.$refs.giveDialogFromThis as GiftedDialog).open( - undefined, + { did: undefined, name: this.name, handleId: this.projectId, image: this.imageUrl }, { did: this.activeDid, name: "You" }, undefined, - `This project gave to you`, + `${this.name} gave to you`, + undefined, + undefined, + true ); } @@ -1530,3 +1479,4 @@ export default class ProjectViewView extends Vue { } } +