df-ae-forms-package 1.1.5 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +236 -36
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +236 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -818,7 +818,6 @@ const DfFormInput = ({ id, properties, validationErrors = {}, formValue = '', in
|
|
|
818
818
|
// Update ref if ID changes (shouldn't happen, but safety check)
|
|
819
819
|
useEffect(() => {
|
|
820
820
|
if (id !== componentIdRef.current) {
|
|
821
|
-
console.warn(`[DfFormInput] Component ID changed from ${componentIdRef.current} to ${id}`);
|
|
822
821
|
componentIdRef.current = id;
|
|
823
822
|
}
|
|
824
823
|
}, [id]);
|
|
@@ -2996,8 +2995,6 @@ const DfFormLocation = ({ id, properties, validationErrors = {}, formValue = nul
|
|
|
2996
2995
|
}
|
|
2997
2996
|
}
|
|
2998
2997
|
catch (error) {
|
|
2999
|
-
// Capacitor not properly initialized, fall through to web geolocation
|
|
3000
|
-
console.warn('Capacitor Geolocation not available, falling back to web geolocation');
|
|
3001
2998
|
}
|
|
3002
2999
|
}
|
|
3003
3000
|
// Fallback to standard web geolocation API (for browsers)
|
|
@@ -3711,7 +3708,6 @@ const AttachmentThumbnails = ({ attachments, onRemove }) => {
|
|
|
3711
3708
|
newUrls.set(index, url);
|
|
3712
3709
|
}
|
|
3713
3710
|
catch (e) {
|
|
3714
|
-
console.warn('Failed to create object URL for attachment:', e);
|
|
3715
3711
|
}
|
|
3716
3712
|
}
|
|
3717
3713
|
else if (file && file.url && file.type && file.type.startsWith('image/')) {
|
|
@@ -4622,7 +4618,6 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4622
4618
|
zIndex: 5
|
|
4623
4619
|
}, children: jsxs("button", { onClick: (e) => {
|
|
4624
4620
|
e.stopPropagation();
|
|
4625
|
-
console.log('[TableView] Add Entry button clicked (grid view)', 'entries:', dataEntries.length, 'max:', maxEntries);
|
|
4626
4621
|
onAddEntry();
|
|
4627
4622
|
}, disabled: dataEntries.length >= maxEntries, style: {
|
|
4628
4623
|
padding: '8px 16px',
|
|
@@ -4748,7 +4743,6 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4748
4743
|
justifyContent: 'center'
|
|
4749
4744
|
}, children: jsxs("button", { onClick: (e) => {
|
|
4750
4745
|
e.stopPropagation();
|
|
4751
|
-
console.log('[TableView] Add Entry button clicked (list view)', 'entries:', dataEntries.length, 'max:', maxEntries);
|
|
4752
4746
|
onAddEntry();
|
|
4753
4747
|
}, disabled: dataEntries.length >= maxEntries, style: {
|
|
4754
4748
|
padding: '8px 16px',
|
|
@@ -5001,12 +4995,8 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
5001
4995
|
// In edit/preview modes, don't handle value changes as components are read-only
|
|
5002
4996
|
}, [mode, onValueChange]);
|
|
5003
4997
|
const handleAddEntry = useCallback(() => {
|
|
5004
|
-
console.log('[DfFormDataGrid] handleAddEntry called - Component ID:', id);
|
|
5005
4998
|
// Safety check: ensure we have entries array
|
|
5006
4999
|
const currentEntries = Array.isArray(properties.entries) ? properties.entries : [];
|
|
5007
|
-
console.log('[DfFormDataGrid] gridComponents:', gridComponents.length);
|
|
5008
|
-
console.log('[DfFormDataGrid] current entries count:', currentEntries.length);
|
|
5009
|
-
console.log('[DfFormDataGrid] onValueChange exists:', !!onValueChange);
|
|
5010
5000
|
// Use timestamp and random string to ensure uniqueness even if entries are deleted
|
|
5011
5001
|
const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
|
|
5012
5002
|
const newEntryId = `entry-${uniqueSuffix}`;
|
|
@@ -5028,11 +5018,8 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
5028
5018
|
}),
|
|
5029
5019
|
styles: {}
|
|
5030
5020
|
};
|
|
5031
|
-
console.log('[DfFormDataGrid] newEntry created:', newEntry.id, 'with', newEntry.components.length, 'components');
|
|
5032
5021
|
const updatedEntries = [...currentEntries, newEntry];
|
|
5033
|
-
console.log('[DfFormDataGrid] updatedEntries count:', updatedEntries.length);
|
|
5034
5022
|
if (onValueChange) {
|
|
5035
|
-
console.log('[DfFormDataGrid] calling onValueChange with updated datagrid structure - Entries:', updatedEntries.length);
|
|
5036
5023
|
onValueChange({
|
|
5037
5024
|
id: gridId, // Use sanitized gridId
|
|
5038
5025
|
value: {
|
|
@@ -5042,13 +5029,9 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
5042
5029
|
});
|
|
5043
5030
|
// Notify parent if callback provided
|
|
5044
5031
|
if (onEntryAdd) {
|
|
5045
|
-
console.log('[DfFormDataGrid] calling onEntryAdd callback');
|
|
5046
5032
|
onEntryAdd();
|
|
5047
5033
|
}
|
|
5048
5034
|
}
|
|
5049
|
-
else {
|
|
5050
|
-
console.warn('[DfFormDataGrid] Cannot add entry: onValueChange is missing');
|
|
5051
|
-
}
|
|
5052
5035
|
}, [onValueChange, properties, gridId, gridComponents, onEntryAdd]);
|
|
5053
5036
|
const handleRemoveEntry = useCallback((entryIndex) => {
|
|
5054
5037
|
// Safety check: ensure we have entries array
|
|
@@ -5057,7 +5040,6 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
5057
5040
|
.filter((_, index) => index !== entryIndex)
|
|
5058
5041
|
.map((entry, index) => ({ ...entry, index })); // Only update index, preserve unique ID
|
|
5059
5042
|
if (onValueChange) {
|
|
5060
|
-
console.log('[DfFormDataGrid] Removing entry at index:', entryIndex, 'New count:', updatedEntries.length);
|
|
5061
5043
|
onValueChange({
|
|
5062
5044
|
id: gridId, // Use sanitized gridId
|
|
5063
5045
|
value: { ...properties, entries: updatedEntries }
|
|
@@ -5445,8 +5427,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5445
5427
|
const [validationErrors, setValidationErrors] = useState({});
|
|
5446
5428
|
const [formSubmitted, setFormSubmitted] = useState(false);
|
|
5447
5429
|
const [touchedFields, setTouchedFields] = useState({});
|
|
5448
|
-
//
|
|
5449
|
-
|
|
5430
|
+
// Component visibility state - driven by conditional logic evaluation
|
|
5431
|
+
const [componentVisibility, setComponentVisibility] = useState({});
|
|
5450
5432
|
// Track raised issues for threshold conditions (Set of condition IDs)
|
|
5451
5433
|
const [raisedThresholdIssues, setRaisedThresholdIssues] = useState(new Set());
|
|
5452
5434
|
// Track threshold action completions: Map<conditionId, { notesCompleted, attachmentsCompleted, emailSent }>
|
|
@@ -5544,6 +5526,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5544
5526
|
if (component.children && Array.isArray(component.children)) {
|
|
5545
5527
|
initializeComponentValues(component.children, values);
|
|
5546
5528
|
}
|
|
5529
|
+
// CRITICAL for conditional logic: Also store value under the label key
|
|
5530
|
+
// so condition lookups by label (e.g. "Temperature") work during init
|
|
5531
|
+
if (component.basic?.label && componentId && values[componentId] !== undefined) {
|
|
5532
|
+
values[component.basic.label] = values[componentId];
|
|
5533
|
+
}
|
|
5547
5534
|
});
|
|
5548
5535
|
};
|
|
5549
5536
|
const initializeFormState = useCallback(() => {
|
|
@@ -5615,15 +5602,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5615
5602
|
const labelPart = safeLabel ? `-${safeLabel}` : '';
|
|
5616
5603
|
validatedComponent.id = `${name}${labelPart}-${index}`;
|
|
5617
5604
|
}
|
|
5618
|
-
console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
|
|
5619
5605
|
}
|
|
5620
5606
|
else {
|
|
5621
5607
|
// ID is a valid string, check for duplicates
|
|
5622
5608
|
if (seenIds.has(validatedComponent.id)) {
|
|
5623
|
-
console.error(`[DfFormPreview] Duplicate component ID detected: ${validatedComponent.id}`);
|
|
5624
5609
|
// Generate a unique ID for duplicate - using index to keep it somewhat stable
|
|
5625
5610
|
validatedComponent.id = `${validatedComponent.id}-dup-${index}`;
|
|
5626
|
-
console.warn(`[DfFormPreview] Generated new unique ID: ${validatedComponent.id}`);
|
|
5627
5611
|
}
|
|
5628
5612
|
}
|
|
5629
5613
|
seenIds.add(validatedComponent.id);
|
|
@@ -5678,7 +5662,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5678
5662
|
validatedFormComponents = getValidatedComponents(localFormComponents);
|
|
5679
5663
|
// Synchronize local state if components were mutated (IDs added/fixed)
|
|
5680
5664
|
if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
|
|
5681
|
-
console.log('[DfFormPreview] Synchronizing local components after ID validation');
|
|
5682
5665
|
setLocalFormComponents(validatedFormComponents);
|
|
5683
5666
|
onFormDataChange?.(validatedFormComponents);
|
|
5684
5667
|
}
|
|
@@ -5731,13 +5714,229 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5731
5714
|
// Initialize notes and attachments state
|
|
5732
5715
|
setComponentNotes(prev => ({ ...initialNotes, ...prev }));
|
|
5733
5716
|
setComponentAttachments(prev => ({ ...initialAttachments, ...prev }));
|
|
5734
|
-
//
|
|
5735
|
-
|
|
5717
|
+
// Evaluate conditional logic on initialization
|
|
5718
|
+
evaluateConditionalLogic(initialValues);
|
|
5736
5719
|
}, [initialFormData, localFormComponents]);
|
|
5737
|
-
//
|
|
5738
|
-
|
|
5739
|
-
|
|
5720
|
+
// ======================== CONDITIONAL LOGIC ENGINE ========================
|
|
5721
|
+
// This is a pure visibility layer. It NEVER modifies component data.
|
|
5722
|
+
// It computes a { [componentId]: boolean } map based on each component's
|
|
5723
|
+
// `logic` property and the current form values.
|
|
5724
|
+
// Helper: Flatten all components (including nested) into a flat list
|
|
5725
|
+
const flattenAllComponents = useCallback((components) => {
|
|
5726
|
+
const flat = [];
|
|
5727
|
+
const traverse = (items) => {
|
|
5728
|
+
if (!items || !Array.isArray(items))
|
|
5729
|
+
return;
|
|
5730
|
+
for (const item of items) {
|
|
5731
|
+
flat.push(item);
|
|
5732
|
+
if (item.children && Array.isArray(item.children))
|
|
5733
|
+
traverse(item.children);
|
|
5734
|
+
if (item.cells && Array.isArray(item.cells)) {
|
|
5735
|
+
for (const row of item.cells) {
|
|
5736
|
+
const normalizedRow = normalizeTableRow(row);
|
|
5737
|
+
for (const cell of normalizedRow) {
|
|
5738
|
+
if (cell.components)
|
|
5739
|
+
traverse(cell.components);
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
}
|
|
5743
|
+
if (item.entries && Array.isArray(item.entries)) {
|
|
5744
|
+
for (const entry of item.entries) {
|
|
5745
|
+
if (entry.components)
|
|
5746
|
+
traverse(entry.components);
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
if (item.templateComponents && Array.isArray(item.templateComponents)) {
|
|
5750
|
+
traverse(item.templateComponents);
|
|
5751
|
+
}
|
|
5752
|
+
}
|
|
5753
|
+
};
|
|
5754
|
+
traverse(components);
|
|
5755
|
+
return flat;
|
|
5756
|
+
}, []);
|
|
5757
|
+
// Helper: Get the value of a component referenced by a condition's `when` field.
|
|
5758
|
+
// The `when` field is typically a component LABEL (e.g. "Temperature"), not an ID.
|
|
5759
|
+
const getConditionComponentValue = useCallback((conditionWhen, allComponents, currentFormValues) => {
|
|
5760
|
+
// Try to find the component by label, id, or _id
|
|
5761
|
+
const comp = allComponents.find(c => c.basic?.label === conditionWhen ||
|
|
5762
|
+
ensureStringId$1(c.id) === conditionWhen ||
|
|
5763
|
+
ensureStringId$1(c._id) === conditionWhen);
|
|
5764
|
+
if (!comp)
|
|
5765
|
+
return undefined;
|
|
5766
|
+
const compId = ensureStringId$1(comp.id || comp._id);
|
|
5767
|
+
// Check formValues by ID first
|
|
5768
|
+
if (compId && currentFormValues[compId] !== undefined) {
|
|
5769
|
+
return currentFormValues[compId];
|
|
5770
|
+
}
|
|
5771
|
+
// Also check by label (main website stores values by label too)
|
|
5772
|
+
if (comp.basic?.label && currentFormValues[comp.basic.label] !== undefined) {
|
|
5773
|
+
return currentFormValues[comp.basic.label];
|
|
5774
|
+
}
|
|
5775
|
+
// Fall back to component's basic.value or defaultValue
|
|
5776
|
+
if (comp.basic?.value !== undefined && comp.basic?.value !== null && comp.basic?.value !== '') {
|
|
5777
|
+
return comp.basic.value;
|
|
5778
|
+
}
|
|
5779
|
+
if (comp.basic?.defaultValue !== undefined && comp.basic?.defaultValue !== null && comp.basic?.defaultValue !== '') {
|
|
5780
|
+
return comp.basic.defaultValue;
|
|
5781
|
+
}
|
|
5782
|
+
return undefined;
|
|
5740
5783
|
}, []);
|
|
5784
|
+
// Helper: Evaluate a single condition
|
|
5785
|
+
const evaluateSingleCondition = useCallback((condition, componentValue) => {
|
|
5786
|
+
const { operator, value } = condition;
|
|
5787
|
+
// isEmpty / isNotEmpty
|
|
5788
|
+
if (operator === 'isEmpty') {
|
|
5789
|
+
if (componentValue == null)
|
|
5790
|
+
return true;
|
|
5791
|
+
if (typeof componentValue === 'string')
|
|
5792
|
+
return componentValue.trim() === '';
|
|
5793
|
+
if (Array.isArray(componentValue))
|
|
5794
|
+
return componentValue.length === 0;
|
|
5795
|
+
return false;
|
|
5796
|
+
}
|
|
5797
|
+
if (operator === 'isNotEmpty') {
|
|
5798
|
+
if (componentValue == null)
|
|
5799
|
+
return false;
|
|
5800
|
+
if (typeof componentValue === 'string')
|
|
5801
|
+
return componentValue.trim() !== '';
|
|
5802
|
+
if (Array.isArray(componentValue))
|
|
5803
|
+
return componentValue.length > 0;
|
|
5804
|
+
return true;
|
|
5805
|
+
}
|
|
5806
|
+
// checked / notChecked (for checkboxes)
|
|
5807
|
+
if (operator === 'checked' || operator === 'notChecked') {
|
|
5808
|
+
let isChecked = false;
|
|
5809
|
+
if (typeof componentValue === 'boolean')
|
|
5810
|
+
isChecked = componentValue;
|
|
5811
|
+
else if (typeof componentValue === 'string')
|
|
5812
|
+
isChecked = componentValue.toLowerCase() === 'true' || componentValue === '1' || componentValue.length > 0;
|
|
5813
|
+
else if (Array.isArray(componentValue))
|
|
5814
|
+
isChecked = componentValue.length > 0;
|
|
5815
|
+
else if (typeof componentValue === 'number')
|
|
5816
|
+
isChecked = componentValue > 0;
|
|
5817
|
+
return operator === 'checked' ? isChecked : !isChecked;
|
|
5818
|
+
}
|
|
5819
|
+
// equals / notEquals
|
|
5820
|
+
if (operator === 'equals' || operator === 'notEquals') {
|
|
5821
|
+
let isEqual = false;
|
|
5822
|
+
// Loose comparison
|
|
5823
|
+
if (componentValue == value)
|
|
5824
|
+
isEqual = true;
|
|
5825
|
+
// String comparison (case-insensitive, trimmed)
|
|
5826
|
+
if (!isEqual && componentValue != null && value != null) {
|
|
5827
|
+
const strA = String(componentValue).trim();
|
|
5828
|
+
const strB = String(value).trim();
|
|
5829
|
+
// Numeric comparison within strings
|
|
5830
|
+
if (strA !== '' && strB !== '' && !isNaN(Number(strA)) && !isNaN(Number(strB))) {
|
|
5831
|
+
isEqual = Number(strA) === Number(strB);
|
|
5832
|
+
}
|
|
5833
|
+
if (!isEqual) {
|
|
5834
|
+
isEqual = strA.toLowerCase() === strB.toLowerCase();
|
|
5835
|
+
}
|
|
5836
|
+
}
|
|
5837
|
+
// Array contains check (for multi-select)
|
|
5838
|
+
if (!isEqual && Array.isArray(componentValue)) {
|
|
5839
|
+
isEqual = componentValue.some(v => String(v).trim().toLowerCase() === String(value).trim().toLowerCase());
|
|
5840
|
+
}
|
|
5841
|
+
return operator === 'equals' ? isEqual : !isEqual;
|
|
5842
|
+
}
|
|
5843
|
+
// contains / notContains
|
|
5844
|
+
if (operator === 'contains' || operator === 'notContains') {
|
|
5845
|
+
let doesContain = false;
|
|
5846
|
+
if (typeof componentValue === 'string' && value != null) {
|
|
5847
|
+
doesContain = componentValue.trim().toLowerCase().includes(String(value).trim().toLowerCase());
|
|
5848
|
+
}
|
|
5849
|
+
else if (Array.isArray(componentValue) && value != null) {
|
|
5850
|
+
doesContain = componentValue.some(v => String(v).trim().toLowerCase() === String(value).trim().toLowerCase());
|
|
5851
|
+
}
|
|
5852
|
+
return operator === 'contains' ? doesContain : !doesContain;
|
|
5853
|
+
}
|
|
5854
|
+
// Numeric comparisons
|
|
5855
|
+
if (['greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual'].includes(operator)) {
|
|
5856
|
+
const numA = typeof componentValue === 'number' ? componentValue : parseFloat(String(componentValue));
|
|
5857
|
+
const numB = typeof value === 'number' ? value : parseFloat(String(value));
|
|
5858
|
+
if (isNaN(numA) || isNaN(numB))
|
|
5859
|
+
return false;
|
|
5860
|
+
switch (operator) {
|
|
5861
|
+
case 'greaterThan': return numA > numB;
|
|
5862
|
+
case 'lessThan': return numA < numB;
|
|
5863
|
+
case 'greaterThanOrEqual': return numA >= numB;
|
|
5864
|
+
case 'lessThanOrEqual': return numA <= numB;
|
|
5865
|
+
default: return false;
|
|
5866
|
+
}
|
|
5867
|
+
}
|
|
5868
|
+
return false;
|
|
5869
|
+
}, []);
|
|
5870
|
+
// Main conditional logic evaluation function
|
|
5871
|
+
const evaluateConditionalLogic = useCallback((explicitValues) => {
|
|
5872
|
+
const currentComponents = localFormComponents;
|
|
5873
|
+
const currentValues = explicitValues || formValues;
|
|
5874
|
+
if (!currentComponents || currentComponents.length === 0)
|
|
5875
|
+
return;
|
|
5876
|
+
const allComponents = flattenAllComponents(currentComponents);
|
|
5877
|
+
const visibility = {};
|
|
5878
|
+
allComponents.forEach(component => {
|
|
5879
|
+
const compId = ensureStringId$1(component.id || component._id);
|
|
5880
|
+
if (!compId)
|
|
5881
|
+
return;
|
|
5882
|
+
// Container components are ALWAYS visible — their children handle their own logic
|
|
5883
|
+
if (['table', 'datagrid', 'section', 'heading', 'instructions'].includes(component.name)) {
|
|
5884
|
+
visibility[compId] = true;
|
|
5885
|
+
return;
|
|
5886
|
+
}
|
|
5887
|
+
// Get the logic property (API sends it as `logic`, builder uses `conditional`)
|
|
5888
|
+
const logic = component.logic || component.conditional;
|
|
5889
|
+
// No logic or action is 'always' → always show
|
|
5890
|
+
if (!logic || logic.action === 'always' || !logic.conditions || logic.conditions.length === 0) {
|
|
5891
|
+
visibility[compId] = true;
|
|
5892
|
+
return;
|
|
5893
|
+
}
|
|
5894
|
+
// Evaluate each condition
|
|
5895
|
+
const conditionResults = logic.conditions.map((condition) => {
|
|
5896
|
+
const componentValue = getConditionComponentValue(condition.when, allComponents, currentValues);
|
|
5897
|
+
return evaluateSingleCondition(condition, componentValue);
|
|
5898
|
+
});
|
|
5899
|
+
// Determine if conditions are met based on 'when' (all/any)
|
|
5900
|
+
let conditionsMet;
|
|
5901
|
+
if (logic.when === 'any') {
|
|
5902
|
+
conditionsMet = conditionResults.some((r) => r);
|
|
5903
|
+
}
|
|
5904
|
+
else {
|
|
5905
|
+
// Default to 'all'
|
|
5906
|
+
conditionsMet = conditionResults.every((r) => r);
|
|
5907
|
+
}
|
|
5908
|
+
// Apply action
|
|
5909
|
+
if (logic.action === 'show') {
|
|
5910
|
+
visibility[compId] = conditionsMet;
|
|
5911
|
+
}
|
|
5912
|
+
else if (logic.action === 'hide') {
|
|
5913
|
+
visibility[compId] = !conditionsMet;
|
|
5914
|
+
}
|
|
5915
|
+
else {
|
|
5916
|
+
visibility[compId] = true;
|
|
5917
|
+
}
|
|
5918
|
+
});
|
|
5919
|
+
// Only update state if visibility actually changed (prevent re-render loops)
|
|
5920
|
+
setComponentVisibility(prev => {
|
|
5921
|
+
const prevStr = JSON.stringify(prev);
|
|
5922
|
+
const newStr = JSON.stringify(visibility);
|
|
5923
|
+
if (prevStr === newStr)
|
|
5924
|
+
return prev;
|
|
5925
|
+
return visibility;
|
|
5926
|
+
});
|
|
5927
|
+
}, [localFormComponents, formValues, flattenAllComponents, getConditionComponentValue, evaluateSingleCondition]);
|
|
5928
|
+
// Re-evaluate conditional logic whenever form values change
|
|
5929
|
+
useEffect(() => {
|
|
5930
|
+
evaluateConditionalLogic();
|
|
5931
|
+
}, [formValues, evaluateConditionalLogic]);
|
|
5932
|
+
// Check if a component should be visible
|
|
5933
|
+
const shouldShowComponent = useCallback((componentId) => {
|
|
5934
|
+
// In preview mode (read-only submission view), always show everything
|
|
5935
|
+
if (isPreviewMode)
|
|
5936
|
+
return true;
|
|
5937
|
+
// Default to visible if not explicitly set to false
|
|
5938
|
+
return componentVisibility[componentId] !== false;
|
|
5939
|
+
}, [componentVisibility, isPreviewMode]);
|
|
5741
5940
|
// Handle form value changes and re-evaluate conditional logic
|
|
5742
5941
|
const onFormValueChange = useCallback((change) => {
|
|
5743
5942
|
// CRITICAL: Validate that change.id is valid and unique
|
|
@@ -5789,6 +5988,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5789
5988
|
// Only update formValues for actual value changes, not structure updates
|
|
5790
5989
|
if (!isStructureUpdate) {
|
|
5791
5990
|
newFormValues[change.id] = change.value;
|
|
5991
|
+
// CRITICAL for conditional logic: Also store value under the component's label.
|
|
5992
|
+
// Conditions reference components by label (e.g. "Temperature"), not by ID.
|
|
5993
|
+
const allComponents = flattenAllComponents(localFormComponents);
|
|
5994
|
+
const targetComp = allComponents.find(c => ensureStringId$1(c.id || c._id) === change.id);
|
|
5995
|
+
if (targetComp?.basic?.label) {
|
|
5996
|
+
newFormValues[targetComp.basic.label] = change.value;
|
|
5997
|
+
}
|
|
5792
5998
|
setFormValues(newFormValues);
|
|
5793
5999
|
}
|
|
5794
6000
|
// Clear raised issues for this component when value changes
|
|
@@ -6529,7 +6735,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6529
6735
|
componentCounterRef.current += 1;
|
|
6530
6736
|
cachedId = `generated-${name}-${componentCounterRef.current}-${Math.random().toString(36).substr(2, 9)}`;
|
|
6531
6737
|
componentIdCacheRef.current.set(cacheKey, cachedId);
|
|
6532
|
-
console.warn('[DfFormPreview] Generated and cached ID for component:', cachedId, 'key:', cacheKey);
|
|
6533
6738
|
}
|
|
6534
6739
|
finalComponentId = cachedId;
|
|
6535
6740
|
// Create a new component object with the cached ID (don't mutate original)
|
|
@@ -6545,9 +6750,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6545
6750
|
if (formValue !== undefined) {
|
|
6546
6751
|
// Check if this value is being used by multiple components
|
|
6547
6752
|
const componentsWithSameValue = localFormComponents.filter(comp => comp.id !== componentId && formValues[comp.id] === formValue);
|
|
6548
|
-
if (componentsWithSameValue.length > 0)
|
|
6549
|
-
console.warn(`[DfFormPreview] Component ${componentId} shares form value with other components:`, componentsWithSameValue.map(c => c.id));
|
|
6550
|
-
}
|
|
6753
|
+
if (componentsWithSameValue.length > 0) ;
|
|
6551
6754
|
}
|
|
6552
6755
|
const commonProps = {
|
|
6553
6756
|
id: componentId, // Use the validated component ID
|
|
@@ -6760,10 +6963,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6760
6963
|
}, onValueChange: (change) => {
|
|
6761
6964
|
const changeId = ensureStringId$1(change.id);
|
|
6762
6965
|
const componentId = ensureStringId$1(component.id);
|
|
6763
|
-
console.log(`[DfFormPreview] datagrid onValueChange - Target: ${changeId}, Component: ${componentId}`);
|
|
6764
6966
|
// Handle datagrid value changes (entries updates)
|
|
6765
6967
|
if (changeId === componentId && change.value && typeof change.value === 'object' && 'entries' in change.value) {
|
|
6766
|
-
console.log('[DfFormPreview] datagrid entries update - entries count:', change.value.entries?.length);
|
|
6767
6968
|
// Update localFormComponents with new entries structure
|
|
6768
6969
|
const updatedComponents = localFormComponents.map(comp => {
|
|
6769
6970
|
const currentCompId = ensureStringId$1(comp.id);
|
|
@@ -6806,7 +7007,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6806
7007
|
}
|
|
6807
7008
|
});
|
|
6808
7009
|
if (valuesChanged) {
|
|
6809
|
-
console.log('[DfFormPreview] Initializing form values for new datagrid entries');
|
|
6810
7010
|
setFormValues(newValues);
|
|
6811
7011
|
}
|
|
6812
7012
|
}
|