diff --git a/app/javascript/elements/field_condition.js b/app/javascript/elements/field_condition.js
index 609d9955..b99a8bb3 100644
--- a/app/javascript/elements/field_condition.js
+++ b/app/javascript/elements/field_condition.js
@@ -64,6 +64,22 @@ export default class extends HTMLElement {
if (action === 'empty' || action === 'unchecked') return this.isEmpty(actual)
if (action === 'not_empty' || action === 'checked') return !this.isEmpty(actual)
+ if (['equal', 'not_equal', 'greater_than', 'less_than'].includes(action) && this.sourceEl?.getAttribute('type') === 'number') {
+ if (this.isEmpty(actual) || this.isEmpty(expected)) return false
+
+ const actualNumber = parseFloat(actual)
+ const expectedNumber = parseFloat(expected)
+
+ if (Number.isNaN(actualNumber) || Number.isNaN(expectedNumber)) return false
+
+ if (action === 'equal') return Math.abs(actualNumber - expectedNumber) < Number.EPSILON
+ if (action === 'not_equal') return Math.abs(actualNumber - expectedNumber) > Number.EPSILON
+ if (action === 'greater_than') return actualNumber > expectedNumber
+ if (action === 'less_than') return actualNumber < expectedNumber
+
+ return false
+ }
+
if (action === 'equal') {
const list = Array.isArray(actual) ? actual : [actual]
return list.filter((v) => v !== null && v !== undefined).map(String).includes(String(expected))
diff --git a/app/javascript/submission_form/form.vue b/app/javascript/submission_form/form.vue
index da939ce4..0f80a3f6 100644
--- a/app/javascript/submission_form/form.vue
+++ b/app/javascript/submission_form/form.vue
@@ -1261,7 +1261,7 @@ export default {
checkFieldCondition (condition, cache = {}) {
const field = this.fieldsUuidIndex[condition.field_uuid]
- if (['not_empty', 'checked', 'equal', 'contains'].includes(condition.action) && field && !this.checkFieldConditions(field, cache)) {
+ if (['not_empty', 'checked', 'equal', 'contains', 'greater_than', 'less_than'].includes(condition.action) && field && !this.checkFieldConditions(field, cache)) {
return false
}
@@ -1271,6 +1271,22 @@ export default {
return isEmpty(this.values[condition.field_uuid] ?? defaultValue)
} else if (['not_empty', 'checked'].includes(condition.action)) {
return !isEmpty(this.values[condition.field_uuid] ?? defaultValue)
+ } else if (field?.type === 'number' && ['equal', 'not_equal', 'greater_than', 'less_than'].includes(condition.action)) {
+ const value = this.values[condition.field_uuid] ?? defaultValue
+
+ if (isEmpty(value) || isEmpty(condition.value)) return false
+
+ const actual = parseFloat(value)
+ const expected = parseFloat(condition.value)
+
+ if (Number.isNaN(actual) || Number.isNaN(expected)) return false
+
+ if (condition.action === 'equal') return Math.abs(actual - expected) < Number.EPSILON
+ if (condition.action === 'not_equal') return Math.abs(actual - expected) > Number.EPSILON
+ if (condition.action === 'greater_than') return actual > expected
+ if (condition.action === 'less_than') return actual < expected
+
+ return false
} else if (['equal', 'contains'].includes(condition.action) && field) {
if (field.options) {
const option = field.options.find((o) => o.uuid === condition.value)
diff --git a/app/javascript/template_builder/conditions_modal.vue b/app/javascript/template_builder/conditions_modal.vue
index 3c7abf29..d8219ff6 100644
--- a/app/javascript/template_builder/conditions_modal.vue
+++ b/app/javascript/template_builder/conditions_modal.vue
@@ -124,6 +124,16 @@
{{ option.value || `${t('option')} ${index + 1}` }}
+
(action) { action == 'equal' && field&.dig('type') == 'number' }
+ return false if value.blank? || condition['value'].blank?
+
+ (value.to_f - condition['value'].to_f).abs < Float::EPSILON
+ when ->(action) { action == 'not_equal' && field&.dig('type') == 'number' }
+ return false if value.blank? || condition['value'].blank?
+
+ (value.to_f - condition['value'].to_f).abs > Float::EPSILON
+ when 'greater_than'
+ return false if field.nil? || value.blank? || condition['value'].blank?
+ value.to_f > condition['value'].to_f
+ when 'less_than'
+ return false if field.nil? || value.blank? || condition['value'].blank?
+
+ value.to_f < condition['value'].to_f
+ when 'equal', 'contains'
return true unless field
values = Array.wrap(value)
@@ -340,8 +356,6 @@ module Submitters
values.include?(option['value'].presence || "#{I18n.t('option')} #{field['options'].index(option) + 1}")
when 'not_equal', 'does_not_contain'
- field = fields_uuid_index[condition['field_uuid']]
-
return true unless field
return false unless field['options']
@@ -356,6 +370,7 @@ module Submitters
true
end
end
+ # rubocop:enable Metrics
def replace_default_variables(value, attrs, submission, with_time: false)
return value if value.in?([true, false]) || value.is_a?(Numeric) || value.is_a?(Array)