<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Celery example</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/css/bootstrap.min.css"
        integrity="sha512-XWTTruHZEYJsxV3W/lSXG1n3Q39YIWOstqvmFsdNEEQfHoZ6vm6E9GK2OrF6DSJSpIbRbi+Nn0WDPID9O7xB2Q=="
        crossorigin="anonymous" referrerpolicy="no-referrer"/>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-12 col-md-4">
        <form id="your-form">
          <div class="mb-3">
            <label for="email" class="form-label">Email address</label>
            <input type="email" class="form-control" id="email" name="email">
          </div>
          <div class="mb-3">
            <label for="username" class="form-label">Username</label>
            <input type="text" class="form-control" id="username" name="username">
          </div>
          <div class="mb-3" id="messages"></div>
          <button type="submit" class="btn btn-primary">Submit</button>
        </form>
      </div>
    </div>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.min.js"
          integrity="sha512-8Y8eGK92dzouwpROIppwr+0kPauu0qqtnzZZNEF8Pat5tuRNJxJXCkbQfJ0HlUG3y1HB3z18CSKmUo7i2zcPpg=="
          crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script>
    function updateProgress(yourForm, task_id, btnHtml) {
      const ws_url = `/ws/task_status/${task_id}`;
      const WS = new WebSocket((location.protocol === 'https:' ? 'wss' : 'ws') + '://' + window.location.host + ws_url);

      WS.onmessage = function (event) {
        const res = JSON.parse(event.data);
        const taskStatus = res.state;

        if (['SUCCESS', 'FAILURE'].includes(taskStatus)) {
          const msg = yourForm.querySelector('#messages');
          const submitBtn = yourForm.querySelector('button[type="submit"]');

          if (taskStatus === 'SUCCESS') {
            msg.innerHTML = 'job succeeded';
          } else if (taskStatus === 'FAILURE') {
            msg.innerHTML = res.error;
          }

          submitBtn.disabled = false;
          submitBtn.innerHTML = btnHtml;

          // close the websocket because we do not need it now
          WS.close();
        }
      }
    }

    function serialize (data) {
      let obj = {};
      for (let [key, value] of data) {
        if (obj[key] !== undefined) {
          if (!Array.isArray(obj[key])) {
            obj[key] = [obj[key]];
          }
          obj[key].push(value);
        } else {
          obj[key] = value;
        }
      }
      return obj;
    }

    document.addEventListener("DOMContentLoaded", function () {
      const yourForm = document.getElementById("your-form");
      yourForm.addEventListener("submit", function (event) {
        event.preventDefault();
        const submitBtn = yourForm.querySelector('button[type="submit"]');
        const btnHtml = submitBtn.innerHTML;
        const spinnerHtml = 'Processing...';
        submitBtn.disabled = true;
        submitBtn.innerHTML = spinnerHtml;

        const msg = yourForm.querySelector('#messages');
        msg.innerHTML = '';

        // Get all field data from the form
        let data = new FormData(yourForm);
        // Convert to an object
        let formData = serialize(data);

        fetch('/users/form/', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(formData),
        })
        .then(response => response.json())
        .then((res) => {
          // after we get Celery task id, we start polling
          const task_id = res.task_id;
          updateProgress(yourForm, task_id, btnHtml);
          console.log(res);
        }).catch((error) => {
          console.error('Error:', error);
        });
      });
    });
  </script>
</body>
</html>