This commit is contained in:
Andras Schmelczer 2026-09-11 22:14:24 +01:00
commit 0c0f08b350

View file

@ -1,11 +1,20 @@
import { useId } from 'react';
import type { FlooringPlan, Geometry, Point, Room, SkirtingPlan, WallEdge } from '../lib/types';
import type {
FlooringPlan,
Geometry,
PlanMaterial,
Point,
Room,
SkirtingPlan,
WallEdge,
} from '../lib/types';
import { area, cutMm, mm } from '../lib/format';
import { signedArea } from '../lib/geometry';
import { isSkirtingCut } from '../lib/cut-list';
import { skirtingPolygon } from '../lib/skirting-polygon';
import { dimensionLabels, wallDimensionBox } from '../lib/dimension-labels';
import { floorPieceLabels } from '../lib/piece-labels';
import { PRECISION } from '../lib/limits';
import type { DimensionLabel, LabelBox } from '../lib/dimension-labels';
const points = (path: Point[]) => path.map((p) => `${p.x},${p.y}`).join(' ');
@ -61,7 +70,10 @@ function Wall({ edge, span, label }: { edge: WallEdge; span: number; label: Dime
</text>
</g>
{edge.doors
.filter((d) => d.offset >= 0 && d.width > 0 && d.offset + d.width <= edge.length + 0.001)
.filter(
(d) =>
d.offset >= 0 && d.width > 0 && d.offset + d.width <= edge.length + PRECISION.clipping,
)
.map((door) => {
const a = {
x: edge.start.x + (dx / length) * door.offset,
@ -116,6 +128,7 @@ interface Props {
completedBoards?: string[];
highlightedPieces?: string[];
searchActive?: boolean;
material?: PlanMaterial;
}
export function FloorPlan({
@ -129,6 +142,7 @@ export function FloorPlan({
completedBoards = [],
highlightedPieces = [],
searchActive = false,
material,
}: Props) {
const hatch = useId().replaceAll(':', '');
const allPoints = geometry.edges.flatMap((edge) => [edge.start, edge.end]);
@ -139,8 +153,11 @@ export function FloorPlan({
const span = Math.max(maxX - minX, maxY - minY, 1000),
font = span * 0.024;
const orientation = Math.sign(signedArea(geometry.vertices)) || 1;
const floorPieces = flooring.pieces.filter((p) => p.roomId === room.id);
const skirtPieces = skirting.pieces.filter((p) => p.roomId === room.id);
// Printing includes both materials; the interactive drawing shows the chosen view.
const floorPieces =
material === 'skirting' ? [] : flooring.pieces.filter((p) => p.roomId === room.id);
const skirtPieces =
material === 'flooring' ? [] : skirting.pieces.filter((p) => p.roomId === room.id);
const skirtLabels = new Map<string, Point & { width: number; text: string }>();
const reserved: LabelBox[] = [];
for (const piece of skirtPieces) {
@ -197,20 +214,25 @@ export function FloorPlan({
className="drawing-card"
aria-label="Floor plan preview"
data-search-active={searchActive}
data-view={material ?? 'both'}
>
<div className="drawing-header">
<h2>
{room.name} <small>{area(geometry.area)} m²</small>
</h2>
<div className="drawing-legend">
<span>
<i className="floor-key" />
Flooring cuts
</span>
<span>
<i className="skirt-key" />
Skirting cuts
</span>
{material !== 'skirting' && (
<span>
<i className="floor-key" />
Flooring cuts
</span>
)}
{material !== 'flooring' && (
<span>
<i className="skirt-key" />
Skirting cuts
</span>
)}
<span>
<i className="uncut-key" />
Uncut
@ -331,8 +353,7 @@ export function FloorPlan({
const done = completedBoards.includes(`skirting:${piece.stockId}`);
const highlighted = highlightedPieces.includes(piece.id);
// Each template uses its true wall-facing and room-facing edges, including mitres.
const thickness = piece.template ? Math.max(...piece.template.map((p) => p.y)) : 0;
const polygon = skirtingPolygon(piece, thickness, orientation);
const polygon = skirtingPolygon(piece, orientation);
return (
<g
key={piece.id}