forked from trent_larson/crowd-funder-for-time-pwa
Replace complex updateEntityTypes() method with explicit giverEntityType and recipientEntityType props. This makes the component more declarative and maintainable by removing hidden logic and making entity type relationships clear at the call site. - Remove updateEntityTypes() method and related watchers - Add explicit giverEntityType and recipientEntityType props with defaults - Update all views to use inline logic for entity type determination - Fix entity type preservation in navigation flows - Enhance query parameter passing for better context preservation - Fix recipient reset issue in ContactGiftingView - Resolve entity type mismatch in HomeView project button flow Files changed: - GiftedDialog.vue: Remove complex logic, add explicit props - EntitySelectionStep.vue: Enhanced query parameter handling - ContactGiftingView.vue: Improved context preservation - HomeView.vue, ProjectViewView.vue, ClaimView.vue, ContactsView.vue: Updated to use explicit entity type props - Add refactoring documentation
324 lines
12 KiB
Vue
324 lines
12 KiB
Vue
<template>
|
|
<QuickNav selected="Home"></QuickNav>
|
|
<!-- CONTENT -->
|
|
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
|
<!-- Breadcrumb -->
|
|
<div id="ViewBreadcrumb" class="mb-8">
|
|
<h1 class="text-2xl text-center font-semibold relative px-7">
|
|
<!-- Back -->
|
|
<router-link
|
|
:to="{ name: 'home' }"
|
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
|
><font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
|
|
</router-link>
|
|
{{ stepType === "giver" ? "Given by..." : "Given to..." }}
|
|
</h1>
|
|
</div>
|
|
|
|
<!-- Results List -->
|
|
<ul class="border-t border-slate-300">
|
|
<li class="border-b border-slate-300 py-3">
|
|
<h2 class="text-base flex gap-4 items-center">
|
|
<span class="grow flex gap-2 items-center font-medium">
|
|
<font-awesome
|
|
icon="circle-question"
|
|
class="text-slate-400 text-4xl"
|
|
/>
|
|
<span class="italic text-slate-400">(Unnamed/Unknown)</span>
|
|
</span>
|
|
<span class="text-right">
|
|
<button
|
|
type="button"
|
|
class="block w-full text-center text-sm uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
|
|
@click="openDialog('Unnamed')"
|
|
>
|
|
<font-awesome icon="gift" class="fa-fw"></font-awesome>
|
|
</button>
|
|
</span>
|
|
</h2>
|
|
</li>
|
|
<li
|
|
v-for="contact in allContacts"
|
|
:key="contact.did"
|
|
class="border-b border-slate-300 py-3"
|
|
>
|
|
<h2 class="text-base flex gap-4 items-center">
|
|
<span class="grow flex gap-2 items-center font-medium">
|
|
<EntityIcon
|
|
:contact="contact"
|
|
:icon-size="34"
|
|
class="inline-block align-middle border border-slate-300 rounded-full overflow-hidden"
|
|
/>
|
|
<span v-if="contact.name">{{ contact.name }}</span>
|
|
<span v-else class="italic text-slate-400">(No name)</span>
|
|
</span>
|
|
<span class="text-right">
|
|
<button
|
|
type="button"
|
|
class="block w-full text-center text-sm uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
|
|
@click="openDialog(contact)"
|
|
>
|
|
<font-awesome icon="gift" class="fa-fw"></font-awesome>
|
|
</button>
|
|
</span>
|
|
</h2>
|
|
</li>
|
|
</ul>
|
|
|
|
<GiftedDialog
|
|
ref="giftedDialog"
|
|
:giver-entity-type="giverEntityType"
|
|
:recipient-entity-type="recipientEntityType"
|
|
:from-project-id="fromProjectId"
|
|
:to-project-id="toProjectId"
|
|
:is-from-project-view="isFromProjectView"
|
|
/>
|
|
</section>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
|
|
|
|
import GiftedDialog from "../components/GiftedDialog.vue";
|
|
import QuickNav from "../components/QuickNav.vue";
|
|
import EntityIcon from "../components/EntityIcon.vue";
|
|
import { NotificationIface } from "../constants/app";
|
|
import { Contact } from "../db/tables/contacts";
|
|
import { GiverReceiverInputInfo } from "../libs/util";
|
|
import { logger } from "../utils/logger";
|
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
|
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
|
@Component({
|
|
components: { GiftedDialog, QuickNav, EntityIcon },
|
|
mixins: [PlatformServiceMixin],
|
|
})
|
|
export default class ContactGiftingView extends Vue {
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
|
$route!: RouteLocationNormalizedLoaded;
|
|
$router!: Router;
|
|
|
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
|
|
|
activeDid = "";
|
|
allContacts: Array<Contact> = [];
|
|
apiServer = "";
|
|
projectId = "";
|
|
prompt = "";
|
|
description = "";
|
|
amountInput = "0";
|
|
unitCode = "HUR";
|
|
recipientProjectName = "";
|
|
recipientProjectImage = "";
|
|
recipientProjectHandleId = "";
|
|
|
|
// New context parameters
|
|
stepType = "giver";
|
|
giverEntityType = "person" as "person" | "project";
|
|
recipientEntityType = "person" as "person" | "project";
|
|
giverProjectId = "";
|
|
giverProjectName = "";
|
|
giverProjectImage = "";
|
|
giverProjectHandleId = "";
|
|
giverDid = "";
|
|
recipientDid = "";
|
|
fromProjectId = "";
|
|
toProjectId = "";
|
|
showProjects = false;
|
|
isFromProjectView = false;
|
|
offerId = "";
|
|
|
|
async created() {
|
|
this.notify = createNotifyHelpers(this.$notify);
|
|
|
|
try {
|
|
const settings = await this.$accountSettings();
|
|
this.apiServer = settings.apiServer || "";
|
|
this.activeDid = settings.activeDid || "";
|
|
|
|
this.allContacts = await this.$getAllContacts();
|
|
|
|
this.projectId =
|
|
(this.$route.query["recipientProjectId"] as string) || "";
|
|
this.recipientProjectName =
|
|
(this.$route.query["recipientProjectName"] as string) || "";
|
|
this.recipientProjectImage =
|
|
(this.$route.query["recipientProjectImage"] as string) || "";
|
|
this.recipientProjectHandleId =
|
|
(this.$route.query["recipientProjectHandleId"] as string) || "";
|
|
this.prompt = (this.$route.query["prompt"] as string) ?? this.prompt;
|
|
this.description = (this.$route.query["description"] as string) || "";
|
|
this.amountInput = (this.$route.query["amountInput"] as string) || "0";
|
|
this.unitCode = (this.$route.query["unitCode"] as string) || "HUR";
|
|
|
|
// Read new context parameters
|
|
this.stepType = (this.$route.query["stepType"] as string) || "giver";
|
|
this.giverEntityType =
|
|
(this.$route.query["giverEntityType"] as "person" | "project") ||
|
|
"person";
|
|
this.recipientEntityType =
|
|
(this.$route.query["recipientEntityType"] as "person" | "project") ||
|
|
"person";
|
|
this.giverProjectId =
|
|
(this.$route.query["giverProjectId"] as string) || "";
|
|
this.giverProjectName =
|
|
(this.$route.query["giverProjectName"] as string) || "";
|
|
this.giverProjectImage =
|
|
(this.$route.query["giverProjectImage"] as string) || "";
|
|
this.giverProjectHandleId =
|
|
(this.$route.query["giverProjectHandleId"] as string) || "";
|
|
this.giverDid = (this.$route.query["giverDid"] as string) || "";
|
|
this.recipientDid = (this.$route.query["recipientDid"] as string) || "";
|
|
this.fromProjectId = (this.$route.query["fromProjectId"] as string) || "";
|
|
this.toProjectId = (this.$route.query["toProjectId"] as string) || "";
|
|
this.showProjects =
|
|
(this.$route.query["showProjects"] as string) === "true";
|
|
this.isFromProjectView =
|
|
(this.$route.query["isFromProjectView"] as string) === "true";
|
|
this.offerId = (this.$route.query["offerId"] as string) || "";
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
} catch (err: any) {
|
|
logger.error("Error retrieving settings & contacts:", err);
|
|
this.notify.error(
|
|
err.message ||
|
|
"There was an error retrieving your settings or contacts.",
|
|
TIMEOUTS.LONG,
|
|
);
|
|
}
|
|
}
|
|
|
|
openDialog(contact?: GiverReceiverInputInfo | "Unnamed") {
|
|
if (contact === "Unnamed") {
|
|
// Special case: Handle "Unnamed" contacts for both givers and recipients
|
|
let recipient: GiverReceiverInputInfo;
|
|
let giver: GiverReceiverInputInfo | undefined;
|
|
|
|
if (this.stepType === "giver") {
|
|
// We're selecting a giver, so recipient is either a project or the current user
|
|
if (this.recipientEntityType === "project") {
|
|
recipient = {
|
|
did: this.recipientProjectHandleId,
|
|
name: this.recipientProjectName,
|
|
image: this.recipientProjectImage,
|
|
handleId: this.recipientProjectHandleId,
|
|
};
|
|
} else {
|
|
recipient = { did: this.activeDid, name: "You" };
|
|
}
|
|
giver = undefined; // Will be set to "Unnamed" in GiftedDialog
|
|
} else {
|
|
// We're selecting a recipient, so recipient is "Unnamed" and giver is preserved from context
|
|
recipient = { did: "", name: "Unnamed" };
|
|
|
|
// Preserve the existing giver from the context
|
|
if (this.giverEntityType === "project") {
|
|
giver = {
|
|
did: this.giverProjectHandleId,
|
|
name: this.giverProjectName,
|
|
image: this.giverProjectImage,
|
|
handleId: this.giverProjectHandleId,
|
|
};
|
|
} else if (this.giverDid) {
|
|
giver = {
|
|
did: this.giverDid,
|
|
name: this.giverProjectName || "Someone",
|
|
};
|
|
} else {
|
|
giver = { did: this.activeDid, name: "You" };
|
|
}
|
|
}
|
|
|
|
(this.$refs.giftedDialog as GiftedDialog).open(
|
|
giver,
|
|
recipient,
|
|
this.offerId,
|
|
this.prompt,
|
|
this.description,
|
|
this.amountInput,
|
|
this.unitCode,
|
|
);
|
|
|
|
// Immediately select "Unnamed" and move to Step 2 based on stepType
|
|
if (this.stepType === "giver") {
|
|
(this.$refs.giftedDialog as GiftedDialog).selectGiver();
|
|
} else {
|
|
(this.$refs.giftedDialog as GiftedDialog).selectRecipient();
|
|
}
|
|
} else {
|
|
// Regular case: contact is a GiverReceiverInputInfo
|
|
let giver: GiverReceiverInputInfo;
|
|
let recipient: GiverReceiverInputInfo;
|
|
|
|
if (this.stepType === "giver") {
|
|
// We're selecting a giver, so the contact becomes the giver
|
|
giver = contact as GiverReceiverInputInfo; // Safe because we know contact is not "Unnamed" or undefined
|
|
|
|
// Preserve the existing recipient from the context
|
|
if (this.recipientEntityType === "project") {
|
|
recipient = {
|
|
did: this.recipientProjectHandleId,
|
|
name: this.recipientProjectName,
|
|
image: this.recipientProjectImage,
|
|
handleId: this.recipientProjectHandleId,
|
|
};
|
|
} else {
|
|
// Check if the preserved recipient was "Unnamed" (empty DID) or a regular contact
|
|
if (this.recipientDid === "") {
|
|
// Recipient was "Unnamed"
|
|
recipient = { did: "", name: "Unnamed" };
|
|
} else if (this.recipientDid) {
|
|
// Recipient was a regular contact
|
|
recipient = {
|
|
did: this.recipientDid,
|
|
name: this.recipientProjectName || "Someone",
|
|
};
|
|
} else {
|
|
// Fallback to current user
|
|
recipient = { did: this.activeDid, name: "You" };
|
|
}
|
|
}
|
|
} else {
|
|
// We're selecting a recipient, so the contact becomes the recipient
|
|
recipient = contact as GiverReceiverInputInfo; // Safe because we know contact is not "Unnamed" or undefined
|
|
|
|
// Preserve the existing giver from the context
|
|
if (this.giverEntityType === "project") {
|
|
giver = {
|
|
did: this.giverProjectHandleId,
|
|
name: this.giverProjectName,
|
|
image: this.giverProjectImage,
|
|
handleId: this.giverProjectHandleId,
|
|
};
|
|
} else {
|
|
// Check if the preserved giver was "Unnamed" (empty DID) or a regular contact
|
|
if (this.giverDid === "") {
|
|
// Giver was "Unnamed"
|
|
giver = { did: "", name: "Unnamed" };
|
|
} else if (this.giverDid) {
|
|
// Giver was a regular contact
|
|
giver = {
|
|
did: this.giverDid,
|
|
name: this.giverProjectName || "Someone",
|
|
};
|
|
} else {
|
|
// Fallback to current user
|
|
giver = { did: this.activeDid, name: "You" };
|
|
}
|
|
}
|
|
}
|
|
|
|
(this.$refs.giftedDialog as GiftedDialog).open(
|
|
giver,
|
|
recipient,
|
|
this.offerId,
|
|
this.prompt,
|
|
this.description,
|
|
this.amountInput,
|
|
this.unitCode,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
</script>
|