Rechtsseiten crawlbar: /datenschutz /agb /impressum als eigenständige HTML-Seiten (einzige Quelle, indexierbar) statt 302→Hash; SPA-Module holen Inhalt per fetch+inject (kein Text-Duplikat); Kontaktformular in geteilte contact-form.js; Sitemap+SW ergänzt, v1278
This commit is contained in:
parent
43b6292d08
commit
40d117874b
13 changed files with 1047 additions and 782 deletions
|
|
@ -1,176 +1,28 @@
|
|||
/* ============================================================
|
||||
BAN YARO — Impressum
|
||||
BAN YARO — Impressum (SPA-Wrapper)
|
||||
Einzige Inhaltsquelle: /impressum.html (crawlbar). Diese Seite
|
||||
holt den Inhalt per fetch und injiziert ihn — kein Text-Duplikat.
|
||||
Das Kontaktformular wird über die geteilte contact-form.js gebunden.
|
||||
============================================================ */
|
||||
|
||||
window.Page_impressum = (() => {
|
||||
|
||||
function init(container) {
|
||||
container.innerHTML = `
|
||||
<div style="max-width:640px;margin:0 auto;padding:var(--space-6) var(--space-4)">
|
||||
|
||||
<h1 style="font-size:var(--text-2xl);font-weight:var(--weight-bold);
|
||||
color:var(--c-text);margin:0 0 var(--space-6)">Impressum</h1>
|
||||
|
||||
<section style="margin-bottom:var(--space-6)">
|
||||
<h2 style="font-size:var(--text-base);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text);margin:0 0 var(--space-2)">Angaben gemäß § 5 DDG</h2>
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.7;margin:0">
|
||||
René Degelmann<br>
|
||||
Ringstr. 26<br>
|
||||
85560 Ebersberg
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section style="margin-bottom:var(--space-6)">
|
||||
<h2 style="font-size:var(--text-base);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text);margin:0 0 var(--space-2)">Kontakt</h2>
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.7;margin:0 0 var(--space-4)">
|
||||
E-Mail: <a href="mailto:hallo@banyaro.app"
|
||||
class="text-primary">hallo@banyaro.app</a><br>
|
||||
Oder nutze das Formular — wir antworten in der Regel innerhalb von 24 Stunden.
|
||||
</p>
|
||||
|
||||
<form id="contact-form" class="flex-col-gap-3">
|
||||
<div class="grid-2">
|
||||
<div>
|
||||
<label for="cf-name" style="display:block;font-size:var(--text-xs);font-weight:600;margin-bottom:4px;color:var(--c-text)">Name *</label>
|
||||
<input id="cf-name" type="text" required maxlength="100"
|
||||
placeholder="Dein Name"
|
||||
style="width:100%;padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);
|
||||
border:1.5px solid var(--c-border);background:var(--c-surface);
|
||||
color:var(--c-text);font-size:var(--text-sm);box-sizing:border-box">
|
||||
</div>
|
||||
<div>
|
||||
<label for="cf-email" style="display:block;font-size:var(--text-xs);font-weight:600;margin-bottom:4px;color:var(--c-text)">E-Mail *</label>
|
||||
<input id="cf-email" type="email" required maxlength="200"
|
||||
placeholder="deine@email.de"
|
||||
style="width:100%;padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);
|
||||
border:1.5px solid var(--c-border);background:var(--c-surface);
|
||||
color:var(--c-text);font-size:var(--text-sm);box-sizing:border-box">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="cf-subject" style="display:block;font-size:var(--text-xs);font-weight:600;margin-bottom:4px;color:var(--c-text)">Betreff *</label>
|
||||
<input id="cf-subject" type="text" required maxlength="150"
|
||||
placeholder="Worum geht es?"
|
||||
style="width:100%;padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);
|
||||
border:1.5px solid var(--c-border);background:var(--c-surface);
|
||||
color:var(--c-text);font-size:var(--text-sm);box-sizing:border-box">
|
||||
</div>
|
||||
<div>
|
||||
<label for="cf-message" style="display:block;font-size:var(--text-xs);font-weight:600;margin-bottom:4px;color:var(--c-text)">Nachricht *</label>
|
||||
<textarea id="cf-message" required maxlength="3000" rows="5"
|
||||
placeholder="Deine Nachricht…"
|
||||
style="width:100%;padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);
|
||||
border:1.5px solid var(--c-border);background:var(--c-surface);
|
||||
color:var(--c-text);font-size:var(--text-sm);resize:vertical;
|
||||
font-family:inherit;box-sizing:border-box"></textarea>
|
||||
</div>
|
||||
<div id="cf-status" style="display:none;padding:var(--space-2) var(--space-3);
|
||||
border-radius:var(--radius-md);font-size:var(--text-sm)"></div>
|
||||
<button id="cf-submit" type="submit"
|
||||
style="align-self:flex-start;padding:var(--space-2) var(--space-5);
|
||||
border-radius:var(--radius-full);border:none;cursor:pointer;
|
||||
background:var(--c-primary);color:#fff;font-size:var(--text-sm);
|
||||
font-weight:600">
|
||||
Nachricht senden
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section style="margin-bottom:var(--space-6)">
|
||||
<h2 style="font-size:var(--text-base);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text);margin:0 0 var(--space-2)">Verantwortlich für den Inhalt
|
||||
gemäß § 18 Abs. 2 MStV</h2>
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.7;margin:0">
|
||||
René Degelmann<br>
|
||||
(Anschrift wie oben)
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section style="margin-bottom:var(--space-6)">
|
||||
<h2 style="font-size:var(--text-base);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text);margin:0 0 var(--space-2)">Streitschlichtung</h2>
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.7;margin:0">
|
||||
Wir sind nicht bereit und nicht verpflichtet, an einem Streitbeilegungsverfahren vor einer
|
||||
Verbraucherschlichtungsstelle teilzunehmen (§ 36 VSBG).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section style="margin-bottom:var(--space-6)">
|
||||
<h2 style="font-size:var(--text-base);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text);margin:0 0 var(--space-2)">Haftungshinweis</h2>
|
||||
<p style="font-size:var(--text-sm);color:var(--c-text-secondary);line-height:1.7;margin:0">
|
||||
Die Inhalte dieser App wurden mit größtmöglicher Sorgfalt erstellt. Für die Richtigkeit,
|
||||
Vollständigkeit und Aktualität der Inhalte übernehmen wir keine Gewähr. Als
|
||||
Diensteanbieter sind wir gemäß § 7 Abs. 1 DDG für eigene Inhalte verantwortlich.
|
||||
Für nutzergenerierte Inhalte (Forenbeiträge, Fotos, Kommentare) sind ausschließlich
|
||||
die jeweiligen Nutzer verantwortlich. Bei Bekanntwerden rechtswidriger Inhalte werden
|
||||
diese im Rahmen der gesetzlichen Vorgaben (§§ 7 ff. DDG) geprüft und gegebenenfalls
|
||||
unverzüglich entfernt.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<p style="font-size:var(--text-xs);color:var(--c-text-muted);margin:0">
|
||||
Stand: Mai 2026
|
||||
</p>
|
||||
|
||||
</div>
|
||||
`;
|
||||
async function init(container) {
|
||||
try {
|
||||
const res = await fetch('/impressum');
|
||||
const html = await res.text();
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
const content = doc.querySelector('#legal-content');
|
||||
container.innerHTML = content
|
||||
? content.innerHTML
|
||||
: '<p style="padding:var(--space-4);color:var(--c-text-secondary)">Inhalt momentan nicht verfügbar.</p>';
|
||||
window.initContactForm?.(container);
|
||||
} catch (e) {
|
||||
container.innerHTML = '<p style="padding:var(--space-4);color:var(--c-text-secondary)">Das Impressum ist offline nicht verfügbar — bitte einmal mit Internetverbindung öffnen.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
function _initContactForm(container) {
|
||||
const form = container.querySelector('#contact-form');
|
||||
const statusEl = container.querySelector('#cf-status');
|
||||
const submitBtn = container.querySelector('#cf-submit');
|
||||
if (!form) return;
|
||||
|
||||
form.addEventListener('submit', async e => {
|
||||
e.preventDefault();
|
||||
const name = container.querySelector('#cf-name').value.trim();
|
||||
const email = container.querySelector('#cf-email').value.trim();
|
||||
const subject = container.querySelector('#cf-subject').value.trim();
|
||||
const message = container.querySelector('#cf-message').value.trim();
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = 'Wird gesendet…';
|
||||
statusEl.style.display = 'none';
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/contact', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, email, subject, message }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err.detail || 'Fehler beim Senden.');
|
||||
}
|
||||
statusEl.style.display = 'block';
|
||||
statusEl.style.background = 'var(--c-success-bg, #f0fdf4)';
|
||||
statusEl.style.color = 'var(--c-success, #16a34a)';
|
||||
statusEl.textContent = '✓ Nachricht gesendet — wir melden uns bald!';
|
||||
form.reset();
|
||||
} catch (err) {
|
||||
statusEl.style.display = 'block';
|
||||
statusEl.style.background = '#fef2f2';
|
||||
statusEl.style.color = '#dc2626';
|
||||
statusEl.textContent = err.message || 'Fehler beim Senden. Bitte versuche es später erneut.';
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = 'Nachricht senden';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const _origInit = init;
|
||||
|
||||
function refresh() {}
|
||||
|
||||
return {
|
||||
init(container) {
|
||||
_origInit(container);
|
||||
_initContactForm(container);
|
||||
},
|
||||
refresh
|
||||
};
|
||||
return { init, refresh };
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue