timesafari
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.
 
 
 

135 lines
3.4 KiB

/** * SpecialEntityCard.vue - Special entity display component * * Extracted
from GiftedDialog.vue to handle special entities like "You" * and "Unnamed" with
conflict detection and selection capability. * * @author Matthew Raymer */
<template>
<li :class="cardClasses" @click="handleClick">
<font-awesome :icon="icon" :class="iconClasses" />
<h3 :class="nameClasses">
{{ label }}
</h3>
</li>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator";
import { Emit } from "vue-facing-decorator";
/**
* SpecialEntityCard - Displays special entities with selection capability
*
* Features:
* - Displays special entities like "You" and "Unnamed"
* - Shows appropriate FontAwesome icons
* - Handles conflict states and selection
* - Emits selection events with entity data
* - Configurable styling based on entity type
*/
@Component({
emits: ["entity-selected"],
})
export default class SpecialEntityCard extends Vue {
/** Type of special entity */
@Prop({ required: true })
entityType!: "you" | "unnamed";
/** Display label for the entity */
@Prop({ required: true })
label!: string;
/** FontAwesome icon name */
@Prop({ required: true })
icon!: string;
/** Whether this entity can be selected */
@Prop({ default: true })
selectable!: boolean;
/** Whether selecting this entity would create a conflict */
@Prop({ default: false })
conflicted!: boolean;
/** Entity data to emit when selected */
@Prop({ required: true })
entityData!: { did?: string; name: string };
/**
* Computed CSS classes for the card container
*/
get cardClasses(): string {
const baseClasses = "block";
if (!this.selectable || this.conflicted) {
return `${baseClasses} cursor-not-allowed opacity-50`;
}
return `${baseClasses} cursor-pointer`;
}
/**
* Computed CSS classes for the icon
*/
get iconClasses(): string {
const baseClasses = "text-5xl mb-1";
if (this.conflicted) {
return `${baseClasses} text-slate-400`;
}
// Different colors for different entity types
switch (this.entityType) {
case "you":
return `${baseClasses} text-blue-500`;
case "unnamed":
return `${baseClasses} text-slate-400`;
default:
return `${baseClasses} text-slate-400`;
}
}
/**
* Computed CSS classes for the entity name/label
*/
get nameClasses(): string {
const baseClasses =
"text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden";
if (this.conflicted) {
return `${baseClasses} text-slate-400`;
}
// Different colors for different entity types
switch (this.entityType) {
case "you":
return `${baseClasses} text-blue-500`;
case "unnamed":
return `${baseClasses} text-slate-500 italic`;
default:
return `${baseClasses} text-slate-500`;
}
}
/**
* Handle card click - only emit if selectable and not conflicted
*/
handleClick(): void {
if (this.selectable && !this.conflicted) {
this.emitEntitySelected({
type: "special",
entityType: this.entityType,
data: this.entityData,
});
}
}
// Emit methods using @Emit decorator
@Emit("entity-selected")
emitEntitySelected(data: any): any {
return data;
}
}
</script>
<style scoped>
/* Component-specific styles if needed */
</style>