Files
dogfather-universe/assets/js/forms.js
T

132 lines
4.8 KiB
JavaScript

/* =====================================================================
forms.js — Validierung + Versand für die Bewerbungsformulare
(Creator: bewerben-creator.html, Scout: bewerben-scout.html,
Modi: bewerben-modi.html, Kooperation: bewerben-kooperation.html)
Jede Bewerbungsart hat ihre eigene Seite (kein Tab-System mehr) —
Hintergrundbild und Farbwelt sitzen wie überall sonst auf der Website
fest im HTML jeder Seite selbst.
Versand-Logik:
1) Bewerbung wird per POST an `${API_BASE_URL}/submit` an den
Cloudflare-Worker gesendet und landet im code-geschützten Postfach
(postfach.html).
2) Schlägt der Versand fehl (z.B. offline): Fallback auf einen
vorausgefüllten "mailto:"-Link.
===================================================================== */
const API_BASE_URL = "https://dogfather-universe-postfach.dogfather1608.workers.dev";
const CONTACT_EMAIL = "[email protected]";
const FORM_TYPES = {
"form-creator": "creator",
"form-scout": "scout",
"form-modi": "modi",
"form-kooperation": "kooperation",
};
function validateField(field) {
const wrapper = field.closest(".field");
if (!wrapper) return true;
let valid = field.checkValidity();
if (valid && field.type === "email" && field.value) {
valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(field.value);
}
wrapper.classList.toggle("has-error", !valid);
return valid;
}
function buildMailto(subjectLabel, data) {
const lines = [...data.entries()].map(([k, v]) => `${k}: ${v}`).join("\n");
return `mailto:${CONTACT_EMAIL}?subject=${encodeURIComponent(
"Bewerbung: " + subjectLabel
)}&body=${encodeURIComponent(lines)}`;
}
async function submitToWorker(type, data) {
if (!API_BASE_URL) return false;
const payload = { type, data: Object.fromEntries(data.entries()) };
try {
const res = await fetch(`${API_BASE_URL}/submit`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (!res.ok) return false;
const json = await res.json();
return !!json.ok;
} catch {
return false; // z.B. offline oder Worker nicht erreichbar -> Fallback greift
}
}
function setupForm(formId, subjectLabel) {
const form = document.getElementById(formId);
if (!form) return;
const status = form.querySelector(".form-status");
const type = FORM_TYPES[formId];
form.addEventListener("submit", async (e) => {
e.preventDefault();
const fields = [...form.querySelectorAll("input[required], select[required], textarea[required], input[type=email]")];
const allValid = fields.map(validateField).every(Boolean);
// Rein per JS gesetzte Statusmeldungen — Übersetzung über
// window.dogiUebersetzen() (siehe main.js), Wörterbuch kommt aus dem
// seiteneigenen assets/js/i18n-bewerben-*.js der jeweiligen Seite.
// Deutscher Text bleibt Fallback, falls ein Key mal fehlen sollte.
if (!allValid) {
if (status) {
status.textContent = window.dogiUebersetzen
? window.dogiUebersetzen("form_error_validation")
: "Bitte prüfe die markierten Felder — es fehlt noch etwas.";
status.className = "form-status show error";
}
return;
}
const data = new FormData(form);
const submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) submitBtn.disabled = true;
const delivered = await submitToWorker(type, data);
if (status) {
if (delivered) {
status.innerHTML = window.dogiUebersetzen
? window.dogiUebersetzen("form_success_delivered")
: `Danke, das sieht super aus! 🩵 Deine Bewerbung ist sicher im Postfach von Team Dogi angekommen.`;
status.className = "form-status show success";
} else {
const mailto = buildMailto(subjectLabel, data);
const introText = window.dogiUebersetzen
? window.dogiUebersetzen("form_success_fallback")
: `Danke, das sieht super aus! 🩵 Solange noch kein automatischer Versand eingerichtet ist:`;
const btnText = window.dogiUebersetzen
? window.dogiUebersetzen("form_success_fallback_btn")
: "E-Mail jetzt senden";
status.innerHTML = `${introText}
<a href="${mailto}" class="btn btn-outline" style="margin-top:.6rem;">${btnText}</a>`;
status.className = "form-status show success";
}
}
if (submitBtn) submitBtn.disabled = false;
form.reset();
});
form.querySelectorAll("input, select, textarea").forEach((field) => {
field.addEventListener("blur", () => validateField(field));
});
}
document.addEventListener("DOMContentLoaded", () => {
setupForm("form-creator", "Creator");
setupForm("form-scout", "Scout");
setupForm("form-modi", "Modi");
setupForm("form-kooperation", "Kooperation");
});