'use client' /** * Strukturierter Editor fuer JSONB-Conditions: * { kind: 'all'|'any', clauses: [{field, op, value}] } * * Wird im RuleEditor verwendet. Reine Praesentations-Komponente — Parent * verwaltet State. */ import type { ClauseOperator, RuleClause, RuleCondition, } from '../_types' import { OPERATOR_LABELS, PROFILE_FIELDS } from '../_types' interface Props { value: RuleCondition onChange: (next: RuleCondition) => void readOnly?: boolean } export default function ConditionBuilder({ value, onChange, readOnly }: Props) { const setKind = (kind: 'all' | 'any') => onChange({ ...value, kind }) const setClause = (idx: number, clause: RuleClause) => { const next = [...value.clauses] next[idx] = clause onChange({ ...value, clauses: next }) } const addClause = () => onChange({ ...value, clauses: [ ...value.clauses, { field: PROFILE_FIELDS[0].key, op: 'eq', value: '' }, ], }) const removeClause = (idx: number) => onChange({ ...value, clauses: value.clauses.filter((_, i) => i !== idx) }) return (
Bedingung:
{value.clauses.length === 0 && (
Keine Klauseln — Regel gilt für jedes Profil.
)} {!readOnly && ( )}
) } function ClauseRow({ clause, onChange, readOnly, }: { clause: RuleClause onChange: (c: RuleClause) => void readOnly: boolean }) { const field = PROFILE_FIELDS.find((f) => f.key === clause.field) || PROFILE_FIELDS[0] const operators: ClauseOperator[] = field.type === 'enum' ? ['eq', 'neq', 'in', 'not_in', 'exists', 'truthy', 'falsy'] : field.type === 'boolean' ? ['truthy', 'falsy', 'eq', 'neq'] : field.type === 'number' ? ['eq', 'neq', 'gt', 'gte', 'lt', 'lte'] : ['eq', 'neq', 'in', 'not_in', 'exists'] const requiresValue = !['exists', 'truthy', 'falsy'].includes(clause.op) const multiValue = clause.op === 'in' || clause.op === 'not_in' return (
{requiresValue && ( onChange({ ...clause, value: v })} readOnly={readOnly} /> )}
) } function ValueInput({ field, multi, value, onChange, readOnly, }: { field: typeof PROFILE_FIELDS[number] multi: boolean value: unknown onChange: (v: unknown) => void readOnly: boolean }) { if (field.type === 'enum' && field.options) { if (multi) { const selected = Array.isArray(value) ? (value as string[]) : [] return ( ) } return ( ) } if (field.type === 'number') { return ( onChange(Number(e.target.value))} /> ) } if (field.type === 'boolean') { return ( ) } return ( onChange(e.target.value)} /> ) }