From af2f97e56e74c1a945a37ed72a6ff92c9d1af8b0 Mon Sep 17 00:00:00 2001
From: f <f@sutty.nl>
Date: Tue, 18 Jun 2024 15:36:13 -0300
Subject: [PATCH] fix: avisar antes de salir si hubo cambios en el formulario

---
 .../controllers/unsaved_changes_controller.js | 45 +++++++++++++++++++
 app/views/posts/_form.haml                    |  2 +-
 config/locales/en.yml                         |  1 +
 config/locales/es.yml                         |  1 +
 4 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100644 app/javascript/controllers/unsaved_changes_controller.js

diff --git a/app/javascript/controllers/unsaved_changes_controller.js b/app/javascript/controllers/unsaved_changes_controller.js
new file mode 100644
index 00000000..04b80f56
--- /dev/null
+++ b/app/javascript/controllers/unsaved_changes_controller.js
@@ -0,0 +1,45 @@
+import { Controller } from "stimulus";
+
+export default class extends Controller {
+  connect() {
+    this.originalFormData = new FormData(this.element);
+    this.originalFormDataSerialized = this.serializeFormData(this.originalFormData);
+    this.submitting = false;
+  }
+
+  submit(event) {
+    this.submitting = true;
+  }
+
+  unsaved(event) {
+    if (this.submitting) return;
+    if (!this.hasChanged()) return;
+
+    this.submitting = false;
+
+    event.preventDefault();
+
+    event.returnValue = true;
+  }
+
+  unsavedTurbolinks(event) {
+    if (this.submitting) return;
+    if (!this.hasChanged()) return;
+
+    this.submitting = false;
+
+    if (window.confirm(this.element.dataset.unsavedChangesConfirmValue)) return;
+
+    event.preventDefault();
+  }
+
+  serializeFormData(formData) {
+    formData.delete("authenticity_token");
+
+    return (new URLSearchParams(formData)).toString();;
+  }
+
+  hasChanged() {
+    return (this.originalFormDataSerialized !== this.serializeFormData(new FormData(this.element)));
+  }
+}
diff --git a/app/views/posts/_form.haml b/app/views/posts/_form.haml
index 8c006274..8a86d203 100644
--- a/app/views/posts/_form.haml
+++ b/app/views/posts/_form.haml
@@ -33,7 +33,7 @@
 - dir = t("locales.#{@locale}.dir")
 
 -# Comienza el formulario
-= form_tag url, method: method, class: "form post #{extra_class}", multipart: true do
+= form_tag url, method: method, class: "form post #{extra_class}", multipart: true, data: { controller: 'unsaved-changes', action: 'unsaved-changes#submit beforeunload@window->unsaved-changes#unsaved turbolinks:before-visit@window->unsaved-changes#unsavedTurbolinks', 'unsaved-changes-confirm-value': t('.confirm') } do
   -# Botones de guardado
   = render 'posts/submit', site: site, post: post
 
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 457b7927..94a6968a 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -814,6 +814,7 @@ en:
     destroy: Delete
     confirm_destroy: Are you sure?
     form:
+      confirm: "You have unsaved changes and changing pages may lose them, continue anyway?"
       errors:
         title: There are some errors on the form
         help: Please, verify that all values are correct.
diff --git a/config/locales/es.yml b/config/locales/es.yml
index d149dee8..fcaa6658 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -822,6 +822,7 @@ es:
     destroy: Borrar
     confirm_destroy: ¿Estás segure?
     form:
+      confirm: "Tenés cambios sin guardar y cambiar de página podría perderlos, ¿querés continuar de todas formas?"
       errors:
         title: Hay errores en el formulario
         help: Por favor, verifica que todos los valores sean correctos.