world-simulator / frontend /src /scene /NpcLabelButton.tsx
kikikita's picture
Refactor action handling and update UI elements
81070c7
Raw
History Blame Contribute Delete
2.44 kB
import type { EntitySnapshot } from "../types";
import { roleMeta } from "./characterUtils";
type NpcLabelButtonProps = {
entity: EntitySnapshot;
onSelect: () => void;
};
export function NpcLabelButton({ entity, onSelect }: NpcLabelButtonProps) {
const meta = roleMeta(entity.role);
const isAlive = entity.state.is_alive;
const health = Math.max(0, entity.state.health);
const maxHealth = Math.max(1, entity.state.max_health);
const healthRatio = Math.min(1, health / maxHealth);
const age = entity.state.age;
const maxAge = entity.state.max_age;
const ageRatio =
age !== undefined && maxAge !== undefined && maxAge > 0
? Math.min(1, age / maxAge)
: null;
const countryBadge = (entity.country_id ?? "?").slice(0, 1).toUpperCase();
const statusLabel = entity.special_status ?? meta.label;
return (
<button
type="button"
className={`npcCard ${isAlive ? "" : "npcCardDead"}`}
style={{ borderColor: meta.color }}
onClick={(event) => {
event.stopPropagation();
onSelect();
}}
aria-label={`Select ${entity.label}`}
title={`${entity.label} - ${entity.country_id ?? "no country"}, ${entity.state.intention}`}
>
<span className="npcCardName">
<span className="npcCardIcon" style={{ color: meta.color }} aria-hidden="true">
{isAlive ? meta.icon : "x"}
</span>
<span className="npcCountryBadge" aria-label={`Country ${entity.country_id ?? "unknown"}`}>
{countryBadge}
</span>
<strong>{entity.label}</strong>
</span>
<span className="npcCardRole" style={{ color: meta.color }}>
{statusLabel}
</span>
{isAlive ? (
<>
<span className="npcBar npcHpBar" aria-hidden="true">
<span
className="npcBarFill"
style={{
width: `${healthRatio * 100}%`,
background: healthRatio > 0.5 ? "#6fd96a" : healthRatio > 0.25 ? "#f0c34e" : "#f06a4e",
}}
/>
</span>
{ageRatio !== null ? (
<span className="npcBar npcAgeBar" aria-hidden="true" title={`Age ${age}/${maxAge}`}>
<span className="npcBarFill npcAgeFill" style={{ width: `${ageRatio * 100}%` }} />
</span>
) : null}
</>
) : (
<span className="npcCardRole">dead</span>
)}
</button>
);
}