| | |
| | | * Frontend JavaScript for the Form Block |
| | | * Handles form validation and submission |
| | | */ |
| | | class FormBlock { |
| | | constructor() { |
| | | this.controller = new window.jvbForm(); |
| | | |
| | | // Wait for DOM to be ready |
| | | document.addEventListener('DOMContentLoaded', function() { |
| | | let formController = new window.jvbForm(); |
| | | |
| | | document.querySelectorAll('.jvb-form-block').forEach(block => { |
| | | const formHandler = formController.registerForm(block.querySelector('form')); |
| | | document.querySelectorAll('.jvb-form-block form').forEach(form => { |
| | | this.controller.registerForm(form); |
| | | }); |
| | | formController.subscribe((event, data) => { |
| | | |
| | | this.controller.subscribe((event, data) => { |
| | | if (event === 'form-submit') { |
| | | handleFormSubmission(null, data.data, data.config.element); |
| | | this.handleFormSubmission(data); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | async function handleFormSubmission(event, data, form) { |
| | | async handleFormSubmission(data) { |
| | | let [ |
| | | formId, |
| | | formConfig, |
| | | formData |
| | | ] = [ |
| | | data.formId, |
| | | data.config, |
| | | data.data |
| | | ]; |
| | | let form = formConfig.element; |
| | | |
| | | let headers = { |
| | | 'X-WP-Nonce': jvbSettings.nonce, |
| | | 'Content-Type': 'application/json' |
| | | }; |
| | | |
| | | data['form_type'] = form.dataset.formId; |
| | | data['form_type'] = formId; |
| | | data['form_id'] = form.id; |
| | | let block = form.closest('.jvb-form-block'); |
| | | let loading = window.getTemplate('spinner'); |
| | | form.hidden = true; |
| | | block.classList.add('loading'); |
| | | block.prepend(loading); |
| | | this.controller.showFormStatus(formId, 'uploading'); |
| | | try { |
| | | const response = await fetch (`${jvbSettings.api}forms`, |
| | | { |
| | | method: 'POST', |
| | | headers, |
| | | body: JSON.stringify(data) |
| | | body: JSON.stringify(formData) |
| | | }); |
| | | 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.showFormStatus(formId, 'submitted'); |
| | | |
| | | updateUI(await response.json(), block); |
| | | this.controller.showSummary(formId, '.jvb-form-block'); |
| | | this.controller.store.delete(formId); |
| | | |
| | | } catch (error) { |
| | | throw error; |
| | | } finally { |
| | | block.classList.remove('loading'); |
| | | } |
| | | } |
| | | |
| | | function updateUI(response, block) { |
| | | if (response.success === false) { |
| | | let form = block.querySelector('form'); |
| | | form.removeAttribute('hidden'); |
| | | if ('required' in response) { |
| | | response.required.forEach(required => { |
| | | let item = form.querySelector(`[name=${required}]`); |
| | | item.classList.add('required', 'error'); |
| | | item.scrollIntoView(); |
| | | }); |
| | | } |
| | | return; |
| | | } |
| | | updateUI(response, block) { |
| | | |
| | | let summary = window.getTemplate('formSummary'); |
| | | summary.querySelector('h2').textContent = 'Success!'; |
| | | console.log('Form Response: ', response); |
| | | console.log(summary); |
| | | for (let [key, value] of Object.entries(response)) { |
| | | let item = summary.querySelector(`#${key}`); |
| | | |
| | | if (item) { |
| | | let title = item.querySelector('h4'); |
| | | if (title.innerText.includes('%s')) { |
| | | title.innerHTML = title.replace('%s', '<b>'+value+'</b>'); |
| | |
| | | item.querySelector('div').innerHTML = value; |
| | | } |
| | | } |
| | | } |
| | | block.append(summary); |
| | | } |
| | | } |
| | | |
| | | document.addEventListener('DOMContentLoaded', function() { |
| | | new FormBlock(); |
| | | }); |