From 25be5747a6e462a3d09fc6607b3639b79e4d9374 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 23 Dec 2025 20:11:26 +0000
Subject: [PATCH] =EmailManager.php refactor, Turnstile properly integrated with form submissions
---
src/forms/view.js | 70 ++++++++++++++++++++++++++++++----
1 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/src/forms/view.js b/src/forms/view.js
index e4a88ea..957a5df 100644
--- a/src/forms/view.js
+++ b/src/forms/view.js
@@ -8,7 +8,7 @@
this.controller = new window.jvbForm();
document.querySelectorAll('.jvb-form-block form').forEach(form => {
- this.controller.registerForm(form, {autosave: true});
+ this.controller.registerForm(form, {autosave: true,autoUpload: false});
});
this.controller.subscribe((event, data) => {
@@ -24,9 +24,39 @@
let formData = data.fullData;
let form = formConfig.element;
+ // Create FormData instead of JSON
+ const submitData = new FormData();
+
+ // Add all regular form fields
+ for (const [key, value] of Object.entries(formData)) {
+ // Skip the nonce field - we don't need it for REST API with __return_true
+ if (key === '_wpnonce' || key === '_wp_http_referer') {
+ continue;
+ }
+ if (Array.isArray(value)) {
+ value.forEach(v => submitData.append(`${key}[]`, v));
+ } else if (typeof value === 'object' && value !== null) {
+ // For nested objects, you might want to JSON.stringify them
+ submitData.append(key, JSON.stringify(value));
+ } else {
+ submitData.append(key, value);
+ }
+ }
+
+ // Get uploaded files from UploadManager
+ if (window.jvbUploads) {
+ const files = await window.jvbUploads.getFilesForForm(form);
+
+ // Append files with their field names
+ files.forEach(({file, fieldName, uploadId, meta}) => {
+ // Use fieldName[] for multiple files per field
+ submitData.append(`${fieldName}[]`, file);
+ });
+ }
+
+
let headers = {
- 'X-WP-Nonce': jvbSettings.nonce,
- 'Content-Type': 'application/json'
+ // 'X-WP-Nonce': window.auth.getNonce()
};
let block = form.closest('.jvb-form-block');
@@ -35,26 +65,48 @@
try {
const response = await fetch(`${jvbSettings.api}forms`, {
method: 'POST',
+ credentials: 'same-origin',
headers,
- body: JSON.stringify(formData)
+ body: submitData // Send FormData instead of JSON
});
+ const result = await response.json();
if (!response.ok) {
this.controller.showFormStatus(formId, 'error');
- const errorData = await response.json().catch(() => ({}));
- throw new Error(errorData.message || `Request failed with status ${response.status}`);
+ this.controller.handleFormError(form, result); // ✓ Show error to user
+ return; // Stop processing
}
this.controller.showFormStatus(formId, 'submitted');
this.controller.showSummary(formId, '.jvb-form-block');
+
+ // Clean up uploaded files from IndexedDB after successful submission
+ if (window.jvbUploads) {
+ const uploadFields = form.querySelectorAll('[data-upload-field]');
+ for (const field of uploadFields) {
+ const fieldId = window.jvbUploads.determineFieldId(field);
+ await window.jvbUploads.clearFieldFromStores(fieldId);
+ }
+ }
} catch (error) {
- throw error;
+ console.error('Form submission error:', error);
+ this.controller.showFormStatus(formId, 'error');
+
+ // Show user-friendly network error - IMPROVED
+ this.controller.handleFormError(form, {
+ message: 'Network error. Please check your connection and try again.',
+ code: 'network_error'
+ });
} finally {
this.controller.store.delete(formId);
}
}
}
-document.addEventListener('DOMContentLoaded', function() {
- new FormBlock();
+document.addEventListener('DOMContentLoaded', async function() {
+ window.auth.subscribe(event => {
+ if (event === 'auth-loaded') {
+ new FormBlock();
+ }
+ });
});
--
Gitblit v1.10.0