import React, { useState, useEffect } from 'react' import { Plus, Trash2, X } from 'lucide-react' import { getFieldType } from '../extensions/registry' // Fields that never carry a submitted value (the server skips them), so rules on them could never match. const NO_VALUE_TYPES = new Set(['grid', 'section', 'static-content', 'html', 'image', 'submit', 'submit_button', 'promo-banner', 'trust-badges', 'faq-accordion', 'countdown-banner', 'captcha']) const hasNoValue = (type) => NO_VALUE_TYPES.has(type) || Boolean(getFieldType(type)?.noValue) /** Values a rule can compare against for fields with a fixed value list (matches what the storefront submits). */ export function ruleValueChoices(field) { if (!field) return null // Registered field types list their own values (`ruleValueChoices(field)` → [{ value, label }]). const registered = getFieldType(field.type) if (registered && typeof registered.ruleValueChoices === 'function') return registered.ruleValueChoices(field) || null return null } const ConditionalLogic = ({ enableLogic = false, setEnableLogic, logicConditions = [], setLogicConditions, fields = [], actionLabel = 'this item', onSave, onClose, setIsDirty, logicMatch = 'all', setLogicMatch, logicAction = 'show', setLogicAction, }) => { const [action, setAction] = useState(logicAction || 'show') // Helper function to get all fields including grid fields and nested fields const getAllFieldsIncludingNested = (fieldsList = []) => { const allFields = [] fieldsList.forEach((field) => { // Include regular fields (not grid) if (field.type !== 'grid') { allFields.push({ ...field, displayName: field.label || field.name || 'Unnamed Field', isNested: false, }) } // Include grid fields and their nested columns if (field.type === 'grid') { allFields.push({ ...field, displayName: `${field.label || field.name || 'Grid Section'} (Section)`, isNested: false, }) if (field.columns) { Object.entries(field.columns).forEach(([columnKey, columnFields]) => { if (Array.isArray(columnFields)) { columnFields.forEach((nestedField) => { const columnDisplayName = columnKey .replace(/col-/i, 'Column ') .replace(/column/i, 'Column ') .replace(/(\d+)/, (m) => Number(m) + 1) allFields.push({ ...nestedField, displayName: `${nestedField.label || nestedField.name || 'Unnamed Field'} (${field.label || field.name || 'Grid'} - ${columnDisplayName})`, isNested: true, parentFieldId: field.id, parentFieldName: field.label || field.name || 'Grid', columnKey: columnKey, }) }) } }) } } }) return allFields } // Sync action from props useEffect(() => { if (logicAction) { setAction(logicAction) } }, [logicAction]) const handleEnableLogicChange = (checked) => { if (setIsDirty) setIsDirty(true) if (setEnableLogic) setEnableLogic(checked) if (setLogicConditions) { setLogicConditions( checked ? logicConditions?.length ? logicConditions : [{ field: '', operator: 'is', value: '' }] : [] ) } } const findConditionField = (fieldId) => { if (!fieldId) return null for (const f of fields) { if (f.id === fieldId) return f if (f.type === 'grid' && f.columns) { for (const colFields of Object.values(f.columns)) { if (Array.isArray(colFields)) { const nested = colFields.find((nf) => nf.id === fieldId) if (nested) return nested } } } } return null } return (
{/* Enable Conditional Logic Switch */}
handleEnableLogicChange(!enableLogic)} data-testid="drawer-conditional-logic-banner" > Enable Conditional Logic
{/* Conditional Logic Configuration */} {enableLogic && (
{/* Action & Match Sentence Header */}
{actionLabel} if of the following match:
{/* Conditions List */}
{Array.isArray(logicConditions) && logicConditions.map((condition, index) => { const conditionField = findConditionField(condition.field || condition.fieldId) return (
{/* Field Selector */} {/* Operator Selector */} {/* Dynamic Value Input / Dropdown */} {!['is_empty', 'is_not_empty'].includes(condition.operator) && (
{(() => { if (conditionField && conditionField.type === 'switch') { return ( ) } if ( conditionField && (['select', 'checkbox', 'radio', 'dropdown'].includes(conditionField.type) || getFieldType(conditionField.type)?.ruleOptions) && Array.isArray(conditionField.options) && conditionField.options.length > 0 ) { return ( ) } const fixed = ruleValueChoices(conditionField) if (fixed && fixed.length) { return ( ) } return ( { if (setIsDirty) setIsDirty(true) const updatedConditions = [...logicConditions] updatedConditions[index] = { ...updatedConditions[index], value: e.target.value, } if (setLogicConditions) setLogicConditions(updatedConditions) }} placeholder="Enter value..." /> ) })()}
)} {/* Remove Condition Button */}
) })}
{/* Add New Condition Button */}
)} {/* Save and Close Footer if provided */} {(onSave || onClose) && (
{onClose && ( )} {onSave && ( )}
)}
) } export default ConditionalLogic