import { useState } from 'react'
import Icon from './Icon'
/** Vertikales Feld-Layout: Label oben, Input darunter — passt in schmale Panels. */
function Field({ label, hint, children }) {
return (
{label}
{children}
{hint && (
{hint}
)}
)
}
/** Toggle-Reihe: Checkbox + Label inline, Hint darunter wenn vorhanden. */
function Toggle({ label, checked, onChange, hint }) {
return (
{hint && (
{hint}
)}
)
}
export default function GeschossSettingsDialog({ geschoss, onSave, onClose, embedded = false }) {
const [draft, setDraft] = useState({ ...geschoss })
const set = (patch) => setDraft({ ...draft, ...patch })
const isG = !!draft.isGeschoss
const isSchnitt = draft.type === 'schnitt'
const hoehe = draft.hoehe ?? 3.0
const schnitt = draft.schnitthoehe ?? 1.0
const hasClip = !!draft.hasClipping
const okff = draft.okff ?? 0
const clipZ = (okff + schnitt).toFixed(2)
// Schnitt-Felder
const cutAtLine = draft.cutAtLine !== false // default true = Schnitt
const depthBack = draft.depthBack ?? 8.0
const heightMin = draft.heightMin ?? -1.0
const heightMax = draft.heightMax ?? 12.0
const dirSign = draft.dirSign ?? 1
// embedded=true: in einem Satelliten-Fenster gerendert — kein Backdrop,
// keine Width-Constraint, fuellt das ganze WebView.
const Wrapper = embedded ? 'div' : 'div'
const wrapperStyle = embedded ? {
width: '100%', height: '100%',
background: 'var(--bg-dialog)',
display: 'flex', flexDirection: 'column',
overflow: 'hidden',
} : {
position: 'absolute', inset: 0, zIndex: 150,
background: 'var(--bg-overlay)',
display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
paddingTop: 30,
}
const innerStyle = embedded ? {
width: '100%', height: '100%',
display: 'flex', flexDirection: 'column',
overflow: 'hidden',
} : {
background: 'var(--bg-dialog)',
border: '1px solid var(--border)',
borderRadius: 'var(--r-lg)',
boxShadow: 'var(--shadow-3)',
width: 'calc(100% - 16px)', maxWidth: 280,
display: 'flex', flexDirection: 'column',
overflow: 'hidden',
}
return (
{/* Header */}
{geschoss.name}
{/* Body */}
set({ name: ev.target.value })}
style={{ flex: 1, fontSize: 11, fontWeight: 600, minWidth: 0 }}
/>
{/* Geschoss-Toggle nur fuer non-schnitt Eintraege — Schnitt-Type
ist exklusiv (kein Geschoss zugleich). */}
{!isSchnitt && (
set({ isGeschoss: v })}
hint={isG ? 'Höhe & Clipping verfügbar' : 'reines Zeichenblatt'}
/>
)}
{isSchnitt && (
<>
set({ cutAtLine: v })}
hint={cutAtLine
? 'Schnitt: alles vor der Schnittlinie wird weggeschnitten'
: 'Ansicht: nur Tiefenbegrenzung hinten, kein Front-Cut'}
/>
set({ depthBack: parseFloat(ev.target.value) || 8.0 })}
style={{ flex: 1, fontSize: 11, textAlign: 'right', minWidth: 0 }}
/>
set({ heightMin: parseFloat(ev.target.value) })}
style={{ flex: 1, fontSize: 11, textAlign: 'right', minWidth: 0 }}
/>
set({ heightMax: parseFloat(ev.target.value) })}
style={{ flex: 1, fontSize: 11, textAlign: 'right', minWidth: 0 }}
/>
>
)}
{isG && !isSchnitt && (
<>
set({ hoehe: parseFloat(ev.target.value) || hoehe })}
style={{ flex: 1, fontSize: 11, textAlign: 'right', minWidth: 0 }}
/>
set({ schnitthoehe: parseFloat(ev.target.value) || 1.0 })}
style={{ flex: 1, fontSize: 11, textAlign: 'right', minWidth: 0 }}
/>
set({ hasClipping: v })}
hint={
hasClip
? `Horizontaler Schnitt bei +${clipZ}m (OKFF + Schnitthöhe). Sichtbar in der Top-Ansicht wenn dieses Geschoss aktiv ist.`
: 'aus'
}
/>
>
)}
set({ projectZeroMum: parseFloat(ev.target.value) || 0 })}
style={{ flex: 1, fontSize: 11, textAlign: 'right', minWidth: 0,
fontFamily: 'var(--font-mono)' }}
/>
{/* Footer */}
)
}