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.
		
		
		
		
		
			
		
			
				
					
					
						
							202 lines
						
					
					
						
							5.4 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							202 lines
						
					
					
						
							5.4 KiB
						
					
					
				
								/** * EntitySummaryButton.vue - Displays selected entity with edit capability *
							 | 
						|
								* Extracted from GiftedDialog.vue to handle entity summary display in the gift *
							 | 
						|
								details step with edit functionality. * * Features: * - Shows entity avatar
							 | 
						|
								(person or project) * - Displays entity name and role label * - Handles editable
							 | 
						|
								vs locked states * - Function props for parent control over edit behavior * -
							 | 
						|
								Supports both person and project entity types * - Template streamlined with
							 | 
						|
								computed CSS properties * * @author Matthew Raymer */
							 | 
						|
								<template>
							 | 
						|
								  <component
							 | 
						|
								    :is="editable ? 'button' : 'div'"
							 | 
						|
								    :class="containerClasses"
							 | 
						|
								    @click="handleClick"
							 | 
						|
								  >
							 | 
						|
								    <!-- Entity Icon/Avatar -->
							 | 
						|
								    <div>
							 | 
						|
								      <template v-if="entityType === 'project'">
							 | 
						|
								        <ProjectIcon
							 | 
						|
								          v-if="entity && 'handleId' in entity && entity.handleId"
							 | 
						|
								          :entity-id="entity.handleId"
							 | 
						|
								          :icon-size="32"
							 | 
						|
								          :image-url="'image' in entity ? entity.image : ''"
							 | 
						|
								          class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
							 | 
						|
								        />
							 | 
						|
								      </template>
							 | 
						|
								      <template v-else>
							 | 
						|
								        <EntityIcon
							 | 
						|
								          v-if="entity?.did"
							 | 
						|
								          :entity-id="entity.did"
							 | 
						|
								          :contact="isContactEntity ? entity : undefined"
							 | 
						|
								          class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
							 | 
						|
								        />
							 | 
						|
								        <font-awesome
							 | 
						|
								          v-else
							 | 
						|
								          icon="circle-question"
							 | 
						|
								          class="text-slate-400 text-3xl"
							 | 
						|
								        />
							 | 
						|
								      </template>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- Entity Information -->
							 | 
						|
								    <div class="text-start min-w-0">
							 | 
						|
								      <p class="text-xs text-slate-500 leading-1 -mb-1 uppercase">
							 | 
						|
								        {{ label }}
							 | 
						|
								      </p>
							 | 
						|
								      <h3 :class="nameClasses">
							 | 
						|
								        {{ displayName }}
							 | 
						|
								      </h3>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- Edit/Lock Icon -->
							 | 
						|
								    <p class="ms-auto text-sm pe-1" :class="iconClasses">
							 | 
						|
								      <font-awesome
							 | 
						|
								        :icon="editable ? 'pen' : 'lock'"
							 | 
						|
								        :title="editable ? 'Change' : 'Can\'t be changed'"
							 | 
						|
								      />
							 | 
						|
								    </p>
							 | 
						|
								  </component>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script lang="ts">
							 | 
						|
								import { Component, Prop, Vue } from "vue-facing-decorator";
							 | 
						|
								import EntityIcon from "./EntityIcon.vue";
							 | 
						|
								import ProjectIcon from "./ProjectIcon.vue";
							 | 
						|
								import { Contact } from "../db/tables/contacts";
							 | 
						|
								import { UNNAMED_ENTITY_NAME } from "@/constants/entities";
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Entity interface for both person and project entities
							 | 
						|
								 */
							 | 
						|
								interface EntityData {
							 | 
						|
								  did?: string;
							 | 
						|
								  handleId?: string;
							 | 
						|
								  name?: string;
							 | 
						|
								  image?: string;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * EntitySummaryButton - Displays selected entity with optional edit capability
							 | 
						|
								 *
							 | 
						|
								 * Features:
							 | 
						|
								 * - Shows entity avatar (person or project)
							 | 
						|
								 * - Displays entity name and role label
							 | 
						|
								 * - Handles editable vs locked states
							 | 
						|
								 * - Function props for parent control over edit behavior
							 | 
						|
								 * - Supports both person and project entity types
							 | 
						|
								 * - Template streamlined with computed CSS properties
							 | 
						|
								 */
							 | 
						|
								@Component({
							 | 
						|
								  components: {
							 | 
						|
								    EntityIcon,
							 | 
						|
								    ProjectIcon,
							 | 
						|
								  },
							 | 
						|
								})
							 | 
						|
								export default class EntitySummaryButton extends Vue {
							 | 
						|
								  /** Entity data to display */
							 | 
						|
								  @Prop({ required: true })
							 | 
						|
								  entity!: EntityData | Contact | null;
							 | 
						|
								
							 | 
						|
								  /** Type of entity: 'person' or 'project' */
							 | 
						|
								  @Prop({ required: true })
							 | 
						|
								  entityType!: "person" | "project";
							 | 
						|
								
							 | 
						|
								  /** Display label for the entity role */
							 | 
						|
								  @Prop({ required: true })
							 | 
						|
								  label!: string;
							 | 
						|
								
							 | 
						|
								  /** Whether the entity can be edited */
							 | 
						|
								  @Prop({ default: true })
							 | 
						|
								  editable!: boolean;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * Function prop for handling edit requests
							 | 
						|
								   * Called when the button is clicked and editable, allowing parent to control edit behavior
							 | 
						|
								   */
							 | 
						|
								  @Prop({ type: Function, default: () => {} })
							 | 
						|
								  onEditRequested!: (data: {
							 | 
						|
								    entityType: string;
							 | 
						|
								    entity: EntityData | Contact | null;
							 | 
						|
								  }) => void | Promise<void>;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * CSS classes for the main container
							 | 
						|
								   */
							 | 
						|
								  get containerClasses(): string {
							 | 
						|
								    return "flex-1 flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2";
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * Whether the entity is a Contact object
							 | 
						|
								   */
							 | 
						|
								  get isContactEntity(): boolean {
							 | 
						|
								    return this.entity !== null && "profileImageUrl" in this.entity;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * Computed CSS classes for the edit/lock icon
							 | 
						|
								   */
							 | 
						|
								  get iconClasses(): string {
							 | 
						|
								    return this.editable ? "text-blue-500" : "text-slate-400";
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * Computed CSS classes for the entity name
							 | 
						|
								   */
							 | 
						|
								  get nameClasses(): string {
							 | 
						|
								    const baseClasses = "font-semibold truncate";
							 | 
						|
								
							 | 
						|
								    // Add italic styling for special "Unnamed" or entities without set names
							 | 
						|
								    if (!this.entity?.name || this.entity?.did === "") {
							 | 
						|
								      return `${baseClasses} italic text-slate-500`;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return baseClasses;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * Computed display name for the entity
							 | 
						|
								   */
							 | 
						|
								  get displayName(): string {
							 | 
						|
								    // If the entity has a set name, use that name
							 | 
						|
								    if (this.entity?.name) {
							 | 
						|
								      return this.entity.name;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // If the entity is the special "Unnamed", use "Unnamed"
							 | 
						|
								    if (this.entity?.did === "") {
							 | 
						|
								      return UNNAMED_ENTITY_NAME;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // If the entity does not have a set name, but is not the special "Unnamed", use their DID
							 | 
						|
								    return this.entity?.did;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								   * Handle click event - only call function prop if editable
							 | 
						|
								   * Allows parent to control edit behavior and validation
							 | 
						|
								   */
							 | 
						|
								  handleClick(): void {
							 | 
						|
								    if (this.editable) {
							 | 
						|
								      this.onEditRequested({
							 | 
						|
								        entityType: this.entityType,
							 | 
						|
								        entity: this.entity,
							 | 
						|
								      });
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								
							 | 
						|
								<style scoped>
							 | 
						|
								/* Ensure button styling is consistent */
							 | 
						|
								button {
							 | 
						|
								  cursor: pointer;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								button:hover {
							 | 
						|
								  background-color: #f1f5f9; /* hover:bg-slate-100 */
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								div {
							 | 
						|
								  cursor: default;
							 | 
						|
								}
							 | 
						|
								</style>
							 | 
						|
								
							 |