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.
148 lines
3.6 KiB
148 lines
3.6 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. * * @author Matthew Raymer */
|
|
<template>
|
|
<component
|
|
:is="editable ? 'button' : 'div'"
|
|
class="flex-1 flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2"
|
|
@click="handleClick"
|
|
>
|
|
<!-- Entity Icon/Avatar -->
|
|
<div>
|
|
<template v-if="entityType === 'project'">
|
|
<ProjectIcon
|
|
v-if="entity?.handleId"
|
|
:entity-id="entity.handleId"
|
|
:icon-size="32"
|
|
:image-url="entity.image"
|
|
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
|
|
/>
|
|
</template>
|
|
<template v-else>
|
|
<EntityIcon
|
|
v-if="entity?.did"
|
|
:contact="entity"
|
|
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="font-semibold truncate">
|
|
{{ entity?.name || "Unnamed" }}
|
|
</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, Emit } from "vue-facing-decorator";
|
|
import EntityIcon from "./EntityIcon.vue";
|
|
import ProjectIcon from "./ProjectIcon.vue";
|
|
import { Contact } from "../db/tables/contacts";
|
|
|
|
/**
|
|
* 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
|
|
* - Emits edit events when clicked and editable
|
|
* - Supports both person and project entity types
|
|
*/
|
|
@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;
|
|
|
|
/**
|
|
* Computed CSS classes for the edit/lock icon
|
|
*/
|
|
get iconClasses(): string {
|
|
return this.editable ? "text-blue-500" : "text-slate-400";
|
|
}
|
|
|
|
/**
|
|
* Handle click event - only emit if editable
|
|
*/
|
|
handleClick(): void {
|
|
if (this.editable) {
|
|
this.emitEditRequested({
|
|
entityType: this.entityType,
|
|
entity: this.entity,
|
|
});
|
|
}
|
|
}
|
|
|
|
// Emit methods using @Emit decorator
|
|
|
|
@Emit("edit-requested")
|
|
emitEditRequested(data: {
|
|
entityType: string;
|
|
entity: EntityData | Contact | null;
|
|
}): { entityType: string; entity: EntityData | Contact | null } {
|
|
return data;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Ensure button styling is consistent */
|
|
button {
|
|
cursor: pointer;
|
|
}
|
|
|
|
button:hover {
|
|
background-color: #f1f5f9; /* hover:bg-slate-100 */
|
|
}
|
|
|
|
div {
|
|
cursor: default;
|
|
}
|
|
</style>
|
|
|