forked from jsnbuchanan/crowd-funder-for-time-pwa
Add server-side pagination to EntityGrid component for projects, enabling infinite scrolling to load all available projects instead of stopping after the initial batch. Changes: - EntityGrid: Add loadMoreCallback prop to trigger server-side loading when scroll reaches end of loaded projects - OnboardMeetingSetupView: Update loadProjects() to support pagination with beforeId parameter and add handleLoadMoreProjects() callback - MeetingProjectDialog: Accept and pass through loadMoreCallback to EntityGrid - GiftedDialog: Add pagination support to loadProjects() and handleLoadMoreProjects() callback - EntitySelectionStep: Accept and pass through loadMoreCallback prop to EntityGrid when showing projects This ensures users can access all projects in MeetingProjectDialog and GiftedDialog by automatically loading more as they scroll, matching the behavior already present in DiscoverView. All project uses of EntityGrid now use pagination by default.
724 lines
20 KiB
Vue
724 lines
20 KiB
Vue
<template>
|
|
<div v-if="visible" class="dialog-overlay">
|
|
<div
|
|
class="dialog"
|
|
data-testid="gifted-dialog"
|
|
:data-recipient-entity-type="recipientEntityType"
|
|
>
|
|
<!-- Step 1: Entity Selection -->
|
|
<EntitySelectionStep
|
|
v-show="firstStep"
|
|
:step-type="stepType"
|
|
:giver-entity-type="giverEntityType"
|
|
:recipient-entity-type="recipientEntityType"
|
|
:show-projects="
|
|
giverEntityType === 'project' || recipientEntityType === 'project'
|
|
"
|
|
:is-from-project-view="isFromProjectView"
|
|
:projects="projects"
|
|
:all-contacts="allContacts"
|
|
:active-did="activeDid"
|
|
:all-my-dids="allMyDids"
|
|
:conflict-checker="wouldCreateConflict"
|
|
:from-project-id="fromProjectId"
|
|
:to-project-id="toProjectId"
|
|
:giver="giver"
|
|
:receiver="receiver"
|
|
:description="description"
|
|
:amount-input="amountInput"
|
|
:unit-code="unitCode"
|
|
:offer-id="offerId"
|
|
:notify="$notify"
|
|
:load-more-callback="
|
|
giverEntityType === 'project' || recipientEntityType === 'project'
|
|
? handleLoadMoreProjects
|
|
: undefined
|
|
"
|
|
@entity-selected="handleEntitySelected"
|
|
@cancel="cancel"
|
|
/>
|
|
|
|
<!-- Step 2: Gift Details -->
|
|
<GiftDetailsStep
|
|
v-show="!firstStep"
|
|
:giver="giver"
|
|
:receiver="receiver"
|
|
:giver-entity-type="giverEntityType"
|
|
:recipient-entity-type="recipientEntityType"
|
|
:description="description"
|
|
:amount="parseFloat(amountInput) || 0"
|
|
:unit-code="unitCode"
|
|
:prompt="prompt"
|
|
:is-from-project-view="isFromProjectView"
|
|
:has-conflict="hasPersonConflict"
|
|
:offer-id="offerId"
|
|
:from-project-id="fromProjectId"
|
|
:to-project-id="toProjectId"
|
|
:on-update-description="(desc: string) => (description = desc)"
|
|
:on-update-amount="handleAmountUpdate"
|
|
:on-update-unit-code="(code: string) => (unitCode = code)"
|
|
@edit-entity="handleEditEntity"
|
|
@explain-data="explainData"
|
|
@submit="handleSubmit"
|
|
@cancel="cancel"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Vue, Component, Prop } from "vue-facing-decorator";
|
|
|
|
import {
|
|
createAndSubmitGive,
|
|
didInfo,
|
|
serverMessageForUser,
|
|
getHeaders,
|
|
} from "../libs/endorserServer";
|
|
import * as libsUtil from "../libs/util";
|
|
import { Contact } from "../db/tables/contacts";
|
|
import { retrieveAccountDids } from "../libs/util";
|
|
import { logger } from "../utils/logger";
|
|
import EntityIcon from "../components/EntityIcon.vue";
|
|
import ProjectIcon from "../components/ProjectIcon.vue";
|
|
import EntitySelectionStep from "../components/EntitySelectionStep.vue";
|
|
import GiftDetailsStep from "../components/GiftDetailsStep.vue";
|
|
import { PlanData } from "../interfaces/records";
|
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
|
import { createNotifyHelpers, TIMEOUTS, NotifyFunction } from "@/utils/notify";
|
|
import { showSeedPhraseReminder } from "@/utils/seedPhraseReminder";
|
|
import {
|
|
NOTIFY_GIFT_ERROR_NEGATIVE_AMOUNT,
|
|
NOTIFY_GIFT_ERROR_NO_DESCRIPTION,
|
|
NOTIFY_GIFTED_DETAILS_NO_IDENTIFIER,
|
|
NOTIFY_GIFTED_DETAILS_RECORDING_GIVE,
|
|
} from "@/constants/notifications";
|
|
import { UNNAMED_ENTITY_NAME } from "@/constants/entities";
|
|
|
|
@Component({
|
|
components: {
|
|
EntityIcon,
|
|
ProjectIcon,
|
|
EntitySelectionStep,
|
|
GiftDetailsStep,
|
|
},
|
|
mixins: [PlatformServiceMixin],
|
|
})
|
|
export default class GiftedDialog extends Vue {
|
|
$notify!: NotifyFunction;
|
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
|
|
|
/**
|
|
* Safe notification method that ensures notify helpers are available
|
|
*/
|
|
get safeNotify() {
|
|
if (!this.notify && this.$notify) {
|
|
this.notify = createNotifyHelpers(this.$notify);
|
|
}
|
|
return this.notify;
|
|
}
|
|
|
|
@Prop() fromProjectId = "";
|
|
@Prop() toProjectId = "";
|
|
@Prop() isFromProjectView = false;
|
|
@Prop({ default: "person" }) giverEntityType = "person" as
|
|
| "person"
|
|
| "project";
|
|
@Prop({ default: "person" }) recipientEntityType = "person" as
|
|
| "person"
|
|
| "project";
|
|
|
|
activeDid = "";
|
|
allContacts: Array<Contact> = [];
|
|
allMyDids: Array<string> = [];
|
|
apiServer = "";
|
|
|
|
amountInput = "0";
|
|
callbackOnSuccess?: (amount: number) => void = () => {};
|
|
description = "";
|
|
firstStep = true; // true = Step 1 (giver/recipient selection), false = Step 2 (amount/description)
|
|
giver?: libsUtil.GiverReceiverInputInfo; // undefined means no identified giver agent
|
|
offerId = "";
|
|
projects: PlanData[] = [];
|
|
prompt = "";
|
|
receiver?: libsUtil.GiverReceiverInputInfo;
|
|
stepType = "giver";
|
|
unitCode = "HUR";
|
|
visible = false;
|
|
|
|
libsUtil = libsUtil;
|
|
|
|
didInfo = didInfo;
|
|
|
|
// Computed property to help debug template logic
|
|
get shouldShowProjects() {
|
|
const result =
|
|
(this.stepType === "giver" && this.giverEntityType === "project") ||
|
|
(this.stepType === "recipient" && this.recipientEntityType === "project");
|
|
return result;
|
|
}
|
|
|
|
// Computed property to check if current selection would create a conflict
|
|
get hasPersonConflict() {
|
|
// Only check for conflicts when both entities are persons
|
|
if (
|
|
this.giverEntityType !== "person" ||
|
|
this.recipientEntityType !== "person"
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
// Check if giver and recipient are the same person
|
|
if (
|
|
this.giver?.did &&
|
|
this.receiver?.did &&
|
|
this.giver.did === this.receiver.did
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Computed property to check if a contact would create a conflict when selected
|
|
wouldCreateConflict(contactDid: string) {
|
|
// Only check for conflicts when both entities are persons
|
|
if (
|
|
this.giverEntityType !== "person" ||
|
|
this.recipientEntityType !== "person"
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
if (this.stepType === "giver") {
|
|
// If selecting as giver, check if it conflicts with current recipient
|
|
return this.receiver?.did === contactDid;
|
|
} else if (this.stepType === "recipient") {
|
|
// If selecting as recipient, check if it conflicts with current giver
|
|
return this.giver?.did === contactDid;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
async open(
|
|
giver?: libsUtil.GiverReceiverInputInfo,
|
|
receiver?: libsUtil.GiverReceiverInputInfo,
|
|
offerId?: string,
|
|
prompt?: string,
|
|
description?: string,
|
|
amountInput?: string,
|
|
unitCode?: string,
|
|
callbackOnSuccess: (amount: number) => void = () => {},
|
|
) {
|
|
this.giver = giver;
|
|
this.receiver = receiver;
|
|
this.offerId = offerId || "";
|
|
this.prompt = prompt || "";
|
|
this.description = description || "";
|
|
this.amountInput = amountInput || "0";
|
|
this.unitCode = unitCode || "HUR";
|
|
this.callbackOnSuccess = callbackOnSuccess;
|
|
this.firstStep = !giver;
|
|
this.stepType = "giver";
|
|
|
|
try {
|
|
const settings = await this.$accountSettings();
|
|
this.apiServer = settings.apiServer || "";
|
|
|
|
// Get activeDid from active_identity table (single source of truth)
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const activeIdentity = await (this as any).$getActiveIdentity();
|
|
this.activeDid = activeIdentity.activeDid || "";
|
|
|
|
logger.debug("[GiftedDialog] Settings received:", {
|
|
activeDid: this.activeDid,
|
|
apiServer: this.apiServer,
|
|
});
|
|
|
|
this.allContacts = await this.$contactsByDateAdded();
|
|
|
|
this.allMyDids = await retrieveAccountDids();
|
|
|
|
if (
|
|
this.giverEntityType === "project" ||
|
|
this.recipientEntityType === "project"
|
|
) {
|
|
await this.loadProjects();
|
|
} else {
|
|
// Clear projects array when not needed
|
|
this.projects = [];
|
|
}
|
|
} catch (err: unknown) {
|
|
logger.error("Error retrieving settings from database:", err);
|
|
this.safeNotify.error(
|
|
err instanceof Error
|
|
? err.message
|
|
: "There was an error retrieving your settings.",
|
|
TIMEOUTS.MODAL,
|
|
);
|
|
}
|
|
|
|
this.visible = true;
|
|
}
|
|
|
|
close() {
|
|
// close the dialog but don't change values (since it might be submitting info)
|
|
this.visible = false;
|
|
}
|
|
|
|
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() {
|
|
this.close();
|
|
this.eraseValues();
|
|
}
|
|
|
|
eraseValues() {
|
|
this.description = "";
|
|
this.giver = undefined;
|
|
this.amountInput = "0";
|
|
this.prompt = "";
|
|
this.unitCode = "HUR";
|
|
this.firstStep = true;
|
|
}
|
|
|
|
async confirm() {
|
|
if (!this.activeDid) {
|
|
this.safeNotify.error(
|
|
NOTIFY_GIFTED_DETAILS_NO_IDENTIFIER.message,
|
|
TIMEOUTS.SHORT,
|
|
);
|
|
return;
|
|
}
|
|
if (parseFloat(this.amountInput) < 0) {
|
|
this.safeNotify.error(
|
|
NOTIFY_GIFT_ERROR_NEGATIVE_AMOUNT.message,
|
|
TIMEOUTS.SHORT,
|
|
);
|
|
return;
|
|
}
|
|
if (!this.description && !parseFloat(this.amountInput)) {
|
|
this.safeNotify.error(
|
|
NOTIFY_GIFT_ERROR_NO_DESCRIPTION.message.replace(
|
|
"{unit}",
|
|
this.libsUtil.UNIT_SHORT[this.unitCode] || this.unitCode,
|
|
),
|
|
TIMEOUTS.SHORT,
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Check for person conflict
|
|
if (this.hasPersonConflict) {
|
|
this.safeNotify.error(
|
|
"You cannot select the same person as both giver and recipient.",
|
|
TIMEOUTS.STANDARD,
|
|
);
|
|
return;
|
|
}
|
|
|
|
this.close();
|
|
this.safeNotify.toast(
|
|
NOTIFY_GIFTED_DETAILS_RECORDING_GIVE.message,
|
|
undefined,
|
|
TIMEOUTS.BRIEF,
|
|
);
|
|
// this is asynchronous, but we don't need to wait for it to complete
|
|
await this.recordGive(
|
|
(this.giver?.did as string) || null,
|
|
(this.receiver?.did as string) || null,
|
|
this.description,
|
|
parseFloat(this.amountInput),
|
|
this.unitCode,
|
|
).then(() => {
|
|
this.eraseValues();
|
|
});
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param giverDid may be null
|
|
* @param recipientDid may be null
|
|
* @param description may be an empty string
|
|
* @param amount may be 0
|
|
* @param unitCode may be omitted, defaults to "HUR"
|
|
*/
|
|
async recordGive(
|
|
giverDid: string | null,
|
|
recipientDid: string | null,
|
|
description: string,
|
|
amount: number,
|
|
unitCode: string = "HUR",
|
|
) {
|
|
try {
|
|
// Determine the correct parameters based on entity types
|
|
let fromDid: string | undefined;
|
|
let toDid: string | undefined;
|
|
let fulfillsProjectHandleId: string | undefined;
|
|
let providerPlanHandleId: string | undefined;
|
|
|
|
if (
|
|
this.giverEntityType === "project" &&
|
|
this.recipientEntityType === "person"
|
|
) {
|
|
// Project-to-person gift
|
|
fromDid = undefined; // No person giver
|
|
toDid = recipientDid as string; // Person recipient
|
|
fulfillsProjectHandleId = undefined; // No project recipient
|
|
providerPlanHandleId = this.giver?.handleId; // Project giver
|
|
} else if (
|
|
this.giverEntityType === "person" &&
|
|
this.recipientEntityType === "project"
|
|
) {
|
|
// Person-to-project gift
|
|
fromDid = giverDid as string; // Person giver
|
|
toDid = undefined; // No person recipient
|
|
fulfillsProjectHandleId = this.toProjectId; // Project recipient
|
|
providerPlanHandleId = undefined; // No project giver
|
|
} else {
|
|
// Person-to-person gift
|
|
fromDid = giverDid as string;
|
|
toDid = recipientDid as string;
|
|
fulfillsProjectHandleId = undefined;
|
|
providerPlanHandleId = undefined;
|
|
}
|
|
|
|
const result = await createAndSubmitGive(
|
|
this.axios,
|
|
this.apiServer,
|
|
this.activeDid,
|
|
fromDid,
|
|
toDid,
|
|
description,
|
|
amount,
|
|
unitCode,
|
|
fulfillsProjectHandleId,
|
|
this.offerId,
|
|
false,
|
|
undefined,
|
|
providerPlanHandleId,
|
|
);
|
|
|
|
if (!result.success) {
|
|
const errorMessage = this.getGiveCreationErrorMessage(result);
|
|
logger.error("Error with give creation result:", result);
|
|
this.safeNotify.error(
|
|
errorMessage || "There was an error creating the give.",
|
|
TIMEOUTS.MODAL,
|
|
);
|
|
} else {
|
|
this.safeNotify.success("That gift was recorded.", TIMEOUTS.VERY_LONG);
|
|
|
|
// Show seed phrase backup reminder if needed
|
|
try {
|
|
const settings = await this.$accountSettings();
|
|
showSeedPhraseReminder(!!settings.hasBackedUpSeed, this.$notify);
|
|
} catch (error) {
|
|
logger.error("Error checking seed backup status:", error);
|
|
}
|
|
|
|
if (this.callbackOnSuccess) {
|
|
this.callbackOnSuccess(amount);
|
|
}
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
} catch (error: any) {
|
|
logger.error("Error with give recordation caught:", error);
|
|
const errorMessage =
|
|
error.userMessage ||
|
|
serverMessageForUser(error) ||
|
|
"There was an error recording the give.";
|
|
this.safeNotify.error(errorMessage, TIMEOUTS.MODAL);
|
|
}
|
|
}
|
|
|
|
// Helper functions for readability
|
|
|
|
/**
|
|
* @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
|
|
getGiveCreationErrorMessage(result: any) {
|
|
return (
|
|
result.error?.userMessage ||
|
|
result.error?.error ||
|
|
result.response?.data?.error?.message
|
|
);
|
|
}
|
|
|
|
explainData() {
|
|
this.safeNotify.info(libsUtil.PRIVACY_MESSAGE, TIMEOUTS.MODAL);
|
|
}
|
|
|
|
selectGiver(contact?: Contact) {
|
|
if (contact) {
|
|
this.giver = {
|
|
did: contact.did,
|
|
name: contact.name,
|
|
};
|
|
} else {
|
|
// Only set to "Unnamed" if no giver is currently set
|
|
if (!this.giver || !this.giver.did) {
|
|
this.giver = {
|
|
did: "",
|
|
name: UNNAMED_ENTITY_NAME,
|
|
};
|
|
}
|
|
}
|
|
this.firstStep = false;
|
|
}
|
|
|
|
goBackToStep1(step: string) {
|
|
this.stepType = step;
|
|
this.firstStep = true;
|
|
}
|
|
|
|
moveToStep2() {
|
|
this.firstStep = false;
|
|
}
|
|
|
|
/**
|
|
* Load projects from the API
|
|
* @param beforeId - Optional rowId for pagination (loads projects before this ID)
|
|
*/
|
|
async loadProjects(beforeId?: string) {
|
|
try {
|
|
let url = this.apiServer + "/api/v2/report/plans";
|
|
if (beforeId) {
|
|
url += `?beforeId=${encodeURIComponent(beforeId)}`;
|
|
}
|
|
const response = await fetch(url, {
|
|
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) {
|
|
// Ensure rowId is included in project data
|
|
const newProjects = results.data.map(
|
|
(plan: PlanData & { rowId?: string }) => ({
|
|
...plan,
|
|
rowId: plan.rowId,
|
|
}),
|
|
);
|
|
|
|
if (beforeId) {
|
|
// Pagination: append new projects
|
|
this.projects.push(...newProjects);
|
|
} else {
|
|
// Initial load: replace array
|
|
this.projects = newProjects;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
logger.error("Error loading projects:", error);
|
|
this.safeNotify.error("Failed to load projects", TIMEOUTS.STANDARD);
|
|
// Don't clear existing projects if this was a pagination request
|
|
if (!beforeId) {
|
|
this.projects = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle loading more projects when EntityGrid reaches the end
|
|
* Called by EntitySelectionStep via loadMoreCallback
|
|
* @param entities - Current array of projects
|
|
*/
|
|
async handleLoadMoreProjects(
|
|
entities: Array<{
|
|
handleId: string;
|
|
rowId?: string;
|
|
}>,
|
|
): Promise<void> {
|
|
if (entities.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const lastProject = entities[entities.length - 1];
|
|
if (!lastProject.rowId) {
|
|
// No rowId means we can't paginate - likely end of data
|
|
return;
|
|
}
|
|
|
|
await this.loadProjects(lastProject.rowId);
|
|
}
|
|
|
|
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.firstStep = false;
|
|
}
|
|
|
|
selectRecipient(contact?: Contact) {
|
|
if (contact) {
|
|
this.receiver = {
|
|
did: contact.did,
|
|
name: contact.name,
|
|
};
|
|
} else {
|
|
// Only set to "Unnamed" if no receiver is currently set
|
|
if (!this.receiver || !this.receiver.did) {
|
|
this.receiver = {
|
|
did: "",
|
|
name: UNNAMED_ENTITY_NAME,
|
|
};
|
|
}
|
|
}
|
|
this.firstStep = false;
|
|
}
|
|
|
|
selectRecipientProject(project: PlanData) {
|
|
this.receiver = {
|
|
did: project.handleId,
|
|
name: project.name,
|
|
image: project.image,
|
|
handleId: project.handleId,
|
|
};
|
|
this.firstStep = false;
|
|
}
|
|
|
|
// Computed property for the query parameters
|
|
get giftedDetailsQuery() {
|
|
return {
|
|
amountInput: this.amountInput,
|
|
description: this.description,
|
|
giverDid: this.giverEntityType === "person" ? this.giver?.did : undefined,
|
|
giverName: this.giver?.name,
|
|
offerId: this.offerId,
|
|
fulfillsProjectId:
|
|
this.recipientEntityType === "project" ? this.toProjectId : undefined,
|
|
providerProjectId:
|
|
this.giverEntityType === "project"
|
|
? this.giver?.handleId
|
|
: this.fromProjectId,
|
|
recipientDid:
|
|
this.recipientEntityType === "person" ? this.receiver?.did : undefined,
|
|
recipientName: this.receiver?.name,
|
|
unitCode: this.unitCode,
|
|
};
|
|
}
|
|
|
|
// New event handlers for component integration
|
|
|
|
/**
|
|
* Handle entity selection from EntitySelectionStep
|
|
* @param entity - The selected entity (person or project) with stepType
|
|
*/
|
|
handleEntitySelected(entity: {
|
|
type: "person" | "project";
|
|
data: Contact | PlanData;
|
|
stepType: string;
|
|
}) {
|
|
if (entity.type === "person") {
|
|
const contact = entity.data as Contact;
|
|
// Apply DID-based logic for person entities
|
|
const processedContact = this.processPersonEntity(contact);
|
|
if (entity.stepType === "giver") {
|
|
this.selectGiver(processedContact);
|
|
} else {
|
|
this.selectRecipient(processedContact);
|
|
}
|
|
} else if (entity.type === "project") {
|
|
const project = entity.data as PlanData;
|
|
if (entity.stepType === "giver") {
|
|
this.selectProject(project);
|
|
} else {
|
|
this.selectRecipientProject(project);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Processes person entities using DID-based logic for "You" and "Unnamed"
|
|
*/
|
|
private processPersonEntity(contact: Contact): Contact {
|
|
if (contact.did === this.activeDid) {
|
|
// If DID matches active DID, create "You" entity
|
|
return { ...contact, name: "You" };
|
|
} else if (!contact.did || contact.did === "") {
|
|
// If DID is empty/null, create "Unnamed" entity
|
|
return { ...contact, name: UNNAMED_ENTITY_NAME };
|
|
} else {
|
|
// Return the contact as-is
|
|
return contact;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle edit entity request from GiftDetailsStep
|
|
* @param data - Object containing entityType and currentEntity
|
|
*/
|
|
handleEditEntity(data: {
|
|
entityType: string;
|
|
currentEntity: { did: string; name: string };
|
|
}) {
|
|
this.goBackToStep1(data.entityType);
|
|
}
|
|
|
|
/**
|
|
* Handle form submission from GiftDetailsStep
|
|
*/
|
|
handleSubmit() {
|
|
this.confirm();
|
|
}
|
|
|
|
/**
|
|
* Handle amount update from GiftDetailsStep
|
|
*/
|
|
handleAmountUpdate(newAmount: number) {
|
|
logger.debug("[GiftedDialog] handleAmountUpdate() called", {
|
|
oldAmount: this.amountInput,
|
|
newAmount,
|
|
});
|
|
this.amountInput = newAmount.toString();
|
|
logger.debug("[GiftedDialog] handleAmountUpdate() - amountInput updated", {
|
|
amountInput: this.amountInput,
|
|
});
|
|
}
|
|
|
|
created() {
|
|
// Initialize notify helpers when component is created
|
|
if (this.$notify) {
|
|
this.notify = createNotifyHelpers(this.$notify);
|
|
}
|
|
}
|
|
|
|
mounted() {
|
|
// Ensure notify helpers are initialized if not already done
|
|
if (!this.notify && this.$notify) {
|
|
this.notify = createNotifyHelpers(this.$notify);
|
|
}
|
|
}
|
|
}
|
|
</script>
|