Jake Vanderwerf
2025-10-20 e729f920139f0c65902be2d6b2c32466b08375e8
src/forms/view.js
@@ -2,80 +2,85 @@
 * 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.querySelectorAll('.jvb-form-block form').forEach(form => {
         this.controller.registerForm(form);
      });
      this.controller.subscribe((event, data) => {
         if (event === 'form-submit') {
            this.handleFormSubmission(data);
         }
      });
   }
   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'] = formId;
      data['form_id'] = form.id;
      let block = form.closest('.jvb-form-block');
      this.controller.showFormStatus(formId, 'uploading');
      try {
         const response = await fetch (`${jvbSettings.api}forms`,
            {
               method: 'POST',
               headers,
               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');
         this.controller.showSummary(formId, '.jvb-form-block');
         this.controller.store.delete(formId);
      } catch (error) {
         throw error;
      }
   }
   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>');
            } else {
               item.querySelector('div').innerHTML = value;
            }
         }
      }
      block.append(summary);
   }
}
document.addEventListener('DOMContentLoaded', function() {
   let formController = new window.jvbForm();
   document.querySelectorAll('.jvb-form-block').forEach(block => {
      const formHandler = formController.registerForm(block.querySelector('form'));
   });
   formController.subscribe((event, data) => {
      if (event === 'form-submit') {
         handleFormSubmission(null, data.data, data.config.element);
      }
   });
   new FormBlock();
});
async function handleFormSubmission(event, data, form) {
   let headers = {
      'X-WP-Nonce': jvbSettings.nonce,
      'Content-Type': 'application/json'
   };
   data['form_type'] = form.dataset.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);
   try {
      const response = await fetch (`${jvbSettings.api}forms`,
         {
            method: 'POST',
            headers,
            body: JSON.stringify(data)
         });
      if (!response.ok) {
         const errorData = await response.json().catch(() => ({}));
         throw new Error(errorData.message|| `Request failed with status ${response.status}`);
      }
      updateUI(await response.json(), block);
   } 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;
   }
   let summary = window.getTemplate('formSummary');
   summary.querySelector('h2').textContent = 'Success!';
   console.log('Form Response: ', response);
   for (let [key, value] of Object.entries(response)) {
      let item = summary.querySelector(`#${key}`);
      let title = item.querySelector('h4');
      if (title.innerText.includes('%s')) {
         title.innerHTML = title.replace('%s', '<b>'+value+'</b>');
      } else {
         item.querySelector('div').innerHTML = value;
      }
   }
   block.append(summary);
}