Bilder: - Neues Hintergrund-System (.page-bg): jede Seite setzt ihr Motiv ueber zwei CSS-Variablen, inkl. eigenem Hochformat-Zuschnitt fuers Handy und Abdunkelung fuer Textlesbarkeit - Hintergruende: Casper, Dogfather, Modi-Team, Scouts, VanVan, Bewerben, Manager, Streamplan, Zeitreise, Stimmen, Community, Werte, Creator - Bewerbungsseite wechselt den Hintergrund mit dem gewaehlten Reiter - Neue Hauptfotos auf der Casper- und der Dogfather-Seite - Stream-Highlight-Bild auf der Streamer-Seite - Funny (Team-Tili-Dog-Abzeichen) und Ghost jetzt mit Bild Inhalt: - Scout-Beschreibung: "Sie finden und begleiten neue Talente fuer Dogi." - Alle Angaben zu Beteiligungen/Verdiensten der Scouts von der Website entfernt — interne Vereinbarungen gehen die Oeffentlichkeit nichts an Co-Authored-By: Claude Opus 5 <[email protected]>
152 lines
5.4 KiB
JavaScript
152 lines
5.4 KiB
JavaScript
/* =====================================================================
|
|
forms.js — Validierung + Versand für die drei Bewerbungsformulare
|
|
(Creator / Scout / Kooperation) auf bewerben.html
|
|
|
|
Versand-Logik:
|
|
1) Wenn API_BASE_URL gesetzt ist (Cloudflare-Worker-Postfach deployed,
|
|
siehe cloudflare-worker/README.md): Bewerbung wird per POST an
|
|
`${API_BASE_URL}/submit` gesendet und landet im code-geschützten
|
|
Postfach (postfach.html).
|
|
2) Solange API_BASE_URL leer ist ODER der Versand fehlschlägt (z.B.
|
|
offline, Worker noch nicht deployed): Fallback auf einen
|
|
vorausgefüllten "mailto:"-Link, wie bisher.
|
|
===================================================================== */
|
|
|
|
// TODO: nach dem Deploy des Cloudflare Workers hier die Worker-URL ohne
|
|
// abschließenden Slash eintragen, z.B.
|
|
// "https://dogfather-universe-postfach.DEIN-ACCOUNT.workers.dev"
|
|
const API_BASE_URL = "https://dogfather-universe-postfach.dogfather1608.workers.dev";
|
|
|
|
const CONTACT_EMAIL = "[email protected]"; // TODO: echte Kontakt-E-Mail eintragen
|
|
|
|
const FORM_TYPES = {
|
|
"form-creator": "creator",
|
|
"form-scout": "scout",
|
|
"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);
|
|
|
|
if (!allValid) {
|
|
if (status) {
|
|
status.textContent = "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 = `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);
|
|
status.innerHTML = `Danke, das sieht super aus! 🩵 Solange noch kein automatischer Versand eingerichtet ist:
|
|
<a href="${mailto}" class="btn btn-outline" style="margin-top:.6rem;">E-Mail jetzt senden</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));
|
|
});
|
|
}
|
|
|
|
/* Der Kopfbereich wechselt sein Hintergrundbild mit dem gewählten Reiter:
|
|
Creator bekommt sein eigenes Motiv, Scout und Kooperation das
|
|
Spicy-Media-Motiv. So passt das Bild immer zur gewählten Bewerbung. */
|
|
const TAB_HINTERGRUENDE = {
|
|
"tab-creator": "bg-bewerben-creator",
|
|
"tab-scout": "bg-bewerben",
|
|
"tab-kooperation": "bg-bewerben",
|
|
};
|
|
|
|
function setzeTabHintergrund(tabId) {
|
|
const hero = document.querySelector(".hero.page-bg");
|
|
const basis = TAB_HINTERGRUENDE[tabId];
|
|
if (!hero || !basis) return;
|
|
hero.style.setProperty("--page-bg", `url('assets/img/${basis}.jpg')`);
|
|
hero.style.setProperty("--page-bg-mobile", `url('assets/img/${basis}-mobile.jpg')`);
|
|
}
|
|
|
|
function setupTabs() {
|
|
const tabs = document.querySelectorAll(".tab-btn");
|
|
const panels = document.querySelectorAll(".tab-panel");
|
|
tabs.forEach((tab) => {
|
|
tab.addEventListener("click", () => {
|
|
tabs.forEach((t) => t.classList.remove("active"));
|
|
panels.forEach((p) => p.classList.remove("active"));
|
|
tab.classList.add("active");
|
|
document.getElementById(tab.dataset.tab).classList.add("active");
|
|
setzeTabHintergrund(tab.dataset.tab);
|
|
});
|
|
});
|
|
|
|
// Beim Laden passend zum bereits aktiven Reiter setzen
|
|
const aktiv = document.querySelector(".tab-btn.active");
|
|
if (aktiv) setzeTabHintergrund(aktiv.dataset.tab);
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
setupTabs();
|
|
setupForm("form-creator", "Creator");
|
|
setupForm("form-scout", "Scout");
|
|
setupForm("form-kooperation", "Kooperation");
|
|
});
|