eb04a658b8
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { Group, Rect } from "react-konva";
|
|
import type { Shape } from "../types";
|
|
|
|
export type Outline = "normal" | "selected" | "valid" | "invalid" | "flagged" | "highlight";
|
|
|
|
const STROKE: Record<Outline, string> = {
|
|
normal: "#3b3b3b",
|
|
selected: "#1c7ed6",
|
|
flagged: "#f08c00",
|
|
highlight: "#d6336c",
|
|
valid: "#2f9e44",
|
|
invalid: "#e03131",
|
|
};
|
|
|
|
interface Props {
|
|
shape: Shape;
|
|
width: number; // meters
|
|
height: number;
|
|
pxPerM: number;
|
|
outline: Outline;
|
|
opacity?: number;
|
|
}
|
|
|
|
/** Top-down shape drawn at local (0,0). Position is set by the parent Group. */
|
|
export function FurnitureShape({ shape, width, height, pxPerM, outline, opacity = 1 }: Props) {
|
|
const w = width * pxPerM;
|
|
const h = height * pxPerM;
|
|
const stroke = STROKE[outline];
|
|
const strokeWidth = outline === "normal" ? 1.5 : 3;
|
|
|
|
if (shape === "screen") {
|
|
const inset = Math.min(3, h / 4);
|
|
return (
|
|
<Group opacity={opacity}>
|
|
<Rect width={w} height={h} fill="#2d3748" stroke={stroke} strokeWidth={strokeWidth} cornerRadius={2} />
|
|
<Rect x={inset} y={inset} width={Math.max(0, w - inset * 2)} height={Math.max(0, h - inset * 2)} fill="#63b3ed" listening={false} />
|
|
</Group>
|
|
);
|
|
}
|
|
if (shape === "table") {
|
|
return (
|
|
<Group opacity={opacity}>
|
|
<Rect width={w} height={h} fill="#d9b382" stroke={stroke} strokeWidth={strokeWidth} cornerRadius={3} />
|
|
</Group>
|
|
);
|
|
}
|
|
const bar = Math.max(4, h * 0.2);
|
|
return (
|
|
<Group opacity={opacity}>
|
|
<Rect width={w} height={h} fill="#8fb4d9" stroke={stroke} strokeWidth={strokeWidth} cornerRadius={3} />
|
|
<Rect width={w} height={bar} fill="#4a6f96" cornerRadius={[3, 3, 0, 0]} listening={false} />
|
|
</Group>
|
|
);
|
|
}
|