You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
6.5 KiB
254 lines
6.5 KiB
/** * EntitySelectionStep.vue - Entity selection step component * * Extracted
|
|
from GiftedDialog.vue to handle the complete step 1 * entity selection interface
|
|
with dynamic labeling and grid display. * * @author Matthew Raymer */
|
|
<template>
|
|
<div id="sectionGiftedGiver">
|
|
<label class="block font-bold mb-4">
|
|
{{ stepLabel }}
|
|
</label>
|
|
|
|
<EntityGrid
|
|
:entity-type="shouldShowProjects ? 'projects' : 'people'"
|
|
:entities="shouldShowProjects ? projects : allContacts"
|
|
:max-items="10"
|
|
:active-did="activeDid"
|
|
:all-my-dids="allMyDids"
|
|
:all-contacts="allContacts"
|
|
:conflict-checker="conflictChecker"
|
|
:show-you-entity="shouldShowYouEntity"
|
|
:you-selectable="youSelectable"
|
|
:show-all-route="showAllRoute"
|
|
:show-all-query-params="showAllQueryParams"
|
|
@entity-selected="handleEntitySelected"
|
|
/>
|
|
|
|
<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-lg"
|
|
@click="handleCancel"
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Prop, Vue, Emit } from "vue-facing-decorator";
|
|
import EntityGrid from "./EntityGrid.vue";
|
|
import { Contact } from "../db/tables/contacts";
|
|
import { PlanData } from "../interfaces/records";
|
|
|
|
/**
|
|
* Entity data interface for giver/receiver
|
|
*/
|
|
interface EntityData {
|
|
did?: string;
|
|
handleId?: string;
|
|
name?: string;
|
|
image?: string;
|
|
}
|
|
|
|
/**
|
|
* Entity selection event data structure
|
|
*/
|
|
interface EntitySelectionEvent {
|
|
type: "person" | "project" | "special";
|
|
entityType?: string;
|
|
data: Contact | PlanData | EntityData;
|
|
}
|
|
|
|
/**
|
|
* EntitySelectionStep - Complete step 1 entity selection interface
|
|
*
|
|
* Features:
|
|
* - Dynamic step labeling based on context
|
|
* - EntityGrid integration for unified entity display
|
|
* - Conflict detection and prevention
|
|
* - Special entity handling (You, Unnamed)
|
|
* - Show All navigation with context preservation
|
|
* - Cancel functionality
|
|
* - Event delegation for entity selection
|
|
*/
|
|
@Component({
|
|
components: {
|
|
EntityGrid,
|
|
},
|
|
})
|
|
export default class EntitySelectionStep extends Vue {
|
|
/** Type of step: 'giver' or 'recipient' */
|
|
@Prop({ required: true })
|
|
stepType!: "giver" | "recipient";
|
|
|
|
/** Type of giver entity: 'person' or 'project' */
|
|
@Prop({ required: true })
|
|
giverEntityType!: "person" | "project";
|
|
|
|
/** Type of recipient entity: 'person' or 'project' */
|
|
@Prop({ required: true })
|
|
recipientEntityType!: "person" | "project";
|
|
|
|
/** Whether to show projects instead of people */
|
|
@Prop({ default: false })
|
|
showProjects!: boolean;
|
|
|
|
/** Whether this is from a project view */
|
|
@Prop({ default: false })
|
|
isFromProjectView!: boolean;
|
|
|
|
/** Array of available projects */
|
|
@Prop({ required: true })
|
|
projects!: PlanData[];
|
|
|
|
/** Array of available contacts */
|
|
@Prop({ required: true })
|
|
allContacts!: Contact[];
|
|
|
|
/** Active user's DID */
|
|
@Prop({ required: true })
|
|
activeDid!: string;
|
|
|
|
/** All user's DIDs */
|
|
@Prop({ required: true })
|
|
allMyDids!: string[];
|
|
|
|
/** Function to check if a DID would create a conflict */
|
|
@Prop({ required: true })
|
|
conflictChecker!: (did: string) => boolean;
|
|
|
|
/** Project ID for context (giver) */
|
|
@Prop({ default: "" })
|
|
fromProjectId!: string;
|
|
|
|
/** Project ID for context (recipient) */
|
|
@Prop({ default: "" })
|
|
toProjectId!: string;
|
|
|
|
/** Current giver entity for context */
|
|
@Prop()
|
|
giver?: EntityData | null;
|
|
|
|
/** Current receiver entity for context */
|
|
@Prop()
|
|
receiver?: EntityData | null;
|
|
|
|
/**
|
|
* Computed step label based on context
|
|
*/
|
|
get stepLabel(): string {
|
|
if (this.stepType === "recipient") {
|
|
return "Choose who received the gift:";
|
|
} else if (this.showProjects) {
|
|
return "Choose a project benefitted from:";
|
|
} else {
|
|
return "Choose a person received from:";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Whether to show projects in the grid
|
|
*/
|
|
get shouldShowProjects(): boolean {
|
|
return (
|
|
(this.stepType === "giver" && this.giverEntityType === "project") ||
|
|
(this.stepType === "recipient" && this.recipientEntityType === "project")
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Whether to show the "You" entity
|
|
*/
|
|
get shouldShowYouEntity(): boolean {
|
|
return (
|
|
this.stepType === "recipient" ||
|
|
(this.stepType === "giver" && this.isFromProjectView)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Whether the "You" entity is selectable
|
|
*/
|
|
get youSelectable(): boolean {
|
|
return !this.conflictChecker(this.activeDid);
|
|
}
|
|
|
|
/**
|
|
* Route name for "Show All" navigation
|
|
*/
|
|
get showAllRoute(): string {
|
|
if (this.shouldShowProjects) {
|
|
return "discover";
|
|
} else if (this.allContacts.length > 0) {
|
|
return "contact-gift";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* Query parameters for "Show All" navigation
|
|
*/
|
|
get showAllQueryParams(): Record<string, string> {
|
|
if (this.shouldShowProjects) {
|
|
return {};
|
|
}
|
|
|
|
return {
|
|
stepType: this.stepType,
|
|
giverEntityType: this.giverEntityType,
|
|
recipientEntityType: this.recipientEntityType,
|
|
...(this.stepType === "giver"
|
|
? {
|
|
recipientProjectId: this.toProjectId || "",
|
|
recipientProjectName: this.receiver?.name || "",
|
|
recipientProjectImage: this.receiver?.image || "",
|
|
recipientProjectHandleId: this.receiver?.handleId || "",
|
|
recipientDid: this.receiver?.did || "",
|
|
}
|
|
: {
|
|
giverProjectId: this.fromProjectId || "",
|
|
giverProjectName: this.giver?.name || "",
|
|
giverProjectImage: this.giver?.image || "",
|
|
giverProjectHandleId: this.giver?.handleId || "",
|
|
giverDid: this.giver?.did || "",
|
|
}),
|
|
fromProjectId: this.fromProjectId,
|
|
toProjectId: this.toProjectId,
|
|
showProjects: this.showProjects.toString(),
|
|
isFromProjectView: this.isFromProjectView.toString(),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Handle entity selection from EntityGrid
|
|
*/
|
|
handleEntitySelected(event: EntitySelectionEvent): void {
|
|
this.emitEntitySelected({
|
|
stepType: this.stepType,
|
|
...event,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handle cancel button click
|
|
*/
|
|
handleCancel(): void {
|
|
this.emitCancel();
|
|
}
|
|
|
|
// Emit methods using @Emit decorator
|
|
|
|
@Emit("entity-selected")
|
|
emitEntitySelected(
|
|
data: EntitySelectionEvent & { stepType: string },
|
|
): EntitySelectionEvent & { stepType: string } {
|
|
return data;
|
|
}
|
|
|
|
@Emit("cancel")
|
|
emitCancel(): void {
|
|
// No return value needed
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Component-specific styles if needed */
|
|
</style>
|
|
|