)
}
// ---------------------------------------------------------------------------
export default function OverridesApp() {
const [state, setState] = useState({
enabled: false, rules: [], layers: [], linetypes: [], hatchPatterns: [], presets: [],
activePreset: null, ruleTemplates: [],
})
const [selectedPreset, setSelectedPreset] = useState('')
const [selectedTemplate, setSelectedTemplate] = useState('')
const [ctxMenu, setCtxMenu] = useState(null) // {x, y, ruleId}
useEffect(() => {
onMessage('STATE', (s) => {
setState((prev) => ({ ...prev, ...s }))
// Dropdown synct sich auf das Backend-activePreset nur wenn der wert
// gesetzt ist (z.B. nachdem Topbar eine Kombination geladen hat).
// Wenn activePreset null wird (Rules wurden gerade editiert -> variant C),
// BEHALTEN wir die lokale Auswahl — sonst weiss der Save-Button nicht
// mehr in welche Kombination der User gerade editiert.
if (s && s.activePreset) {
setSelectedPreset(s.activePreset)
}
})
notifyReady()
}, [])
const onPatch = (rule) => updateRule(rule.id, rule)
const onMove = (id, delta) => {
const ids = state.rules.map(r => r.id)
const i = ids.indexOf(id)
const j = i + delta
if (i < 0 || j < 0 || j >= ids.length) return
const next = ids.slice()
next.splice(j, 0, next.splice(i, 1)[0])
reorderRules(next)
}
// Kontextmenue fuer eine Regel — analog Ausschnitte/Ebenen.
const ruleCtxItems = (ruleId) => {
const rule = (state.rules || []).find(r => r.id === ruleId)
if (!rule) return []
const i = state.rules.findIndex(r => r.id === ruleId)
const enabled = rule.enabled !== false
return [
{ label: enabled ? 'Deaktivieren' : 'Aktivieren',
icon: enabled ? 'visibility_off' : 'visibility',
onClick: () => updateRule(ruleId, { ...rule, enabled: !enabled }) },
{ divider: true },
{ label: 'Prio hoeher (nach oben)',
icon: 'arrow_upward', disabled: i <= 0,
onClick: () => onMove(ruleId, -1) },
{ label: 'Prio tiefer (nach unten)',
icon: 'arrow_downward', disabled: i >= state.rules.length - 1,
onClick: () => onMove(ruleId, +1) },
{ divider: true },
{ label: 'Duplizieren',
icon: 'content_copy',
onClick: () => duplicateRule(ruleId) },
{ label: 'Als Vorlage speichern…',
icon: 'bookmark_add',
onClick: () => {
const def = rule.name || 'Vorlage'
const name = window.prompt('Name für Vorlage:', def)
if (!name || !name.trim()) return
saveRuleTemplate(name.trim(), rule)
} },
{ divider: true },
{ label: 'Löschen',
icon: 'delete', danger: true,
onClick: () => {
if (window.confirm(`Regel "${rule.name || '(ohne Name)'}" löschen?`)) deleteRule(ruleId)
} },
]
}
return (
{/* Override-Kombinationen — Dropdown plus kontextabhaengiger Save.
Globaler AN/AUS-Toggle ist jetzt in der Oberleiste, hier ueber-
fluessig. Reapply-Button raus: Backend re-applied automatisch
bei jeder Aenderung. */}
Override-Kombinationen
{/* Neue Regel: leere Regel ODER aus Vorlage. */}
Regeln sind additiv. Bei Konflikt gewinnt die oberste.