df-ae-forms-package 1.1.5 → 1.1.7

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.d.ts CHANGED
@@ -875,6 +875,7 @@ interface IRaiseIssueModalProps {
875
875
  assetNumber?: string;
876
876
  isStandalone?: boolean;
877
877
  allowWorkflowActions?: boolean;
878
+ inEditMode?: boolean;
878
879
  isEdit?: boolean;
879
880
  }
880
881
  declare const RaiseIssueModal: React.FC<IRaiseIssueModalProps>;
package/dist/index.esm.js CHANGED
@@ -332,7 +332,7 @@ const RaiseIssueModal = ({ isOpen, onClose, onSuccess, component, formTemplateId
332
332
  'Maria Garcia',
333
333
  'John Smith',
334
334
  'Sarah Johnson'
335
- ], workOrderNumber: initialWorkOrderNumber, assetNumber: initialAssetNumber, isStandalone, isEdit }) => {
335
+ ], workOrderNumber: initialWorkOrderNumber, assetNumber: initialAssetNumber, isStandalone, inEditMode = false, isEdit }) => {
336
336
  // Determine if workflow actions should be enabled
337
337
  // If explicitly provided, use that. Otherwise, default to isEdit (true if editing, false/undefined otherwise).
338
338
  // Fallback to false if neither is provided.
@@ -348,6 +348,7 @@ const RaiseIssueModal = ({ isOpen, onClose, onSuccess, component, formTemplateId
348
348
  // State to hold both File objects and existing attachments
349
349
  const [localAttachments, setLocalAttachments] = useState(attachments || []);
350
350
  const [isDragging, setIsDragging] = useState(false);
351
+ const [isViewMode, setIsViewMode] = useState(!!issue && !inEditMode);
351
352
  const fileInputRef = React.useRef(null);
352
353
  const isEditMode = isEdit !== undefined ? isEdit : !!issue;
353
354
  useEffect(() => {
@@ -369,6 +370,11 @@ const RaiseIssueModal = ({ isOpen, onClose, onSuccess, component, formTemplateId
369
370
  }
370
371
  }
371
372
  }, [isOpen, attachments, issue, isEditMode]);
373
+ useEffect(() => {
374
+ if (issue) {
375
+ setIsViewMode(!inEditMode);
376
+ }
377
+ }, [issue, inEditMode]);
372
378
  const handleFileChange = (event) => {
373
379
  if (event.target.files && event.target.files.length > 0) {
374
380
  const newFiles = Array.from(event.target.files);
@@ -585,6 +591,7 @@ const RaiseIssueModal = ({ isOpen, onClose, onSuccess, component, formTemplateId
585
591
  await onUpdateIssue(issue._id, updateData);
586
592
  }
587
593
  toastService.showSuccess('Issue updated successfully');
594
+ setIsViewMode(true);
588
595
  if (onSuccess) {
589
596
  onSuccess();
590
597
  }
@@ -666,7 +673,7 @@ const RaiseIssueModal = ({ isOpen, onClose, onSuccess, component, formTemplateId
666
673
  if (!isOpen) {
667
674
  return null;
668
675
  }
669
- const modalContent = (jsx("div", { className: "raise-issue-modal-overlay", onClick: onClose, children: jsxs("div", { className: "raise-issue-modal", onClick: (e) => e.stopPropagation(), children: [jsxs("div", { className: "raise-issue-modal-header", children: [jsxs("div", { className: "raise-issue-modal-header-left", children: [jsx(AlertTriangle, { className: "raise-issue-modal-icon", size: 20 }), jsx("div", { className: "raise-issue-modal-header-text", children: jsx("div", { className: "raise-issue-modal-title-main", children: isEditMode ? 'Issue Details' : 'Create Issue' }) })] }), jsx("button", { className: "raise-issue-modal-close", onClick: onClose, "aria-label": "Close", children: jsx(X$1, { size: 18 }) })] }), jsx("div", { className: "raise-issue-modal-content", children: jsxs("div", { className: "raise-issue-fields-grid", children: [isEditMode && issue?.issueNumber && (jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Issue ID" }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: issue.issueNumber, readOnly: true })] })), jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Task" }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: isEditMode ? (issue?.component?.basic?.label || '') : (component?.basic?.label || ''), readOnly: true })] }), jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Task Value" }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: isEditMode ? (issue?.component?.basic?.value || '') : (component?.basic?.value || ''), readOnly: true })] }), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Title ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: `raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: title, onChange: (e) => setTitle(e.target.value), placeholder: "Enter issue title", readOnly: isEditMode })] }), !isStandalone && (jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Work Order ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: `raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: workOrderNumber, onChange: (e) => setWorkOrderNumber(e.target.value), placeholder: "N/A", readOnly: isEditMode })] })), !isStandalone && (jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Asset Number ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: `raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: assetNumber, onChange: (e) => setAssetNumber(e.target.value), placeholder: "Enter asset number", readOnly: isEditMode })] })), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Raised By ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("div", { className: "raise-issue-field-value-with-icon", children: [jsx(User, { size: 16 }), jsx("span", { children: user ? `${user.firstName || ''} ${user.lastName || ''}`.trim() || 'User' : 'User' })] })] }), jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Created On" }), jsxs("div", { className: "raise-issue-field-value-with-icon", children: [jsx(Calendar, { size: 16 }), jsx("span", { children: isEditMode && issue?.createdAt
676
+ const modalContent = (jsx("div", { className: "raise-issue-modal-overlay", onClick: onClose, children: jsxs("div", { className: "raise-issue-modal", onClick: (e) => e.stopPropagation(), children: [jsxs("div", { className: "raise-issue-modal-header", children: [jsxs("div", { className: "raise-issue-modal-header-left", children: [jsx(AlertTriangle, { className: "raise-issue-modal-icon", size: 20 }), jsx("div", { className: "raise-issue-modal-header-text", children: jsx("div", { className: "raise-issue-modal-title-main", children: isEditMode ? 'Issue Details' : 'Create Issue' }) })] }), jsx("button", { className: "raise-issue-modal-close", onClick: onClose, "aria-label": "Close", children: jsx(X$1, { size: 18 }) })] }), jsx("div", { className: "raise-issue-modal-content", children: jsxs("div", { className: "raise-issue-fields-grid", children: [isEditMode && issue?.issueNumber && (jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Issue ID" }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: issue.issueNumber, readOnly: true })] })), jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Task" }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: isEditMode ? (issue?.component?.basic?.label || '') : (component?.basic?.label || ''), readOnly: true })] }), jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Task Value" }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: isEditMode ? (issue?.component?.basic?.value || '') : (component?.basic?.value || ''), readOnly: true })] }), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Title ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: `raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: title, onChange: (e) => setTitle(e.target.value), placeholder: "Enter issue title", readOnly: isEditMode && isViewMode })] }), !isStandalone && (jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Work Order ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: `raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: workOrderNumber, onChange: (e) => setWorkOrderNumber(e.target.value), placeholder: "N/A", readOnly: isEditMode && isViewMode })] })), !isStandalone && (jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Asset Number ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: `raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: assetNumber, onChange: (e) => setAssetNumber(e.target.value), placeholder: "Enter asset number", readOnly: isEditMode && isViewMode })] })), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Raised By ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("div", { className: "raise-issue-field-value-with-icon", children: [jsx(User, { size: 16 }), jsx("span", { children: user ? `${user.firstName || ''} ${user.lastName || ''}`.trim() || 'User' : 'User' })] })] }), jsxs("div", { className: "raise-issue-field", children: [jsx("label", { className: "raise-issue-field-label", children: "Created On" }), jsxs("div", { className: "raise-issue-field-value-with-icon", children: [jsx(Calendar, { size: 16 }), jsx("span", { children: isEditMode && issue?.createdAt
670
677
  ? (safeDate(issue.createdAt) || new Date()).toLocaleString('en-US', {
671
678
  year: 'numeric',
672
679
  month: 'short',
@@ -682,7 +689,7 @@ const RaiseIssueModal = ({ isOpen, onClose, onSuccess, component, formTemplateId
682
689
  hour: '2-digit',
683
690
  minute: '2-digit',
684
691
  hour12: true
685
- }) })] })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Description ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("textarea", { className: `raise-issue-field-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Enter issue description", rows: 4, readOnly: isEditMode })] }), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Status ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("select", { className: `raise-issue-field-select ${!isEditMode ? 'raise-issue-field-readonly' : ''}`, value: status, onChange: (e) => setStatus(e.target.value), disabled: !isEditMode, children: [jsx("option", { value: EIssueStatus.OPEN, children: EIssueStatus.OPEN }), jsx("option", { value: EIssueStatus.IN_PROGRESS, children: EIssueStatus.IN_PROGRESS }), jsx("option", { value: EIssueStatus.REJECTED, children: EIssueStatus.REJECTED }), jsx("option", { value: EIssueStatus.RESOLVE, children: EIssueStatus.RESOLVE })] })] }), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Assign to ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("select", { className: "raise-issue-field-select", value: assignee, onChange: (e) => setAssignee(e.target.value), children: [jsx("option", { value: "", children: "Unassigned" }), availableUsers.map(userName => (jsx("option", { value: userName, children: userName }, userName)))] })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Priority ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("div", { className: "raise-issue-priority-buttons", children: [jsx("button", { type: "button", className: `priority-button priority-low ${priority === 'Low' ? 'active' : ''}`, onClick: () => setPriority('Low'), children: "Low" }), jsx("button", { type: "button", className: `priority-button priority-medium ${priority === 'Medium' ? 'active' : ''}`, onClick: () => setPriority('Medium'), children: "Medium" }), jsx("button", { type: "button", className: `priority-button priority-high ${priority === 'High' ? 'active' : ''}`, onClick: () => setPriority('High'), children: "High" })] })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", children: [jsxs("label", { className: "raise-issue-field-label-with-icon", children: [jsx(MessageSquare, { size: 16 }), jsx("span", { children: "Comments" })] }), !comments && (jsx("div", { className: "raise-issue-no-comments", children: "No comments yet" })), jsx("textarea", { className: `raise-issue-field-textarea raise-issue-comments-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: comments, onChange: (e) => setComments(e.target.value), placeholder: "Add a comment...", rows: 4, readOnly: isEditMode })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", style: { marginTop: '1rem' }, children: [jsx("label", { className: "raise-issue-field-label", children: "Attachments" }), jsxs("div", { className: "raise-issue-attachments-container", children: [!isEditMode && (jsxs("div", { className: `raise-issue-dropzone ${isDragging ? 'dragging' : ''}`, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: () => fileInputRef.current?.click(), children: [jsx("input", { type: "file", ref: fileInputRef, style: { display: 'none' }, onChange: handleFileChange, multiple: true }), jsx("div", { className: "raise-issue-dropzone-icon", children: jsx(UploadCloud, { size: 24 }) }), jsx("div", { className: "raise-issue-dropzone-text", children: "Click to upload or drag and drop" }), jsx("div", { className: "raise-issue-dropzone-hint", children: "PNG, JPG up to 10MB" })] })), localAttachments.length > 0 && (jsx("div", { className: "raise-issue-attachments-list", children: localAttachments.map((file, index) => (jsxs("div", { className: "raise-issue-attachment-item", children: [jsx("div", { className: "raise-issue-attachment-thumbnail", children: getAttachmentPreview(file) ? (jsx("img", { src: getAttachmentPreview(file), alt: "Thumbnail" })) : (jsx(Paperclip, { size: 20, color: "#9ca3af" })) }), jsxs("div", { className: "raise-issue-attachment-info", children: [jsx("span", { className: "attachment-name", title: getAttachmentName(file), children: getAttachmentName(file) }), file instanceof File && (jsxs("span", { className: "attachment-size", children: [(file.size / 1024).toFixed(1), " KB"] }))] }), !isEditMode && (jsx("button", { type: "button", className: "attachment-remove-btn", onClick: () => handleRemoveAttachment(index), title: "Remove", children: jsx(X$1, { size: 12 }) }))] }, index))) }))] })] })] }) }), jsx("div", { className: "raise-issue-modal-actions", children: jsxs("div", { className: "raise-issue-modal-actions-buttons", children: [isEditMode && issue && (jsxs(Fragment, { children: [status === EIssueStatus.OPEN && (jsx("button", { className: "raise-issue-modal-button raise-issue-modal-button-accept", onClick: handleAccept, disabled: isSubmitting, children: isSubmitting ? 'Processing...' : 'Accept' })), status === EIssueStatus.IN_PROGRESS && (jsx("button", { className: "raise-issue-modal-button raise-issue-modal-button-resolve", onClick: handleResolve, disabled: isSubmitting, children: isSubmitting ? 'Processing...' : 'Resolve' })), (status === EIssueStatus.OPEN || status === EIssueStatus.IN_PROGRESS) && (jsx("button", { className: "raise-issue-modal-button raise-issue-modal-button-reject", onClick: handleReject, disabled: isSubmitting, children: isSubmitting ? 'Processing...' : 'Reject' }))] })), !isEditMode && (jsx("button", { className: `raise-issue-modal-button raise-issue-modal-button-save ${!isFormValid ? 'disabled' : ''}`, onClick: handleSubmit, disabled: isSubmitting || !isFormValid, children: isSubmitting ? 'Creating...' : 'Create Issue' }))] }) })] }) }));
692
+ }) })] })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Description ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("textarea", { className: `raise-issue-field-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Enter issue description", rows: 4, readOnly: isEditMode && isViewMode })] }), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Status ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsx("input", { type: "text", className: "raise-issue-field-input raise-issue-field-readonly", value: status, readOnly: true })] }), jsxs("div", { className: "raise-issue-field", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Assign to ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("select", { className: "raise-issue-field-select", value: assignee, onChange: (e) => setAssignee(e.target.value), disabled: isEditMode && isViewMode, children: [jsx("option", { value: "", children: "Unassigned" }), availableUsers.map(userName => (jsx("option", { value: userName, children: userName }, userName)))] })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", children: [jsxs("label", { className: "raise-issue-field-label", children: ["Priority ", jsx("span", { className: "raise-issue-required", children: "*" })] }), jsxs("div", { className: "raise-issue-priority-buttons", children: [jsx("button", { type: "button", className: `priority-button priority-low ${priority === 'Low' ? 'active' : ''}`, onClick: () => setPriority('Low'), disabled: isEditMode && isViewMode, children: "Low" }), jsx("button", { type: "button", className: `priority-button priority-medium ${priority === 'Medium' ? 'active' : ''}`, onClick: () => setPriority('Medium'), disabled: isEditMode && isViewMode, children: "Medium" }), jsx("button", { type: "button", className: `priority-button priority-high ${priority === 'High' ? 'active' : ''}`, onClick: () => setPriority('High'), disabled: isEditMode && isViewMode, children: "High" })] })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", children: [jsxs("label", { className: "raise-issue-field-label-with-icon", children: [jsx(MessageSquare, { size: 16 }), jsx("span", { children: "Comments" })] }), !comments && (jsx("div", { className: "raise-issue-no-comments", children: "No comments yet" })), jsx("textarea", { className: `raise-issue-field-textarea raise-issue-comments-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`, value: comments, onChange: (e) => setComments(e.target.value), placeholder: "Add a comment...", rows: 4, readOnly: isEditMode })] }), jsxs("div", { className: "raise-issue-field raise-issue-field-full-width", style: { marginTop: '1rem' }, children: [jsx("label", { className: "raise-issue-field-label", children: "Attachments" }), jsxs("div", { className: "raise-issue-attachments-container", children: [!isEditMode && (jsxs("div", { className: `raise-issue-dropzone ${isDragging ? 'dragging' : ''}`, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: () => fileInputRef.current?.click(), children: [jsx("input", { type: "file", ref: fileInputRef, style: { display: 'none' }, onChange: handleFileChange, multiple: true }), jsx("div", { className: "raise-issue-dropzone-icon", children: jsx(UploadCloud, { size: 24 }) }), jsx("div", { className: "raise-issue-dropzone-text", children: "Click to upload or drag and drop" }), jsx("div", { className: "raise-issue-dropzone-hint", children: "PNG, JPG up to 10MB" })] })), localAttachments.length > 0 && (jsx("div", { className: "raise-issue-attachments-list", children: localAttachments.map((file, index) => (jsxs("div", { className: "raise-issue-attachment-item", children: [jsx("div", { className: "raise-issue-attachment-thumbnail", children: getAttachmentPreview(file) ? (jsx("img", { src: getAttachmentPreview(file), alt: "Thumbnail" })) : (jsx(Paperclip, { size: 20, color: "#9ca3af" })) }), jsxs("div", { className: "raise-issue-attachment-info", children: [jsx("span", { className: "attachment-name", title: getAttachmentName(file), children: getAttachmentName(file) }), file instanceof File && (jsxs("span", { className: "attachment-size", children: [(file.size / 1024).toFixed(1), " KB"] }))] }), !isEditMode && (jsx("button", { type: "button", className: "attachment-remove-btn", onClick: () => handleRemoveAttachment(index), title: "Remove", children: jsx(X$1, { size: 12 }) }))] }, index))) }))] })] })] }) }), jsx("div", { className: "raise-issue-modal-actions", children: jsxs("div", { className: "raise-issue-modal-actions-buttons", children: [isEditMode && issue && !isViewMode && (jsxs(Fragment, { children: [status === EIssueStatus.OPEN && (jsx("button", { className: "raise-issue-modal-button raise-issue-modal-button-accept", onClick: handleAccept, disabled: isSubmitting, children: isSubmitting ? 'Processing...' : 'Accept' })), status === EIssueStatus.IN_PROGRESS && (jsx("button", { className: "raise-issue-modal-button raise-issue-modal-button-resolve", onClick: handleResolve, disabled: isSubmitting, children: isSubmitting ? 'Processing...' : 'Resolve' })), (status === EIssueStatus.OPEN) && (jsx("button", { className: "raise-issue-modal-button raise-issue-modal-button-reject", onClick: handleReject, disabled: isSubmitting, children: isSubmitting ? 'Processing...' : 'Reject' }))] })), !isEditMode && (jsx("button", { className: `raise-issue-modal-button raise-issue-modal-button-save ${!isFormValid ? 'disabled' : ''}`, onClick: handleSubmit, disabled: isSubmitting || !isFormValid, children: isSubmitting ? 'Creating...' : 'Create Issue' }))] }) })] }) }));
686
693
  // Render modal using portal to document body for full-page overlay
687
694
  return createPortal(modalContent, document.body);
688
695
  };
@@ -818,7 +825,6 @@ const DfFormInput = ({ id, properties, validationErrors = {}, formValue = '', in
818
825
  // Update ref if ID changes (shouldn't happen, but safety check)
819
826
  useEffect(() => {
820
827
  if (id !== componentIdRef.current) {
821
- console.warn(`[DfFormInput] Component ID changed from ${componentIdRef.current} to ${id}`);
822
828
  componentIdRef.current = id;
823
829
  }
824
830
  }, [id]);
@@ -2996,8 +3002,6 @@ const DfFormLocation = ({ id, properties, validationErrors = {}, formValue = nul
2996
3002
  }
2997
3003
  }
2998
3004
  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
3005
  }
3002
3006
  }
3003
3007
  // Fallback to standard web geolocation API (for browsers)
@@ -3711,7 +3715,6 @@ const AttachmentThumbnails = ({ attachments, onRemove }) => {
3711
3715
  newUrls.set(index, url);
3712
3716
  }
3713
3717
  catch (e) {
3714
- console.warn('Failed to create object URL for attachment:', e);
3715
3718
  }
3716
3719
  }
3717
3720
  else if (file && file.url && file.type && file.type.startsWith('image/')) {
@@ -4622,7 +4625,6 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4622
4625
  zIndex: 5
4623
4626
  }, children: jsxs("button", { onClick: (e) => {
4624
4627
  e.stopPropagation();
4625
- console.log('[TableView] Add Entry button clicked (grid view)', 'entries:', dataEntries.length, 'max:', maxEntries);
4626
4628
  onAddEntry();
4627
4629
  }, disabled: dataEntries.length >= maxEntries, style: {
4628
4630
  padding: '8px 16px',
@@ -4748,7 +4750,6 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4748
4750
  justifyContent: 'center'
4749
4751
  }, children: jsxs("button", { onClick: (e) => {
4750
4752
  e.stopPropagation();
4751
- console.log('[TableView] Add Entry button clicked (list view)', 'entries:', dataEntries.length, 'max:', maxEntries);
4752
4753
  onAddEntry();
4753
4754
  }, disabled: dataEntries.length >= maxEntries, style: {
4754
4755
  padding: '8px 16px',
@@ -5001,12 +5002,8 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
5001
5002
  // In edit/preview modes, don't handle value changes as components are read-only
5002
5003
  }, [mode, onValueChange]);
5003
5004
  const handleAddEntry = useCallback(() => {
5004
- console.log('[DfFormDataGrid] handleAddEntry called - Component ID:', id);
5005
5005
  // Safety check: ensure we have entries array
5006
5006
  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
5007
  // Use timestamp and random string to ensure uniqueness even if entries are deleted
5011
5008
  const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
5012
5009
  const newEntryId = `entry-${uniqueSuffix}`;
@@ -5028,11 +5025,8 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
5028
5025
  }),
5029
5026
  styles: {}
5030
5027
  };
5031
- console.log('[DfFormDataGrid] newEntry created:', newEntry.id, 'with', newEntry.components.length, 'components');
5032
5028
  const updatedEntries = [...currentEntries, newEntry];
5033
- console.log('[DfFormDataGrid] updatedEntries count:', updatedEntries.length);
5034
5029
  if (onValueChange) {
5035
- console.log('[DfFormDataGrid] calling onValueChange with updated datagrid structure - Entries:', updatedEntries.length);
5036
5030
  onValueChange({
5037
5031
  id: gridId, // Use sanitized gridId
5038
5032
  value: {
@@ -5042,13 +5036,9 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
5042
5036
  });
5043
5037
  // Notify parent if callback provided
5044
5038
  if (onEntryAdd) {
5045
- console.log('[DfFormDataGrid] calling onEntryAdd callback');
5046
5039
  onEntryAdd();
5047
5040
  }
5048
5041
  }
5049
- else {
5050
- console.warn('[DfFormDataGrid] Cannot add entry: onValueChange is missing');
5051
- }
5052
5042
  }, [onValueChange, properties, gridId, gridComponents, onEntryAdd]);
5053
5043
  const handleRemoveEntry = useCallback((entryIndex) => {
5054
5044
  // Safety check: ensure we have entries array
@@ -5057,7 +5047,6 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
5057
5047
  .filter((_, index) => index !== entryIndex)
5058
5048
  .map((entry, index) => ({ ...entry, index })); // Only update index, preserve unique ID
5059
5049
  if (onValueChange) {
5060
- console.log('[DfFormDataGrid] Removing entry at index:', entryIndex, 'New count:', updatedEntries.length);
5061
5050
  onValueChange({
5062
5051
  id: gridId, // Use sanitized gridId
5063
5052
  value: { ...properties, entries: updatedEntries }
@@ -5445,8 +5434,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5445
5434
  const [validationErrors, setValidationErrors] = useState({});
5446
5435
  const [formSubmitted, setFormSubmitted] = useState(false);
5447
5436
  const [touchedFields, setTouchedFields] = useState({});
5448
- // Conditional logic disabled temporarily
5449
- // const [componentVisibility, setComponentVisibility] = useState<Record<string, boolean>>({})
5437
+ // Component visibility state - driven by conditional logic evaluation
5438
+ const [componentVisibility, setComponentVisibility] = useState({});
5450
5439
  // Track raised issues for threshold conditions (Set of condition IDs)
5451
5440
  const [raisedThresholdIssues, setRaisedThresholdIssues] = useState(new Set());
5452
5441
  // Track threshold action completions: Map<conditionId, { notesCompleted, attachmentsCompleted, emailSent }>
@@ -5544,6 +5533,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5544
5533
  if (component.children && Array.isArray(component.children)) {
5545
5534
  initializeComponentValues(component.children, values);
5546
5535
  }
5536
+ // CRITICAL for conditional logic: Also store value under the label key
5537
+ // so condition lookups by label (e.g. "Temperature") work during init
5538
+ if (component.basic?.label && componentId && values[componentId] !== undefined) {
5539
+ values[component.basic.label] = values[componentId];
5540
+ }
5547
5541
  });
5548
5542
  };
5549
5543
  const initializeFormState = useCallback(() => {
@@ -5615,15 +5609,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5615
5609
  const labelPart = safeLabel ? `-${safeLabel}` : '';
5616
5610
  validatedComponent.id = `${name}${labelPart}-${index}`;
5617
5611
  }
5618
- console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
5619
5612
  }
5620
5613
  else {
5621
5614
  // ID is a valid string, check for duplicates
5622
5615
  if (seenIds.has(validatedComponent.id)) {
5623
- console.error(`[DfFormPreview] Duplicate component ID detected: ${validatedComponent.id}`);
5624
5616
  // Generate a unique ID for duplicate - using index to keep it somewhat stable
5625
5617
  validatedComponent.id = `${validatedComponent.id}-dup-${index}`;
5626
- console.warn(`[DfFormPreview] Generated new unique ID: ${validatedComponent.id}`);
5627
5618
  }
5628
5619
  }
5629
5620
  seenIds.add(validatedComponent.id);
@@ -5678,7 +5669,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5678
5669
  validatedFormComponents = getValidatedComponents(localFormComponents);
5679
5670
  // Synchronize local state if components were mutated (IDs added/fixed)
5680
5671
  if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
5681
- console.log('[DfFormPreview] Synchronizing local components after ID validation');
5682
5672
  setLocalFormComponents(validatedFormComponents);
5683
5673
  onFormDataChange?.(validatedFormComponents);
5684
5674
  }
@@ -5731,13 +5721,229 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5731
5721
  // Initialize notes and attachments state
5732
5722
  setComponentNotes(prev => ({ ...initialNotes, ...prev }));
5733
5723
  setComponentAttachments(prev => ({ ...initialAttachments, ...prev }));
5734
- // Conditional logic evaluation disabled temporarily to fix table issues
5735
- // evaluateConditionalLogic()
5724
+ // Evaluate conditional logic on initialization
5725
+ evaluateConditionalLogic(initialValues);
5736
5726
  }, [initialFormData, localFormComponents]);
5737
- // Conditional logic disabled temporarily - all components are always visible
5738
- const shouldShowComponent = useCallback((_componentId) => {
5739
- return true;
5727
+ // ======================== CONDITIONAL LOGIC ENGINE ========================
5728
+ // This is a pure visibility layer. It NEVER modifies component data.
5729
+ // It computes a { [componentId]: boolean } map based on each component's
5730
+ // `logic` property and the current form values.
5731
+ // Helper: Flatten all components (including nested) into a flat list
5732
+ const flattenAllComponents = useCallback((components) => {
5733
+ const flat = [];
5734
+ const traverse = (items) => {
5735
+ if (!items || !Array.isArray(items))
5736
+ return;
5737
+ for (const item of items) {
5738
+ flat.push(item);
5739
+ if (item.children && Array.isArray(item.children))
5740
+ traverse(item.children);
5741
+ if (item.cells && Array.isArray(item.cells)) {
5742
+ for (const row of item.cells) {
5743
+ const normalizedRow = normalizeTableRow(row);
5744
+ for (const cell of normalizedRow) {
5745
+ if (cell.components)
5746
+ traverse(cell.components);
5747
+ }
5748
+ }
5749
+ }
5750
+ if (item.entries && Array.isArray(item.entries)) {
5751
+ for (const entry of item.entries) {
5752
+ if (entry.components)
5753
+ traverse(entry.components);
5754
+ }
5755
+ }
5756
+ if (item.templateComponents && Array.isArray(item.templateComponents)) {
5757
+ traverse(item.templateComponents);
5758
+ }
5759
+ }
5760
+ };
5761
+ traverse(components);
5762
+ return flat;
5763
+ }, []);
5764
+ // Helper: Get the value of a component referenced by a condition's `when` field.
5765
+ // The `when` field is typically a component LABEL (e.g. "Temperature"), not an ID.
5766
+ const getConditionComponentValue = useCallback((conditionWhen, allComponents, currentFormValues) => {
5767
+ // Try to find the component by label, id, or _id
5768
+ const comp = allComponents.find(c => c.basic?.label === conditionWhen ||
5769
+ ensureStringId$1(c.id) === conditionWhen ||
5770
+ ensureStringId$1(c._id) === conditionWhen);
5771
+ if (!comp)
5772
+ return undefined;
5773
+ const compId = ensureStringId$1(comp.id || comp._id);
5774
+ // Check formValues by ID first
5775
+ if (compId && currentFormValues[compId] !== undefined) {
5776
+ return currentFormValues[compId];
5777
+ }
5778
+ // Also check by label (main website stores values by label too)
5779
+ if (comp.basic?.label && currentFormValues[comp.basic.label] !== undefined) {
5780
+ return currentFormValues[comp.basic.label];
5781
+ }
5782
+ // Fall back to component's basic.value or defaultValue
5783
+ if (comp.basic?.value !== undefined && comp.basic?.value !== null && comp.basic?.value !== '') {
5784
+ return comp.basic.value;
5785
+ }
5786
+ if (comp.basic?.defaultValue !== undefined && comp.basic?.defaultValue !== null && comp.basic?.defaultValue !== '') {
5787
+ return comp.basic.defaultValue;
5788
+ }
5789
+ return undefined;
5790
+ }, []);
5791
+ // Helper: Evaluate a single condition
5792
+ const evaluateSingleCondition = useCallback((condition, componentValue) => {
5793
+ const { operator, value } = condition;
5794
+ // isEmpty / isNotEmpty
5795
+ if (operator === 'isEmpty') {
5796
+ if (componentValue == null)
5797
+ return true;
5798
+ if (typeof componentValue === 'string')
5799
+ return componentValue.trim() === '';
5800
+ if (Array.isArray(componentValue))
5801
+ return componentValue.length === 0;
5802
+ return false;
5803
+ }
5804
+ if (operator === 'isNotEmpty') {
5805
+ if (componentValue == null)
5806
+ return false;
5807
+ if (typeof componentValue === 'string')
5808
+ return componentValue.trim() !== '';
5809
+ if (Array.isArray(componentValue))
5810
+ return componentValue.length > 0;
5811
+ return true;
5812
+ }
5813
+ // checked / notChecked (for checkboxes)
5814
+ if (operator === 'checked' || operator === 'notChecked') {
5815
+ let isChecked = false;
5816
+ if (typeof componentValue === 'boolean')
5817
+ isChecked = componentValue;
5818
+ else if (typeof componentValue === 'string')
5819
+ isChecked = componentValue.toLowerCase() === 'true' || componentValue === '1' || componentValue.length > 0;
5820
+ else if (Array.isArray(componentValue))
5821
+ isChecked = componentValue.length > 0;
5822
+ else if (typeof componentValue === 'number')
5823
+ isChecked = componentValue > 0;
5824
+ return operator === 'checked' ? isChecked : !isChecked;
5825
+ }
5826
+ // equals / notEquals
5827
+ if (operator === 'equals' || operator === 'notEquals') {
5828
+ let isEqual = false;
5829
+ // Loose comparison
5830
+ if (componentValue == value)
5831
+ isEqual = true;
5832
+ // String comparison (case-insensitive, trimmed)
5833
+ if (!isEqual && componentValue != null && value != null) {
5834
+ const strA = String(componentValue).trim();
5835
+ const strB = String(value).trim();
5836
+ // Numeric comparison within strings
5837
+ if (strA !== '' && strB !== '' && !isNaN(Number(strA)) && !isNaN(Number(strB))) {
5838
+ isEqual = Number(strA) === Number(strB);
5839
+ }
5840
+ if (!isEqual) {
5841
+ isEqual = strA.toLowerCase() === strB.toLowerCase();
5842
+ }
5843
+ }
5844
+ // Array contains check (for multi-select)
5845
+ if (!isEqual && Array.isArray(componentValue)) {
5846
+ isEqual = componentValue.some(v => String(v).trim().toLowerCase() === String(value).trim().toLowerCase());
5847
+ }
5848
+ return operator === 'equals' ? isEqual : !isEqual;
5849
+ }
5850
+ // contains / notContains
5851
+ if (operator === 'contains' || operator === 'notContains') {
5852
+ let doesContain = false;
5853
+ if (typeof componentValue === 'string' && value != null) {
5854
+ doesContain = componentValue.trim().toLowerCase().includes(String(value).trim().toLowerCase());
5855
+ }
5856
+ else if (Array.isArray(componentValue) && value != null) {
5857
+ doesContain = componentValue.some(v => String(v).trim().toLowerCase() === String(value).trim().toLowerCase());
5858
+ }
5859
+ return operator === 'contains' ? doesContain : !doesContain;
5860
+ }
5861
+ // Numeric comparisons
5862
+ if (['greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual'].includes(operator)) {
5863
+ const numA = typeof componentValue === 'number' ? componentValue : parseFloat(String(componentValue));
5864
+ const numB = typeof value === 'number' ? value : parseFloat(String(value));
5865
+ if (isNaN(numA) || isNaN(numB))
5866
+ return false;
5867
+ switch (operator) {
5868
+ case 'greaterThan': return numA > numB;
5869
+ case 'lessThan': return numA < numB;
5870
+ case 'greaterThanOrEqual': return numA >= numB;
5871
+ case 'lessThanOrEqual': return numA <= numB;
5872
+ default: return false;
5873
+ }
5874
+ }
5875
+ return false;
5740
5876
  }, []);
5877
+ // Main conditional logic evaluation function
5878
+ const evaluateConditionalLogic = useCallback((explicitValues) => {
5879
+ const currentComponents = localFormComponents;
5880
+ const currentValues = explicitValues || formValues;
5881
+ if (!currentComponents || currentComponents.length === 0)
5882
+ return;
5883
+ const allComponents = flattenAllComponents(currentComponents);
5884
+ const visibility = {};
5885
+ allComponents.forEach(component => {
5886
+ const compId = ensureStringId$1(component.id || component._id);
5887
+ if (!compId)
5888
+ return;
5889
+ // Container components are ALWAYS visible — their children handle their own logic
5890
+ if (['table', 'datagrid', 'section', 'heading', 'instructions'].includes(component.name)) {
5891
+ visibility[compId] = true;
5892
+ return;
5893
+ }
5894
+ // Get the logic property (API sends it as `logic`, builder uses `conditional`)
5895
+ const logic = component.logic || component.conditional;
5896
+ // No logic or action is 'always' → always show
5897
+ if (!logic || logic.action === 'always' || !logic.conditions || logic.conditions.length === 0) {
5898
+ visibility[compId] = true;
5899
+ return;
5900
+ }
5901
+ // Evaluate each condition
5902
+ const conditionResults = logic.conditions.map((condition) => {
5903
+ const componentValue = getConditionComponentValue(condition.when, allComponents, currentValues);
5904
+ return evaluateSingleCondition(condition, componentValue);
5905
+ });
5906
+ // Determine if conditions are met based on 'when' (all/any)
5907
+ let conditionsMet;
5908
+ if (logic.when === 'any') {
5909
+ conditionsMet = conditionResults.some((r) => r);
5910
+ }
5911
+ else {
5912
+ // Default to 'all'
5913
+ conditionsMet = conditionResults.every((r) => r);
5914
+ }
5915
+ // Apply action
5916
+ if (logic.action === 'show') {
5917
+ visibility[compId] = conditionsMet;
5918
+ }
5919
+ else if (logic.action === 'hide') {
5920
+ visibility[compId] = !conditionsMet;
5921
+ }
5922
+ else {
5923
+ visibility[compId] = true;
5924
+ }
5925
+ });
5926
+ // Only update state if visibility actually changed (prevent re-render loops)
5927
+ setComponentVisibility(prev => {
5928
+ const prevStr = JSON.stringify(prev);
5929
+ const newStr = JSON.stringify(visibility);
5930
+ if (prevStr === newStr)
5931
+ return prev;
5932
+ return visibility;
5933
+ });
5934
+ }, [localFormComponents, formValues, flattenAllComponents, getConditionComponentValue, evaluateSingleCondition]);
5935
+ // Re-evaluate conditional logic whenever form values change
5936
+ useEffect(() => {
5937
+ evaluateConditionalLogic();
5938
+ }, [formValues, evaluateConditionalLogic]);
5939
+ // Check if a component should be visible
5940
+ const shouldShowComponent = useCallback((componentId) => {
5941
+ // In preview mode (read-only submission view), always show everything
5942
+ if (isPreviewMode)
5943
+ return true;
5944
+ // Default to visible if not explicitly set to false
5945
+ return componentVisibility[componentId] !== false;
5946
+ }, [componentVisibility, isPreviewMode]);
5741
5947
  // Handle form value changes and re-evaluate conditional logic
5742
5948
  const onFormValueChange = useCallback((change) => {
5743
5949
  // CRITICAL: Validate that change.id is valid and unique
@@ -5789,6 +5995,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
5789
5995
  // Only update formValues for actual value changes, not structure updates
5790
5996
  if (!isStructureUpdate) {
5791
5997
  newFormValues[change.id] = change.value;
5998
+ // CRITICAL for conditional logic: Also store value under the component's label.
5999
+ // Conditions reference components by label (e.g. "Temperature"), not by ID.
6000
+ const allComponents = flattenAllComponents(localFormComponents);
6001
+ const targetComp = allComponents.find(c => ensureStringId$1(c.id || c._id) === change.id);
6002
+ if (targetComp?.basic?.label) {
6003
+ newFormValues[targetComp.basic.label] = change.value;
6004
+ }
5792
6005
  setFormValues(newFormValues);
5793
6006
  }
5794
6007
  // Clear raised issues for this component when value changes
@@ -6529,7 +6742,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6529
6742
  componentCounterRef.current += 1;
6530
6743
  cachedId = `generated-${name}-${componentCounterRef.current}-${Math.random().toString(36).substr(2, 9)}`;
6531
6744
  componentIdCacheRef.current.set(cacheKey, cachedId);
6532
- console.warn('[DfFormPreview] Generated and cached ID for component:', cachedId, 'key:', cacheKey);
6533
6745
  }
6534
6746
  finalComponentId = cachedId;
6535
6747
  // Create a new component object with the cached ID (don't mutate original)
@@ -6545,9 +6757,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6545
6757
  if (formValue !== undefined) {
6546
6758
  // Check if this value is being used by multiple components
6547
6759
  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
- }
6760
+ if (componentsWithSameValue.length > 0) ;
6551
6761
  }
6552
6762
  const commonProps = {
6553
6763
  id: componentId, // Use the validated component ID
@@ -6760,10 +6970,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6760
6970
  }, onValueChange: (change) => {
6761
6971
  const changeId = ensureStringId$1(change.id);
6762
6972
  const componentId = ensureStringId$1(component.id);
6763
- console.log(`[DfFormPreview] datagrid onValueChange - Target: ${changeId}, Component: ${componentId}`);
6764
6973
  // Handle datagrid value changes (entries updates)
6765
6974
  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
6975
  // Update localFormComponents with new entries structure
6768
6976
  const updatedComponents = localFormComponents.map(comp => {
6769
6977
  const currentCompId = ensureStringId$1(comp.id);
@@ -6806,7 +7014,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6806
7014
  }
6807
7015
  });
6808
7016
  if (valuesChanged) {
6809
- console.log('[DfFormPreview] Initializing form values for new datagrid entries');
6810
7017
  setFormValues(newValues);
6811
7018
  }
6812
7019
  }