landing
All checks were successful
Deploy to Pages / build (push) Successful in 26s

This commit is contained in:
Andras Schmelczer 2026-09-11 20:34:36 +01:00
commit b9485e4097
32 changed files with 4692 additions and 65 deletions

View file

@ -1,10 +1,13 @@
import { ArrowRight, ArrowDown } from 'lucide-react';
import type { Project, Room, FlooringSettings, SkirtingSettings } from '../lib/types';
import { NumberField } from './Fields';
import type { FlooringOptions } from '../lib/flooring';
import { mm } from '../lib/format';
interface Props {
project: Project;
room: Room;
flooringOptions: FlooringOptions;
changeProject: (fn: (p: Project) => Project) => void;
changeRoom: (fn: (r: Room) => Room) => void;
}
@ -12,7 +15,13 @@ interface Props {
const kerfHelp =
'Width of material removed by the saw blade. A 3 mm blade turns a 1,000 mm board into 600 mm + 397 mm after one cut.';
export function MaterialsEditor({ project, room, changeProject, changeRoom }: Props) {
export function MaterialsEditor({
project,
room,
flooringOptions,
changeProject,
changeRoom,
}: Props) {
const f = project.flooring;
const s = project.skirting;
const floor = (key: keyof FlooringSettings, value: number | string) =>
@ -63,6 +72,34 @@ export function MaterialsEditor({ project, room, changeProject, changeRoom }: Pr
</button>
</div>
</div>
{f.pattern === 'random' && (
<div className="field">
<span>Optimise random flooring · all rooms</span>
<div className="optimisation-options" role="group" aria-label="Flooring optimisation">
{(['cuts', 'random'] as const).map((priority) => {
const plan = flooringOptions[priority];
const valid = !plan.issues.some((issue) => issue.severity === 'error');
const selected = (f.optimisation ?? 'cuts') === priority;
return (
<button
key={priority}
type="button"
className={selected ? 'active' : ''}
aria-pressed={selected}
onClick={() => floor('optimisation', priority)}
>
<span>{priority === 'cuts' ? 'Minimise cuts' : 'Maximise randomness'}</span>
<small>
{valid
? `${plan.cuts} cuts · ${mm(plan.wastePercent)}% waste`
: 'Check measurements'}
</small>
</button>
);
})}
</div>
</div>
)}
<div className="field">
<span>Board direction · {room.name}</span>
<div className="segmented" role="group" aria-label="Board direction">