make astro module scripts view transition aware

This commit is contained in:
bytedream 2025-06-03 23:28:31 +02:00
parent e09a232f3c
commit 56e0e15a04
2 changed files with 163 additions and 144 deletions

View File

@ -32,82 +32,91 @@ import Input from '@components/input/Input.svelte';
import { popupState } from '@components/popup/Popup'; import { popupState } from '@components/popup/Popup';
import { actionErrorPopup } from '../util/action'; import { actionErrorPopup } from '../util/action';
const form = document.getElementById('feedback-contact') as HTMLFormElement; function setupForm() {
const type = document.getElementById('type') as HTMLSelectElement; const form = document.getElementById('feedback-contact') as HTMLFormElement;
const content = document.getElementById('content') as HTMLTextAreaElement; const type = document.getElementById('type') as HTMLSelectElement;
const email = document.getElementById('email') as HTMLInputElement; const content = document.getElementById('content') as HTMLTextAreaElement;
const email = document.getElementById('email') as HTMLInputElement;
// reset form on site (re-)load // reset form on site (re-)load
form.reset(); form.reset();
type.addEventListener('change', () => { type.addEventListener('change', () => {
if (type.value === 'website-feedback') { if (type.value === 'website-feedback') {
// content input // content input
content.previousElementSibling!.firstChild!.textContent = 'Feedback'; content.previousElementSibling!.firstChild!.textContent = 'Feedback';
// email input // email input
email.parentElement!.hidden = true; email.parentElement!.hidden = true;
email.required = false; email.required = false;
} else if (type.value === 'website-contact') { } else if (type.value === 'website-contact') {
// content input // content input
content.previousElementSibling!.firstChild!.textContent = 'Anfrage'; content.previousElementSibling!.firstChild!.textContent = 'Anfrage';
// email input // email input
email.required = true; email.required = true;
email.parentElement!.hidden = false; 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
}); });
if (error) { email.required = false;
actionErrorPopup(error);
return;
}
popupState.set({ form.addEventListener('submit', async (e) => {
type: 'info', e.preventDefault();
title: 'Feedback abgeschickt',
message: 'Dein Feedback wurde abgeschickt. Vielen Dank, dass du uns hilfst, das Projekt besser zu machen!' 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 pathname = document.location.pathname;
const { error } = await actions.feedback.addWebsiteContact({ document.addEventListener('astro:page-load', () => {
content: content.value, if (document.location.pathname !== pathname) return;
email: email.value
});
if (error) { setupForm();
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.'
});
}
</script> </script>

View File

@ -155,89 +155,99 @@ const signupDisabledSubMessage = signupSetting[SettingKey.SignupDisabledSubMessa
import { teamPopupName, teamPopupOpen } from '@app/website/signup/TeamPopup'; import { teamPopupName, teamPopupOpen } from '@app/website/signup/TeamPopup';
import { registeredPopupState } from '@app/website/signup/RegisteredPopup'; import { registeredPopupState } from '@app/website/signup/RegisteredPopup';
/* ----- client validation ----- */ function setupClientValidation() {
const rulesCheckbox = document.getElementById('rules')! as HTMLInputElement; const rulesCheckbox = document.getElementById('rules') as HTMLInputElement;
const rulesCheckboxRulesLink = rulesCheckbox.nextElementSibling!.querySelector('.link') as HTMLAnchorElement; const rulesCheckboxRulesLink = rulesCheckbox.nextElementSibling!.querySelector('.link') as HTMLAnchorElement;
// add popup state subscriber to check when the accepted button is clicked // add popup state subscriber to check when the accepted button is clicked
rulesPopupState.subscribe((value) => { rulesPopupState.subscribe((value) => {
if (value == 'accepted') rulesCheckbox.checked = true; 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()
}); });
// must be done in order to show the team popup again if it's closed or an error occurs // add click handler to open rules popup to rules checkbox
teamPopupName.set(null); rulesCheckbox.addEventListener('click', (e) => {
if (!rulesPopupRead.get()) {
if (error) { e.preventDefault();
if (error.code == 'BAD_REQUEST') { rulesPopupState.set('open');
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) => { // add click handler to open rules popup when clicking the rules link in the rules checkbox label
if (value) return; rulesCheckboxRulesLink!.addEventListener('click', () => rulesPopupState.set('open'));
cancel(); }
form.reset();
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) => { const pathname = document.location.pathname;
e.preventDefault(); document.addEventListener('astro:page-load', () => {
sendSignup(); if (document.location.pathname !== pathname) return;
setupClientValidation();
setupForm();
}); });
</script> </script>