From 82ef36b4390ec36d6b38a8c51352d5f45ba461a3 Mon Sep 17 00:00:00 2001 From: Andika Date: Mon, 2 Feb 2026 17:29:03 +0700 Subject: [PATCH] =?UTF-8?q?Conditional=20Rules=20in=20Registration=20Build?= =?UTF-8?q?er=20Fix=201.=20Trigger=20Field=20Selection=20-=20Dropdown=20to?= =?UTF-8?q?=20select=20which=20field=20triggers=20the=20rule=20(filters=20?= =?UTF-8?q?to=20checkbox,=20dropdown,=20radio,=20text=20fields)=202.=20Ope?= =?UTF-8?q?rator=20Selection=20-=20Dropdown=20with=20options:=20=09-=20equ?= =?UTF-8?q?als=20=09-=20not=20equals=20=09-=20contains=20=09-=20is=20not?= =?UTF-8?q?=20empty=20=09-=20is=20empty=203.=20Value=20Input=20-=20Smart?= =?UTF-8?q?=20input=20based=20on=20field=20type:=20=09-=20Checkbox=20field?= =?UTF-8?q?s=20=E2=86=92=20dropdown=20with=20"Checked=20(true)"=20/=20"Unc?= =?UTF-8?q?hecked=20(false)"=20=09-=20empty/not=5Fempty=20operators=20?= =?UTF-8?q?=E2=86=92=20disabled=20(no=20value=20needed)=20=09-=20Other=20f?= =?UTF-8?q?ields=20=E2=86=92=20text=20input=204.=20Action=20Selection=20-?= =?UTF-8?q?=20Dropdown=20with=20options:=20=09-=20Show=20fields=20=09-=20H?= =?UTF-8?q?ide=20fields=20=09-=20Make=20required=20=09-=20Make=20optional?= =?UTF-8?q?=205.=20Target=20Fields=20-=20Checkbox=20list=20of=20all=20fiel?= =?UTF-8?q?ds=20(excluding=20the=20trigger=20field)=20to=20select=20which?= =?UTF-8?q?=20fields=20are=20affected=206.=20Rule=20Summary=20-=20A=20blue?= =?UTF-8?q?=20info=20box=20at=20the=20bottom=20of=20each=20rule=20showing?= =?UTF-8?q?=20a=20human-readable=20summary=20of=20the=20configured=20rule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SettingsSidebar.js | 1 - src/pages/admin/AdminRegistrationBuilder.js | 234 +++++++++++++++++--- 2 files changed, 201 insertions(+), 34 deletions(-) diff --git a/src/components/SettingsSidebar.js b/src/components/SettingsSidebar.js index 551c827..fc08858 100644 --- a/src/components/SettingsSidebar.js +++ b/src/components/SettingsSidebar.js @@ -7,7 +7,6 @@ const settingsItems = [ { label: 'Permissions', path: '/admin/settings/permissions', icon: Shield }, { label: 'Theme', path: '/admin/settings/theme', icon: Palette }, { label: 'Directory', path: '/admin/settings/directory', icon: BookUser }, - // { label: 'Registration', path: '/admin/settings/registration', icon: FileEdit }, // Commented out for future fallback ]; const SettingsTabs = () => { diff --git a/src/pages/admin/AdminRegistrationBuilder.js b/src/pages/admin/AdminRegistrationBuilder.js index 104c60d..aa125e3 100644 --- a/src/pages/admin/AdminRegistrationBuilder.js +++ b/src/pages/admin/AdminRegistrationBuilder.js @@ -1026,45 +1026,213 @@ const AdminRegistrationBuilder = () => { {/* Conditional Rules Dialog */} - + Conditional Rules -
- {(schema?.conditional_rules || []).map((rule, index) => ( -
-
- Rule {index + 1} - +
+

+ Rules allow you to show or hide fields based on other field values. For example, show a "Scholarship Reason" field only when "Request Scholarship" is checked. +

+ + {(schema?.conditional_rules || []).map((rule, index) => { + // Get all available fields for dropdowns + const allFields = schema?.steps?.flatMap(step => + step.sections?.flatMap(section => + section.fields?.map(field => ({ + id: field.id, + label: field.label, + type: field.type, + stepTitle: step.title, + sectionTitle: section.title, + })) || [] + ) || [] + ) || []; + + // Filter trigger fields (checkbox, dropdown, radio work best) + const triggerFields = allFields.filter(f => + ['checkbox', 'dropdown', 'radio', 'text'].includes(f.type) + ); + + // Update a specific rule + const updateRule = (ruleId, updates) => { + updateSchema((prev) => ({ + ...prev, + conditional_rules: prev.conditional_rules.map((r) => + r.id === ruleId ? { ...r, ...updates } : r + ), + })); + }; + + // Get the trigger field's type to determine value input + const triggerFieldData = allFields.find(f => f.id === rule.trigger_field); + + return ( +
+
+ Rule {index + 1} + +
+ + {/* Trigger Field Selection */} +
+
+ + +
+ +
+ + +
+ +
+ + {triggerFieldData?.type === 'checkbox' ? ( + + ) : ['empty', 'not_empty'].includes(rule.trigger_operator) ? ( + + ) : ( + updateRule(rule.id, { trigger_value: e.target.value })} + placeholder="Enter value" + /> + )} +
+
+ + {/* Action Selection */} +
+
+ + +
+ +
+ +
+ {allFields.length === 0 ? ( +

No fields available

+ ) : ( +
+ {allFields + .filter(f => f.id !== rule.trigger_field) // Don't show trigger field as target + .map((field) => ( +
+ { + const currentTargets = rule.target_fields || []; + const newTargets = checked + ? [...currentTargets, field.id] + : currentTargets.filter((id) => id !== field.id); + updateRule(rule.id, { target_fields: newTargets }); + }} + /> + +
+ ))} +
+ )} +
+
+
+ + {/* Rule Summary */} + {rule.trigger_field && (rule.target_fields?.length || 0) > 0 && ( +
+ Summary: When "{triggerFieldData?.label || rule.trigger_field}" {rule.trigger_operator} "{String(rule.trigger_value)}", {rule.action} the following fields: {rule.target_fields?.map(id => allFields.find(f => f.id === id)?.label || id).join(', ')} +
+ )}
-
- When {rule.trigger_field}{' '} - {rule.trigger_operator}{' '} - {String(rule.trigger_value)},{' '} - {rule.action} fields:{' '} - - {rule.target_fields?.join(', ')} - -
-
- ))} + ); + })} {(schema?.conditional_rules || []).length === 0 && ( -
- No conditional rules configured. Rules allow you to show or hide fields based on - other field values. +
+ No conditional rules configured yet.
+ Click "Add Rule" to create your first rule.
)}