From 56e0e15a04593df0760479ca28de354ccd7b8793 Mon Sep 17 00:00:00 2001
From: bytedream <me@bytedream.dev>
Date: Tue, 3 Jun 2025 23:28:31 +0200
Subject: [PATCH] make astro module scripts view transition aware

---
 src/pages/feedback.astro | 147 ++++++++++++++++++-----------------
 src/pages/signup.astro   | 160 +++++++++++++++++++++------------------
 2 files changed, 163 insertions(+), 144 deletions(-)

diff --git a/src/pages/feedback.astro b/src/pages/feedback.astro
index 61330bd..e12ae09 100644
--- a/src/pages/feedback.astro
+++ b/src/pages/feedback.astro
@@ -32,82 +32,91 @@ import Input from '@components/input/Input.svelte';
   import { popupState } from '@components/popup/Popup';
   import { actionErrorPopup } from '../util/action';
 
-  const form = document.getElementById('feedback-contact') as HTMLFormElement;
-  const type = document.getElementById('type') as HTMLSelectElement;
-  const content = document.getElementById('content') as HTMLTextAreaElement;
-  const email = document.getElementById('email') as HTMLInputElement;
+  function setupForm() {
+    const form = document.getElementById('feedback-contact') as HTMLFormElement;
+    const type = document.getElementById('type') as HTMLSelectElement;
+    const content = document.getElementById('content') as HTMLTextAreaElement;
+    const email = document.getElementById('email') as HTMLInputElement;
 
-  // reset form on site (re-)load
-  form.reset();
+    // reset form on site (re-)load
+    form.reset();
 
-  type.addEventListener('change', () => {
-    if (type.value === 'website-feedback') {
-      // content input
-      content.previousElementSibling!.firstChild!.textContent = 'Feedback';
-      // email input
-      email.parentElement!.hidden = true;
-      email.required = false;
-    } else if (type.value === 'website-contact') {
-      // content input
-      content.previousElementSibling!.firstChild!.textContent = 'Anfrage';
-      // email input
-      email.required = true;
-      email.parentElement!.hidden = false;
-    }
-  });
-
-  email.required = false;
-
-  form.addEventListener('submit', async (e) => {
-    e.preventDefault();
-
-    if (type.value === 'website-feedback') {
-      confirmPopupState.set({
-        title: 'Feedback abschicken',
-        message: 'Soll das Feedback abgeschickt werden?',
-        onConfirm: () => sendFeedback().then(() => form.reset())
-      });
-    } else if (type.value === 'website-contact') {
-      confirmPopupState.set({
-        title: 'Kontaktanfrage abschicken',
-        message: 'Soll die Kontaktanfrage abgeschickt werden?',
-        onConfirm: () => sendContact().then(() => form.reset())
-      });
-    }
-  });
-
-  async function sendFeedback() {
-    const { error } = await actions.feedback.addWebsiteFeedback({
-      content: content.value
+    type.addEventListener('change', () => {
+      if (type.value === 'website-feedback') {
+        // content input
+        content.previousElementSibling!.firstChild!.textContent = 'Feedback';
+        // email input
+        email.parentElement!.hidden = true;
+        email.required = false;
+      } else if (type.value === 'website-contact') {
+        // content input
+        content.previousElementSibling!.firstChild!.textContent = 'Anfrage';
+        // email input
+        email.required = true;
+        email.parentElement!.hidden = false;
+      }
     });
 
-    if (error) {
-      actionErrorPopup(error);
-      return;
-    }
+    email.required = false;
 
-    popupState.set({
-      type: 'info',
-      title: 'Feedback abgeschickt',
-      message: 'Dein Feedback wurde abgeschickt. Vielen Dank, dass du uns hilfst, das Projekt besser zu machen!'
+    form.addEventListener('submit', async (e) => {
+      e.preventDefault();
+
+      if (type.value === 'website-feedback') {
+        confirmPopupState.set({
+          title: 'Feedback abschicken',
+          message: 'Soll das Feedback abgeschickt werden?',
+          onConfirm: () => sendFeedback().then(() => form.reset())
+        });
+      } else if (type.value === 'website-contact') {
+        confirmPopupState.set({
+          title: 'Kontaktanfrage abschicken',
+          message: 'Soll die Kontaktanfrage abgeschickt werden?',
+          onConfirm: () => sendContact().then(() => form.reset())
+        });
+      }
     });
+
+    const sendFeedback = async () => {
+      const { error } = await actions.feedback.addWebsiteFeedback({
+        content: content.value
+      });
+
+      if (error) {
+        actionErrorPopup(error);
+        return;
+      }
+
+      popupState.set({
+        type: 'info',
+        title: 'Feedback abgeschickt',
+        message: 'Dein Feedback wurde abgeschickt. Vielen Dank, dass du uns hilfst, das Projekt besser zu machen!'
+      });
+    };
+
+    const sendContact = async () => {
+      const { error } = await actions.feedback.addWebsiteContact({
+        content: content.value,
+        email: email.value
+      });
+
+      if (error) {
+        actionErrorPopup(error);
+        return;
+      }
+
+      popupState.set({
+        type: 'info',
+        title: 'Kontaktanfrage abgeschickt',
+        message: 'Deine Kontaktanfrage wurde abgeschickt. Jemand aus dem Team wird sich nächstmöglich bei Dir melden.'
+      });
+    };
   }
 
-  async function sendContact() {
-    const { error } = await actions.feedback.addWebsiteContact({
-      content: content.value,
-      email: email.value
-    });
+  const pathname = document.location.pathname;
+  document.addEventListener('astro:page-load', () => {
+    if (document.location.pathname !== pathname) return;
 
-    if (error) {
-      actionErrorPopup(error);
-      return;
-    }
-
-    popupState.set({
-      type: 'info',
-      title: 'Kontaktanfrage abgeschickt',
-      message: 'Deine Kontaktanfrage wurde abgeschickt. Jemand aus dem Team wird sich nächstmöglich bei Dir melden.'
-    });
-  }
+    setupForm();
+  });
 </script>
diff --git a/src/pages/signup.astro b/src/pages/signup.astro
index ab9aaae..95c9916 100644
--- a/src/pages/signup.astro
+++ b/src/pages/signup.astro
@@ -155,89 +155,99 @@ const signupDisabledSubMessage = signupSetting[SettingKey.SignupDisabledSubMessa
   import { teamPopupName, teamPopupOpen } from '@app/website/signup/TeamPopup';
   import { registeredPopupState } from '@app/website/signup/RegisteredPopup';
 
-  /* ----- client validation ----- */
-  const rulesCheckbox = document.getElementById('rules')! as HTMLInputElement;
-  const rulesCheckboxRulesLink = rulesCheckbox.nextElementSibling!.querySelector('.link') as HTMLAnchorElement;
+  function setupClientValidation() {
+    const rulesCheckbox = document.getElementById('rules') as HTMLInputElement;
+    const rulesCheckboxRulesLink = rulesCheckbox.nextElementSibling!.querySelector('.link') as HTMLAnchorElement;
 
-  // add popup state subscriber to check when the accepted button is clicked
-  rulesPopupState.subscribe((value) => {
-    if (value == 'accepted') rulesCheckbox.checked = true;
-  });
-
-  // add click handler to open rules popup to rules checkbox
-  rulesCheckbox.addEventListener('click', (e) => {
-    if (!rulesPopupRead.get()) {
-      e.preventDefault();
-      rulesPopupState.set('open');
-    }
-  });
-
-  // add click handler to open rules popup when clicking the rules link in the rules checkbox label
-  rulesCheckboxRulesLink!.addEventListener('click', () => rulesPopupState.set('open'));
-
-  /* ----- signup form ----- */
-  const form = document.getElementById('signup')! as HTMLFormElement;
-
-  // reset form on site (re-)load
-  form.reset();
-
-  async function sendSignup() {
-    const { data, error } = await actions.signup.signup({
-      firstname: form.firstname.value,
-      lastname: form.lastname.value,
-      birthday: form.birthday.value,
-      phone: form.phone.value,
-      username: form.username.value,
-      teamMember: form.teamMember.value,
-      teamName: teamPopupName.get()
+    // add popup state subscriber to check when the accepted button is clicked
+    rulesPopupState.subscribe((value) => {
+      if (value == 'accepted') rulesCheckbox.checked = true;
     });
 
-    // must be done in order to show the team popup again if it's closed or an error occurs
-    teamPopupName.set(null);
-
-    if (error) {
-      if (error.code == 'BAD_REQUEST') {
-        teamPopupOpen.set(true);
-        const close = teamPopupName.listen(() => {
-          close();
-          sendSignup();
-        });
-      } else if (error.code == 'CONFLICT' || error.code == 'FORBIDDEN') {
-        popupState.set({
-          type: 'error',
-          title: 'Fehler',
-          message: error.message
-        });
-      } else {
-        popupState.set({
-          type: 'error',
-          title: 'Fehler',
-          message: error.message
-        });
+    // add click handler to open rules popup to rules checkbox
+    rulesCheckbox.addEventListener('click', (e) => {
+      if (!rulesPopupRead.get()) {
+        e.preventDefault();
+        rulesPopupState.set('open');
       }
-      return;
-    }
-
-    registeredPopupState.set({
-      firstname: form.firstname.value,
-      lastname: form.lastname.value,
-      birthday: form.birthday.value,
-      phone: form.phone.value,
-      username: form.username.value,
-      team: data.team.name,
-      teamMember: form.teamMember.value,
-      teamColor: data.team.color
     });
 
-    const cancel = registeredPopupState.subscribe((value) => {
-      if (value) return;
-      cancel();
-      form.reset();
+    // add click handler to open rules popup when clicking the rules link in the rules checkbox label
+    rulesCheckboxRulesLink!.addEventListener('click', () => rulesPopupState.set('open'));
+  }
+
+  function setupForm() {
+    const form = document.getElementById('signup')! as HTMLFormElement;
+
+    // reset form on site (re-)load
+    form.reset();
+
+    const sendSignup = async () => {
+      const { data, error } = await actions.signup.signup({
+        firstname: form.firstname.value,
+        lastname: form.lastname.value,
+        birthday: form.birthday.value,
+        phone: form.phone.value,
+        username: form.username.value,
+        teamMember: form.teamMember.value,
+        teamName: teamPopupName.get()
+      });
+
+      // must be done in order to show the team popup again if it's closed or an error occurs
+      teamPopupName.set(null);
+
+      if (error) {
+        if (error.code == 'BAD_REQUEST') {
+          teamPopupOpen.set(true);
+          const close = teamPopupName.listen(() => {
+            close();
+            sendSignup();
+          });
+        } else if (error.code == 'CONFLICT' || error.code == 'FORBIDDEN') {
+          popupState.set({
+            type: 'error',
+            title: 'Fehler',
+            message: error.message
+          });
+        } else {
+          popupState.set({
+            type: 'error',
+            title: 'Fehler',
+            message: error.message
+          });
+        }
+        return;
+      }
+
+      registeredPopupState.set({
+        firstname: form.firstname.value,
+        lastname: form.lastname.value,
+        birthday: form.birthday.value,
+        phone: form.phone.value,
+        username: form.username.value,
+        team: data.team.name,
+        teamMember: form.teamMember.value,
+        teamColor: data.team.color
+      });
+
+      const cancel = registeredPopupState.subscribe((value) => {
+        if (value) return;
+        cancel();
+        form.reset();
+      });
+    };
+
+    form.addEventListener('submit', (e) => {
+      e.preventDefault();
+      sendSignup();
     });
   }
 
-  form.addEventListener('submit', (e) => {
-    e.preventDefault();
-    sendSignup();
+  const pathname = document.location.pathname;
+  document.addEventListener('astro:page-load', () => {
+    if (document.location.pathname !== pathname) return;
+
+    setupClientValidation();
+    setupForm();
   });
 </script>