mirror of
https://github.com/superschnups/Emy.git
synced 2026-06-22 03:13:10 +00:00
origin
This commit is contained in:
parent
4558a1638b
commit
b8e4f6c20b
16 changed files with 1324 additions and 317 deletions
|
|
@ -15,10 +15,17 @@ const DATA_FILE = path.join(__dirname, 'data/gallery.json');
|
|||
const HOMEPAGE_FILE = path.join(__dirname, 'data/homepage.json');
|
||||
const CATEGORIES_FILE = path.join(__dirname, 'data/categories.json');
|
||||
const UEBERMICH_FILE = path.join(__dirname, 'data/uebermich.json');
|
||||
const ERFOLGE_FILE = path.join(__dirname, 'data/erfolge.json');
|
||||
const ERFOLGE_IMG_DIR = path.join(__dirname, 'static/erfolge-img');
|
||||
const GALERIE_PAGE_FILE = path.join(__dirname, 'data/galerie.json');
|
||||
const GAESTEBUCH_FILE = path.join(__dirname, 'data/gaestebuch.json');
|
||||
const GLOBAL_FILE = path.join(__dirname, 'data/global.json');
|
||||
const GAESTEBUCH_IMG_DIR = path.join(__dirname, 'static/gaestebuch-img');
|
||||
|
||||
if (!fs.existsSync(UEBERMICH_IMG_DIR)) fs.mkdirSync(UEBERMICH_IMG_DIR, { recursive: true });
|
||||
|
||||
if (!fs.existsSync(HERO_DIR)) fs.mkdirSync(HERO_DIR, { recursive: true });
|
||||
if (!fs.existsSync(ERFOLGE_IMG_DIR)) fs.mkdirSync(ERFOLGE_IMG_DIR, { recursive: true });
|
||||
if (!fs.existsSync(GAESTEBUCH_IMG_DIR)) fs.mkdirSync(GAESTEBUCH_IMG_DIR, { recursive: true });
|
||||
|
||||
app.use(express.json());
|
||||
app.use('/images', express.static(IMAGES_DIR));
|
||||
|
|
@ -164,9 +171,14 @@ function rebuildAndDeploy() {
|
|||
|
||||
app.put('/api/homepage', (req, res) => {
|
||||
const hp = readHomepage();
|
||||
if (req.body.siteTitle !== undefined) hp.siteTitle = req.body.siteTitle;
|
||||
if (req.body.badge !== undefined) hp.hero.badge = req.body.badge;
|
||||
if (req.body.description !== undefined) hp.hero.description = req.body.description;
|
||||
if (req.body.stats !== undefined) hp.stats = req.body.stats;
|
||||
if (req.body.hero_karte !== undefined) hp.hero_karte = req.body.hero_karte;
|
||||
if (req.body.pruefung_karte !== undefined) hp.pruefung_karte = req.body.pruefung_karte;
|
||||
if (req.body.dojo_karte !== undefined) hp.dojo_karte = req.body.dojo_karte;
|
||||
if (req.body.cta !== undefined) hp.cta = req.body.cta;
|
||||
writeHomepage(hp);
|
||||
res.json({ ok: true });
|
||||
rebuildAndDeploy();
|
||||
|
|
@ -191,6 +203,8 @@ app.post('/api/homepage/image', upload.single('image'), async (req, res) => {
|
|||
|
||||
app.use('/hero', express.static(HERO_DIR));
|
||||
app.use('/uebermich', express.static(UEBERMICH_IMG_DIR));
|
||||
app.use('/erfolge-img', express.static(ERFOLGE_IMG_DIR));
|
||||
app.use('/gaestebuch-img', express.static(GAESTEBUCH_IMG_DIR));
|
||||
|
||||
// Über mich API
|
||||
function readUebermich() {
|
||||
|
|
@ -228,6 +242,87 @@ app.post('/api/uebermich/image', upload.single('image'), async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
// ── Erfolge API ───────────────────────────────────────────────
|
||||
function readErfolge() {
|
||||
return JSON.parse(fs.readFileSync(ERFOLGE_FILE, 'utf8'));
|
||||
}
|
||||
function writeErfolge(data) {
|
||||
fs.writeFileSync(ERFOLGE_FILE, JSON.stringify(data, null, 2));
|
||||
}
|
||||
|
||||
app.get('/api/erfolge', (req, res) => {
|
||||
res.json(readErfolge());
|
||||
});
|
||||
|
||||
app.put('/api/erfolge', (req, res) => {
|
||||
writeErfolge(req.body);
|
||||
res.json({ ok: true });
|
||||
rebuildAndDeploy();
|
||||
});
|
||||
|
||||
app.post('/api/erfolge/image', upload.single('image'), async (req, res) => {
|
||||
try {
|
||||
const filename = 'hero.webp';
|
||||
await sharp(req.file.buffer)
|
||||
.resize(1200, 1500, { fit: 'inside', withoutEnlargement: true })
|
||||
.webp({ quality: 88 })
|
||||
.toFile(path.join(ERFOLGE_IMG_DIR, filename));
|
||||
const data = readErfolge();
|
||||
data.hero.image = filename;
|
||||
writeErfolge(data);
|
||||
res.json({ ok: true, image: filename });
|
||||
rebuildAndDeploy();
|
||||
} catch (e) {
|
||||
res.status(500).json({ ok: false, error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ── Galerie Seiten-Texte API ──────────────────────────────────
|
||||
app.get('/api/galerie', (req, res) => {
|
||||
res.json(JSON.parse(fs.readFileSync(GALERIE_PAGE_FILE, 'utf8')));
|
||||
});
|
||||
app.put('/api/galerie', (req, res) => {
|
||||
fs.writeFileSync(GALERIE_PAGE_FILE, JSON.stringify(req.body, null, 2));
|
||||
res.json({ ok: true });
|
||||
rebuildAndDeploy();
|
||||
});
|
||||
|
||||
// ── Gästebuch API ─────────────────────────────────────────────
|
||||
app.get('/api/gaestebuch', (req, res) => {
|
||||
res.json(JSON.parse(fs.readFileSync(GAESTEBUCH_FILE, 'utf8')));
|
||||
});
|
||||
app.put('/api/gaestebuch', (req, res) => {
|
||||
fs.writeFileSync(GAESTEBUCH_FILE, JSON.stringify(req.body, null, 2));
|
||||
res.json({ ok: true });
|
||||
rebuildAndDeploy();
|
||||
});
|
||||
app.post('/api/gaestebuch/image', upload.single('image'), async (req, res) => {
|
||||
try {
|
||||
const filename = 'hero.webp';
|
||||
await sharp(req.file.buffer)
|
||||
.resize(1400, 600, { fit: 'cover', position: 'center' })
|
||||
.webp({ quality: 88 })
|
||||
.toFile(path.join(GAESTEBUCH_IMG_DIR, filename));
|
||||
const data = JSON.parse(fs.readFileSync(GAESTEBUCH_FILE, 'utf8'));
|
||||
data.hero.image = filename;
|
||||
fs.writeFileSync(GAESTEBUCH_FILE, JSON.stringify(data, null, 2));
|
||||
res.json({ ok: true, image: filename });
|
||||
rebuildAndDeploy();
|
||||
} catch (e) {
|
||||
res.status(500).json({ ok: false, error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ── Global (Social Links) API ─────────────────────────────────
|
||||
app.get('/api/global', (req, res) => {
|
||||
res.json(JSON.parse(fs.readFileSync(GLOBAL_FILE, 'utf8')));
|
||||
});
|
||||
app.put('/api/global', (req, res) => {
|
||||
fs.writeFileSync(GLOBAL_FILE, JSON.stringify(req.body, null, 2));
|
||||
res.json({ ok: true });
|
||||
rebuildAndDeploy();
|
||||
});
|
||||
|
||||
// Admin-UI
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'admin.html'));
|
||||
|
|
|
|||
866
admin.html
866
admin.html
|
|
@ -103,7 +103,7 @@ tailwind.config = {
|
|||
<span class="material-symbols-outlined" style="font-variation-settings:'FILL' 1;">bolt</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-xl font-black text-primary font-lexend">MiyaKarate</h1>
|
||||
<h1 class="text-xl font-black text-primary font-lexend" id="adminSiteTitle">MiyaKarate</h1>
|
||||
<p class="text-[10px] uppercase tracking-widest text-zinc-500 font-bold">Admin Panel</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -178,7 +178,7 @@ tailwind.config = {
|
|||
</button>
|
||||
<div class="flex items-center gap-3 bg-surface-container-low px-4 py-2 rounded-full">
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-primary to-primary-container flex items-center justify-center text-white text-xs font-black">M</div>
|
||||
<span class="font-lexend font-bold text-sm">MiyaKarate</span>
|
||||
<span class="font-lexend font-bold text-sm" id="adminSiteTitleHeader">MiyaKarate</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
@ -265,6 +265,46 @@ tailwind.config = {
|
|||
<!-- ══ SECTION: MEDIA LIBRARY ══ -->
|
||||
<div id="section-media" class="hidden">
|
||||
|
||||
<!-- Galerie Seiten-Texte -->
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 mb-8 shadow-sm">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-8 flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-primary">text_fields</span>
|
||||
Galerie – Seiten-Texte
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Badge (oben)</label>
|
||||
<input id="galBadge" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (normal)</label>
|
||||
<input id="galHeadingMain" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold uppercase"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (farbig)</label>
|
||||
<input id="galHeadingColored" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold uppercase"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibungstext</label>
|
||||
<textarea id="galDescription" rows="3" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mb-4">Stats Ribbon (Zähler unter dem Grid)</h4>
|
||||
<div class="mb-4">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift Ribbon</label>
|
||||
<input id="galRibbonHeading" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold"/>
|
||||
</div>
|
||||
<div class="mb-6">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibung Ribbon</label>
|
||||
<textarea id="galRibbonDesc" rows="2" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-3">Statistiken (Wert + Bezeichnung)</label>
|
||||
<div class="space-y-3 mb-8" id="galStatsFields"></div>
|
||||
<button id="galSaveBtn" type="button" class="w-full py-4 rounded-xl font-black text-lg bg-gradient-to-r from-primary to-primary-container text-on-primary shadow-lg shadow-primary/20 active:scale-95 transition-all font-lexend">
|
||||
Galerie-Texte speichern & deployen
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<!-- Upload -->
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 mb-8 shadow-sm">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-6 flex items-center gap-2">
|
||||
|
|
@ -382,6 +422,66 @@ tailwind.config = {
|
|||
<div class="space-y-3" id="statsFields"></div>
|
||||
</div>
|
||||
|
||||
<!-- Hero-Karte -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Hero-Karte (Rang auf dem Bild)</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Rang (z.B. Blaugurt)</label>
|
||||
<input id="hpKarteRang" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Status (z.B. Status 2024)</label>
|
||||
<input id="hpKarteStatus" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Prüfungs-Karte -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Prüfungs-Karte (pinke Box)</h4>
|
||||
<div class="grid grid-cols-1 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Titel</label>
|
||||
<input id="hpPruefungTitel" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibung</label>
|
||||
<textarea id="hpPruefungDesc" rows="2" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dojo-Karte -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Dojo-Karte (graue Box)</h4>
|
||||
<div class="grid grid-cols-1 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Titel</label>
|
||||
<input id="hpDojoTitel" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibung</label>
|
||||
<textarea id="hpDojoDesc" rows="2" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CTA-Sektion -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Galerie-CTA (dunkler Bereich)</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (normal)</label>
|
||||
<input id="hpCtaMain" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (farbig/akzent)</label>
|
||||
<input id="hpCtaColored" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibungstext</label>
|
||||
<textarea id="hpCtaDesc" rows="2" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Button-Text</label>
|
||||
<input id="hpCtaBtn" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold uppercase tracking-widest"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="heroSaveBtn"
|
||||
class="w-full py-4 rounded-xl font-black text-lg bg-gradient-to-r from-primary to-primary-container text-on-primary shadow-lg shadow-primary/20 active:scale-95 transition-all font-lexend">
|
||||
Änderungen speichern
|
||||
|
|
@ -459,42 +559,6 @@ tailwind.config = {
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Haupterfolg -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Haupterfolg</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Titel</label>
|
||||
<input id="umHeTitel" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Platz / Ergebnis</label>
|
||||
<input id="umHePlatz" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Jahr</label>
|
||||
<input id="umHeJahr" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Ort</label>
|
||||
<input id="umHeOrt" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Kategorie</label>
|
||||
<input id="umHeKat" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibung</label>
|
||||
<textarea id="umHeDesc" rows="3" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Weitere Erfolge -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Weitere Erfolge</h4>
|
||||
<div id="umWeitereFields" class="space-y-3 mb-3"></div>
|
||||
<button id="umWeitereAdd" type="button" class="flex items-center gap-2 text-sm font-bold text-primary border border-primary/30 rounded-xl px-4 py-2 hover:bg-pink-50 transition-all mb-6">
|
||||
<span class="material-symbols-outlined text-base">add</span> Erfolg hinzufügen
|
||||
</button>
|
||||
|
||||
<!-- Stats -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Statistik-Boxen</h4>
|
||||
<div id="umStatsFields" class="space-y-3 mb-6"></div>
|
||||
|
|
@ -517,22 +581,245 @@ tailwind.config = {
|
|||
|
||||
<!-- ══ SECTION: CAREER ══ -->
|
||||
<div id="section-career" class="hidden">
|
||||
<div class="bg-surface-container-low rounded-xl p-12 text-center">
|
||||
<span class="material-symbols-outlined text-6xl text-surface-variant mb-4 block">emoji_events</span>
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface-variant">Erfolge — demnächst verfügbar</h3>
|
||||
</div>
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 shadow-sm">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-8 flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-primary">emoji_events</span>
|
||||
Erfolge-Seite bearbeiten
|
||||
</h3>
|
||||
|
||||
<!-- Hero-Bild -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mb-4">Hero-Bild</h4>
|
||||
<div class="flex gap-6 items-start flex-wrap mb-8">
|
||||
<div class="w-40 h-48 rounded-xl overflow-hidden bg-surface-container flex-shrink-0">
|
||||
<img id="efHeroPreview" src="" alt="Erfolge Hero" class="w-full h-full object-cover hidden"/>
|
||||
<div id="efHeroPlaceholder" class="w-full h-full flex flex-col items-center justify-center text-on-surface-variant">
|
||||
<span class="material-symbols-outlined text-4xl mb-2">image</span>
|
||||
<span class="text-xs font-medium">Kein Bild</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 min-w-48">
|
||||
<label for="efHeroFileInput" class="block border-2 border-dashed border-primary/30 bg-surface-container-low rounded-xl p-6 text-center cursor-pointer hover:border-primary/60 transition-all mb-3">
|
||||
<span class="material-symbols-outlined text-primary block mb-2">upload_file</span>
|
||||
<p class="text-sm font-bold text-primary font-lexend">Bild auswählen</p>
|
||||
<p class="text-xs text-on-surface-variant mt-1">JPG, PNG, HEIC</p>
|
||||
</label>
|
||||
<input type="file" id="efHeroFileInput" accept="image/*" class="sr-only"/>
|
||||
<button id="efHeroUploadBtn" disabled class="w-full py-3 rounded-xl font-bold text-sm bg-gradient-to-r from-primary to-primary-container text-on-primary shadow-md shadow-primary/20 disabled:opacity-40 disabled:cursor-not-allowed active:scale-95 transition-all font-lexend">Bild hochladen</button>
|
||||
<p id="efHeroUploadStatus" class="text-xs text-on-surface-variant mt-2 text-center"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hero-Texte -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mb-4">Hero-Text</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Badge-Text</label>
|
||||
<input id="efBadge" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Aktueller Rang (Karte)</label>
|
||||
<input id="efRang" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (normal)</label>
|
||||
<input id="efHeadingMain" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-black uppercase"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (farbig)</label>
|
||||
<input id="efHeadingColored" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-black uppercase"/>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibungstext</label>
|
||||
<textarea id="efDescription" rows="3" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm leading-relaxed resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Haupt-Meilenstein -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Haupt-Meilenstein (große Karte)</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Event / Titel</label>
|
||||
<input id="efMeilensteinEvent" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Platz / Ergebnis</label>
|
||||
<input id="efMeilensteinPlatz" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Jahr</label>
|
||||
<input id="efMeilensteinJahr" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Ort</label>
|
||||
<input id="efMeilensteinOrt" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Kategorie</label>
|
||||
<input id="efMeilensteinKat" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibung</label>
|
||||
<textarea id="efMeilensteinDesc" rows="3" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Weitere Auszeichnungen -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Weitere Auszeichnungen</h4>
|
||||
<div id="efWeitereFields" class="space-y-3 mb-3"></div>
|
||||
<button id="efWeitereAdd" type="button" class="flex items-center gap-2 text-sm font-bold text-primary border border-primary/30 rounded-xl px-4 py-2 hover:bg-pink-50 transition-all mb-8">
|
||||
<span class="material-symbols-outlined text-base">add</span> Auszeichnung hinzufügen
|
||||
</button>
|
||||
|
||||
<!-- Statistiken -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-2">Statistiken (3 Boxen)</h4>
|
||||
<p class="text-xs text-on-surface-variant mb-4">Box 1 = lila, Box 2 = grau, Box 3 = weiß mit pinker Linie.</p>
|
||||
<div id="efStatsFields" class="space-y-3 mb-8"></div>
|
||||
|
||||
<!-- Zitat -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-4">Zitat</h4>
|
||||
<div class="mb-4">
|
||||
<textarea id="efZitatText" rows="3" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Autor</label>
|
||||
<input id="efZitatAutor" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
|
||||
<button id="careerSaveBtn" class="w-full py-4 rounded-xl font-black text-lg bg-gradient-to-r from-primary to-primary-container text-on-primary shadow-lg shadow-primary/20 active:scale-95 transition-all font-lexend">
|
||||
Erfolge speichern & deployen
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- ══ SECTION: COMMUNITY ══ -->
|
||||
<div id="section-community" class="hidden">
|
||||
<div class="bg-surface-container-low rounded-xl p-12 text-center">
|
||||
<span class="material-symbols-outlined text-6xl text-surface-variant mb-4 block">forum</span>
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface-variant">Gästebuch — demnächst verfügbar</h3>
|
||||
</div>
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 shadow-sm mb-8">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-8 flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-primary">forum</span>
|
||||
Gästebuch bearbeiten
|
||||
</h3>
|
||||
|
||||
<!-- Hero Bild -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mb-4">Hero-Bild (Hintergrundbild)</h4>
|
||||
<div class="flex gap-6 items-start flex-wrap mb-8">
|
||||
<div class="w-48 h-24 rounded-xl overflow-hidden bg-surface-container flex-shrink-0">
|
||||
<img id="gbHeroPreview" src="" alt="Gästebuch Hero" class="w-full h-full object-cover hidden"/>
|
||||
<div id="gbHeroPlaceholder" class="w-full h-full flex flex-col items-center justify-center text-on-surface-variant">
|
||||
<span class="material-symbols-outlined text-3xl mb-1">image</span>
|
||||
<span class="text-xs font-medium">Kein Bild</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 min-w-48">
|
||||
<label for="gbHeroFileInput" class="block border-2 border-dashed border-primary/30 bg-surface-container-low rounded-xl p-5 text-center cursor-pointer hover:border-primary/60 transition-all mb-3">
|
||||
<span class="material-symbols-outlined text-primary block mb-1">upload_file</span>
|
||||
<p class="text-sm font-bold text-primary font-lexend">Bild auswählen</p>
|
||||
<p class="text-xs text-on-surface-variant mt-1">JPG, PNG, HEIC (16:9 empfohlen)</p>
|
||||
</label>
|
||||
<input type="file" id="gbHeroFileInput" accept="image/*" class="sr-only"/>
|
||||
<button id="gbHeroUploadBtn" disabled class="w-full py-3 rounded-xl font-bold text-sm bg-gradient-to-r from-primary to-primary-container text-on-primary shadow-md shadow-primary/20 disabled:opacity-40 disabled:cursor-not-allowed active:scale-95 transition-all font-lexend">Bild hochladen</button>
|
||||
<p id="gbHeroUploadStatus" class="text-xs text-on-surface-variant mt-2 text-center"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hero Texte -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mb-4">Hero-Text</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Badge</label>
|
||||
<input id="gbBadge" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (normal)</label>
|
||||
<input id="gbHeading" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Überschrift (farbig)</label>
|
||||
<input id="gbHeadingColored" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Beschreibungstext</label>
|
||||
<textarea id="gbDescription" rows="3" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kontakt -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mb-4">Kontakt-Info (Sidebar)</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">E-Mail</label>
|
||||
<input id="gbEmail" type="email" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-on-surface-variant uppercase tracking-widest mb-2">Dojo-Name</label>
|
||||
<input id="gbDojo" type="text" class="w-full bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Einträge -->
|
||||
<h4 class="text-sm font-black font-lexend text-on-surface-variant uppercase tracking-widest mt-8 mb-2">Gästebuch-Einträge</h4>
|
||||
<p class="text-xs text-on-surface-variant mb-4">Erster Eintrag erscheint im "Neuester Eintrag"-Widget. Farbe "Akzent" erzeugt die lila/pink Verlaufskarte.</p>
|
||||
<div id="gbEintragFields" class="space-y-3 mb-3"></div>
|
||||
<button id="gbEintragAdd" type="button" class="flex items-center gap-2 text-sm font-bold text-primary border border-primary/30 rounded-xl px-4 py-2 hover:bg-pink-50 transition-all mb-8">
|
||||
<span class="material-symbols-outlined text-base">add</span> Eintrag hinzufügen
|
||||
</button>
|
||||
|
||||
<button id="gbSaveBtn" class="w-full py-4 rounded-xl font-black text-lg bg-gradient-to-r from-primary to-primary-container text-on-primary shadow-lg shadow-primary/20 active:scale-95 transition-all font-lexend">
|
||||
Gästebuch speichern & deployen
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- ══ SECTION: SETTINGS ══ -->
|
||||
<div id="section-settings" class="hidden">
|
||||
<!-- Social Links -->
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 shadow-sm mb-6">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-6 flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-primary">share</span>
|
||||
Social Links
|
||||
</h3>
|
||||
<p class="text-sm text-on-surface-variant mb-6">Diese Links erscheinen im Footer auf allen Seiten der Website.</p>
|
||||
<div class="space-y-4 mb-6">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="material-symbols-outlined text-on-surface-variant">photo_camera</span>
|
||||
<input id="socialInstagram" type="text" placeholder="Instagram URL (oder #)"
|
||||
class="flex-1 bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="material-symbols-outlined text-on-surface-variant">smart_display</span>
|
||||
<input id="socialYoutube" type="text" placeholder="YouTube URL (oder #)"
|
||||
class="flex-1 bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="material-symbols-outlined text-on-surface-variant">mail</span>
|
||||
<input id="socialEmail" type="email" placeholder="E-Mail-Adresse"
|
||||
class="flex-1 bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" id="saveSocialBtn"
|
||||
class="px-6 py-3 rounded-xl font-black text-sm bg-primary text-on-primary active:scale-95 transition-all font-lexend flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-sm">save</span> Speichern & deployen
|
||||
</button>
|
||||
<p id="socialStatus" class="text-xs text-on-surface-variant mt-2"></p>
|
||||
</section>
|
||||
|
||||
<!-- Site-Name -->
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 shadow-sm mb-6">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-6 flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-primary">badge</span>
|
||||
Site-Name
|
||||
</h3>
|
||||
<p class="text-sm text-on-surface-variant mb-4">Dieser Name erscheint in der Navbar, im Footer und überall auf der Website.</p>
|
||||
<div class="flex gap-3">
|
||||
<input id="siteTitleInput" type="text" placeholder="z.B. MiyaKarate"
|
||||
class="flex-1 bg-surface-container-low rounded-DEFAULT px-4 py-3 text-on-surface placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold font-lexend uppercase italic tracking-tight"/>
|
||||
<button type="button" id="saveSiteTitleBtn"
|
||||
class="px-6 py-3 rounded-xl font-black text-sm bg-primary text-on-primary active:scale-95 transition-all font-lexend flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-sm">save</span> Speichern
|
||||
</button>
|
||||
</div>
|
||||
<p id="siteTitleStatus" class="text-xs text-on-surface-variant mt-2"></p>
|
||||
</section>
|
||||
|
||||
<section class="bg-surface-container-lowest rounded-xl p-8 shadow-sm">
|
||||
<h3 class="text-xl font-black font-lexend text-on-surface mb-6 flex items-center gap-2">
|
||||
<span class="material-symbols-outlined text-primary">label</span>
|
||||
|
|
@ -634,10 +921,12 @@ tailwind.config = {
|
|||
const [title, sub] = pageTitles[name] || ['Admin', ''];
|
||||
document.getElementById('pageTitle').textContent = title;
|
||||
document.getElementById('pageSubtitle').textContent = sub;
|
||||
if (name === 'media') loadPhotos();
|
||||
if (name === 'media') { loadPhotos(); loadGaleriePage(); }
|
||||
if (name === 'homepage') loadHomepage();
|
||||
if (name === 'uebermich') loadUebermich();
|
||||
if (name === 'settings') renderCatManage();
|
||||
if (name === 'career') loadCareer();
|
||||
if (name === 'community') loadGaestebuch();
|
||||
if (name === 'settings') { renderCatManage(); loadSiteTitle(); loadSocialLinks(); }
|
||||
}
|
||||
|
||||
document.getElementById('sideNav').addEventListener('click', function (e) {
|
||||
|
|
@ -1179,15 +1468,29 @@ tailwind.config = {
|
|||
const hero = data.hero || {};
|
||||
document.getElementById('heroBadge').value = hero.badge || '';
|
||||
document.getElementById('heroDescription').value = hero.description || '';
|
||||
const hk = data.hero_karte || {};
|
||||
document.getElementById('hpKarteRang').value = hk.rang || '';
|
||||
document.getElementById('hpKarteStatus').value = hk.status || '';
|
||||
const pk = data.pruefung_karte || {};
|
||||
document.getElementById('hpPruefungTitel').value = pk.titel || '';
|
||||
document.getElementById('hpPruefungDesc').value = pk.beschreibung || '';
|
||||
const dk = data.dojo_karte || {};
|
||||
document.getElementById('hpDojoTitel').value = dk.titel || '';
|
||||
document.getElementById('hpDojoDesc').value = dk.beschreibung || '';
|
||||
const cta = data.cta || {};
|
||||
document.getElementById('hpCtaMain').value = cta.heading_main || '';
|
||||
document.getElementById('hpCtaColored').value = cta.heading_colored || '';
|
||||
document.getElementById('hpCtaDesc').value = cta.description || '';
|
||||
document.getElementById('hpCtaBtn').value = cta.button_text || '';
|
||||
const statsFields = document.getElementById('statsFields');
|
||||
statsFields.innerHTML = '';
|
||||
(data.stats || []).forEach(function(s) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'flex gap-3 items-center';
|
||||
row.innerHTML =
|
||||
'<input type="text" value="' + s.value + '" placeholder="Wert" data-stat="value"' +
|
||||
'<input type="text" value="' + escHtml(s.value||'') + '" placeholder="Wert" data-stat="value"' +
|
||||
' class="w-24 bg-surface-container-low rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-black text-center"/>' +
|
||||
'<input type="text" value="' + s.label + '" placeholder="Bezeichnung" data-stat="label"' +
|
||||
'<input type="text" value="' + escHtml(s.label||'') + '" placeholder="Bezeichnung" data-stat="label"' +
|
||||
' class="flex-1 bg-surface-container-low rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>';
|
||||
statsFields.appendChild(row);
|
||||
});
|
||||
|
|
@ -1248,10 +1551,28 @@ tailwind.config = {
|
|||
body: JSON.stringify({
|
||||
badge: document.getElementById('heroBadge').value,
|
||||
description: document.getElementById('heroDescription').value,
|
||||
stats: stats
|
||||
stats: stats,
|
||||
hero_karte: {
|
||||
rang: document.getElementById('hpKarteRang').value,
|
||||
status: document.getElementById('hpKarteStatus').value
|
||||
},
|
||||
pruefung_karte: {
|
||||
titel: document.getElementById('hpPruefungTitel').value,
|
||||
beschreibung: document.getElementById('hpPruefungDesc').value
|
||||
},
|
||||
dojo_karte: {
|
||||
titel: document.getElementById('hpDojoTitel').value,
|
||||
beschreibung: document.getElementById('hpDojoDesc').value
|
||||
},
|
||||
cta: {
|
||||
heading_main: document.getElementById('hpCtaMain').value,
|
||||
heading_colored: document.getElementById('hpCtaColored').value,
|
||||
description: document.getElementById('hpCtaDesc').value,
|
||||
button_text: document.getElementById('hpCtaBtn').value
|
||||
}
|
||||
})
|
||||
});
|
||||
if (r.ok) showToast('✓ Startseite gespeichert');
|
||||
if (r.ok) showToast('✓ Startseite gespeichert & Deploy gestartet');
|
||||
} catch (err) { console.error('Save error:', err); }
|
||||
});
|
||||
|
||||
|
|
@ -1282,10 +1603,6 @@ tailwind.config = {
|
|||
return row;
|
||||
}
|
||||
|
||||
document.getElementById('umWeitereAdd').addEventListener('click', function() {
|
||||
document.getElementById('umWeitereFields').appendChild(createWeitereRow('', ''));
|
||||
});
|
||||
|
||||
async function loadUebermich() {
|
||||
try {
|
||||
const r = await fetch('/api/uebermich');
|
||||
|
|
@ -1297,22 +1614,9 @@ tailwind.config = {
|
|||
document.getElementById('umHSuffix').value = d.hero.heading_suffix || '';
|
||||
document.getElementById('umDesc').value = d.hero.description || '';
|
||||
document.getElementById('umGurt').value = d.gurtweg.aktiver_gurt || 'Blau';
|
||||
document.getElementById('umHeTitel').value = d.haupterfolg.titel || '';
|
||||
document.getElementById('umHePlatz').value = d.haupterfolg.platz || '';
|
||||
document.getElementById('umHeJahr').value = d.haupterfolg.jahr || '';
|
||||
document.getElementById('umHeOrt').value = d.haupterfolg.ort || '';
|
||||
document.getElementById('umHeKat').value = d.haupterfolg.kategorie || '';
|
||||
document.getElementById('umHeDesc').value = d.haupterfolg.beschreibung || '';
|
||||
document.getElementById('umZitat').value = d.zitat.text || '';
|
||||
document.getElementById('umZitatAutor').value = d.zitat.autor || '';
|
||||
|
||||
// Weitere Erfolge
|
||||
const wf = document.getElementById('umWeitereFields');
|
||||
wf.innerHTML = '';
|
||||
(d.weitere_erfolge || []).forEach(function(e) {
|
||||
wf.appendChild(createWeitereRow(e.titel, e.detail, e.beschreibung, e.jahr, e.ort, e.kategorie));
|
||||
});
|
||||
|
||||
// Stats
|
||||
const sf = document.getElementById('umStatsFields');
|
||||
sf.innerHTML = '';
|
||||
|
|
@ -1378,27 +1682,9 @@ tailwind.config = {
|
|||
data.hero.heading_suffix = document.getElementById('umHSuffix').value;
|
||||
data.hero.description = document.getElementById('umDesc').value;
|
||||
data.gurtweg.aktiver_gurt = document.getElementById('umGurt').value;
|
||||
data.haupterfolg.titel = document.getElementById('umHeTitel').value;
|
||||
data.haupterfolg.platz = document.getElementById('umHePlatz').value;
|
||||
data.haupterfolg.jahr = document.getElementById('umHeJahr').value;
|
||||
data.haupterfolg.ort = document.getElementById('umHeOrt').value;
|
||||
data.haupterfolg.kategorie = document.getElementById('umHeKat').value;
|
||||
data.haupterfolg.beschreibung = document.getElementById('umHeDesc').value;
|
||||
data.zitat.text = document.getElementById('umZitat').value;
|
||||
data.zitat.autor = document.getElementById('umZitatAutor').value;
|
||||
|
||||
const weRows = document.getElementById('umWeitereFields').querySelectorAll(':scope > div');
|
||||
data.weitere_erfolge = Array.from(weRows).map(function(row) {
|
||||
return {
|
||||
titel: row.querySelector('[data-we="titel"]').value,
|
||||
detail: row.querySelector('[data-we="detail"]').value,
|
||||
beschreibung: row.querySelector('[data-we="beschreibung"]').value,
|
||||
jahr: row.querySelector('[data-we="jahr"]').value,
|
||||
ort: row.querySelector('[data-we="ort"]').value,
|
||||
kategorie: row.querySelector('[data-we="kategorie"]').value
|
||||
};
|
||||
});
|
||||
|
||||
const stRows = document.getElementById('umStatsFields').querySelectorAll('div.flex');
|
||||
data.stats = Array.from(stRows).map(function(row) {
|
||||
return {
|
||||
|
|
@ -1416,8 +1702,414 @@ tailwind.config = {
|
|||
} catch(err) { console.error('Save error:', err); }
|
||||
});
|
||||
|
||||
// ─── Erfolge (Career) ─────────────────────────────────────
|
||||
function createAuszeichnungRow(titel, detail) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'bg-surface-container-low rounded-xl p-4 flex gap-3 items-center';
|
||||
row.innerHTML =
|
||||
'<input type="text" value="' + escHtml(titel||'') + '" placeholder="Titel" data-ea="titel"' +
|
||||
' class="flex-1 bg-white rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold"/>' +
|
||||
'<input type="text" value="' + escHtml(detail||'') + '" placeholder="Untertitel (z.B. Silber – Kata 2024)" data-ea="detail"' +
|
||||
' class="flex-1 bg-white rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>' +
|
||||
'<button type="button" class="ea-delete shrink-0 w-8 h-8 flex items-center justify-center rounded-lg text-error hover:bg-error/10 transition-all">' +
|
||||
'<span class="material-symbols-outlined text-lg">delete</span></button>';
|
||||
row.querySelector('.ea-delete').addEventListener('click', function() { row.remove(); });
|
||||
return row;
|
||||
}
|
||||
|
||||
document.getElementById('efWeitereAdd').addEventListener('click', function() {
|
||||
document.getElementById('efWeitereFields').appendChild(createAuszeichnungRow('', ''));
|
||||
});
|
||||
|
||||
document.getElementById('efHeroFileInput').addEventListener('change', function() {
|
||||
const file = this.files[0];
|
||||
if (!file) return;
|
||||
document.getElementById('efHeroPreview').src = URL.createObjectURL(file);
|
||||
document.getElementById('efHeroPreview').classList.remove('hidden');
|
||||
document.getElementById('efHeroPlaceholder').classList.add('hidden');
|
||||
document.getElementById('efHeroUploadBtn').disabled = false;
|
||||
document.getElementById('efHeroUploadStatus').textContent = file.name;
|
||||
});
|
||||
|
||||
document.getElementById('efHeroUploadBtn').addEventListener('click', async function() {
|
||||
const file = document.getElementById('efHeroFileInput').files[0];
|
||||
if (!file) return;
|
||||
this.disabled = true;
|
||||
document.getElementById('efHeroUploadStatus').textContent = 'Wird hochgeladen…';
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('image', file);
|
||||
const r = await fetch('/api/erfolge/image', { method: 'POST', body: fd });
|
||||
if (r.ok) {
|
||||
showToast('✓ Bild gespeichert');
|
||||
document.getElementById('efHeroUploadStatus').textContent = 'Gespeichert!';
|
||||
} else {
|
||||
document.getElementById('efHeroUploadStatus').textContent = 'Fehler beim Upload';
|
||||
}
|
||||
} catch(err) {
|
||||
document.getElementById('efHeroUploadStatus').textContent = 'Verbindungsfehler';
|
||||
}
|
||||
this.disabled = false;
|
||||
});
|
||||
|
||||
async function loadCareer() {
|
||||
try {
|
||||
const r = await fetch('/api/erfolge');
|
||||
const d = await r.json();
|
||||
const hero = d.hero || {};
|
||||
document.getElementById('efBadge').value = hero.badge || '';
|
||||
document.getElementById('efHeadingMain').value = hero.heading_main || '';
|
||||
document.getElementById('efHeadingColored').value = hero.heading_colored || '';
|
||||
document.getElementById('efDescription').value = hero.description || '';
|
||||
document.getElementById('efRang').value = hero.rang_value || '';
|
||||
if (hero.image) {
|
||||
document.getElementById('efHeroPreview').src = '/erfolge-img/' + hero.image + '?t=' + Date.now();
|
||||
document.getElementById('efHeroPreview').classList.remove('hidden');
|
||||
document.getElementById('efHeroPlaceholder').classList.add('hidden');
|
||||
}
|
||||
const m = d.meilenstein || {};
|
||||
document.getElementById('efMeilensteinEvent').value = m.event || '';
|
||||
document.getElementById('efMeilensteinPlatz').value = m.platz || '';
|
||||
document.getElementById('efMeilensteinDesc').value = m.beschreibung || '';
|
||||
document.getElementById('efMeilensteinJahr').value = m.jahr || '';
|
||||
document.getElementById('efMeilensteinOrt').value = m.ort || '';
|
||||
document.getElementById('efMeilensteinKat').value = m.kategorie || '';
|
||||
const wf = document.getElementById('efWeitereFields');
|
||||
wf.innerHTML = '';
|
||||
(d.weitere_auszeichnungen || []).forEach(function(a) {
|
||||
wf.appendChild(createAuszeichnungRow(a.titel, a.detail));
|
||||
});
|
||||
const sf = document.getElementById('efStatsFields');
|
||||
sf.innerHTML = '';
|
||||
(d.stats || []).forEach(function(s) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'flex gap-3 items-center';
|
||||
row.innerHTML =
|
||||
'<input type="text" value="' + escHtml(s.wert||'') + '" placeholder="Wert" data-es="wert"' +
|
||||
' class="w-24 bg-surface-container-low rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-black text-center"/>' +
|
||||
'<input type="text" value="' + escHtml(s.label||'') + '" placeholder="Bezeichnung" data-es="label"' +
|
||||
' class="flex-1 bg-surface-container-low rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>';
|
||||
sf.appendChild(row);
|
||||
});
|
||||
document.getElementById('efZitatText').value = (d.zitat || {}).text || '';
|
||||
document.getElementById('efZitatAutor').value = (d.zitat || {}).autor || '';
|
||||
} catch(err) { console.error('Career load error:', err); }
|
||||
}
|
||||
|
||||
document.getElementById('careerSaveBtn').addEventListener('click', async function() {
|
||||
try {
|
||||
const r0 = await fetch('/api/erfolge');
|
||||
const existing = await r0.json();
|
||||
const weRows = document.getElementById('efWeitereFields').querySelectorAll(':scope > div');
|
||||
const stRows = document.getElementById('efStatsFields').querySelectorAll('div.flex');
|
||||
const data = {
|
||||
hero: {
|
||||
badge: document.getElementById('efBadge').value,
|
||||
heading_main: document.getElementById('efHeadingMain').value,
|
||||
heading_colored: document.getElementById('efHeadingColored').value,
|
||||
description: document.getElementById('efDescription').value,
|
||||
rang_value: document.getElementById('efRang').value,
|
||||
rang_label: (existing.hero || {}).rang_label || 'Aktueller Rang',
|
||||
image: (existing.hero || {}).image || ''
|
||||
},
|
||||
meilenstein: {
|
||||
event: document.getElementById('efMeilensteinEvent').value,
|
||||
platz: document.getElementById('efMeilensteinPlatz').value,
|
||||
beschreibung: document.getElementById('efMeilensteinDesc').value,
|
||||
jahr: document.getElementById('efMeilensteinJahr').value,
|
||||
ort: document.getElementById('efMeilensteinOrt').value,
|
||||
kategorie: document.getElementById('efMeilensteinKat').value
|
||||
},
|
||||
weitere_auszeichnungen: Array.from(weRows).map(function(row) {
|
||||
return {
|
||||
titel: row.querySelector('[data-ea="titel"]').value,
|
||||
detail: row.querySelector('[data-ea="detail"]').value
|
||||
};
|
||||
}),
|
||||
stats: Array.from(stRows).map(function(row) {
|
||||
return {
|
||||
wert: row.querySelector('[data-es="wert"]').value,
|
||||
label: row.querySelector('[data-es="label"]').value
|
||||
};
|
||||
}),
|
||||
zitat: {
|
||||
text: document.getElementById('efZitatText').value,
|
||||
autor: document.getElementById('efZitatAutor').value
|
||||
}
|
||||
};
|
||||
|
||||
const res = await fetch('/api/erfolge', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
if (res.ok) showToast('✓ Erfolge gespeichert & Deploy gestartet');
|
||||
} catch(err) { console.error('Career save error:', err); }
|
||||
});
|
||||
|
||||
// ─── Site-Name ────────────────────────────────────────────
|
||||
async function loadSiteTitle() {
|
||||
try {
|
||||
const r = await fetch('/api/homepage');
|
||||
const data = await r.json();
|
||||
const title = data.siteTitle || '';
|
||||
document.getElementById('siteTitleInput').value = title;
|
||||
updateAdminTitle(title);
|
||||
} catch (err) { console.error('SiteTitle load error:', err); }
|
||||
}
|
||||
|
||||
function updateAdminTitle(title) {
|
||||
if (!title) return;
|
||||
document.getElementById('adminSiteTitle').textContent = title;
|
||||
document.getElementById('adminSiteTitleHeader').textContent = title;
|
||||
}
|
||||
|
||||
document.getElementById('saveSiteTitleBtn').addEventListener('click', async function () {
|
||||
const status = document.getElementById('siteTitleStatus');
|
||||
const val = document.getElementById('siteTitleInput').value.trim();
|
||||
if (!val) { status.textContent = 'Bitte einen Namen eingeben.'; return; }
|
||||
try {
|
||||
const r = await fetch('/api/homepage', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ siteTitle: val })
|
||||
});
|
||||
if (r.ok) {
|
||||
updateAdminTitle(val);
|
||||
showToast('✓ Site-Name gespeichert & Deploy gestartet');
|
||||
status.textContent = '';
|
||||
} else {
|
||||
status.textContent = 'Fehler beim Speichern.';
|
||||
}
|
||||
} catch (err) { status.textContent = 'Verbindungsfehler'; }
|
||||
});
|
||||
|
||||
// ─── Galerie Seiten-Texte ─────────────────────────────────
|
||||
async function loadGaleriePage() {
|
||||
try {
|
||||
const r = await fetch('/api/galerie');
|
||||
const d = await r.json();
|
||||
const hero = d.hero || {};
|
||||
document.getElementById('galBadge').value = hero.badge || '';
|
||||
document.getElementById('galHeadingMain').value = hero.heading_main || '';
|
||||
document.getElementById('galHeadingColored').value = hero.heading_colored || '';
|
||||
document.getElementById('galDescription').value = hero.description || '';
|
||||
const ribbon = d.ribbon || {};
|
||||
document.getElementById('galRibbonHeading').value = ribbon.heading || '';
|
||||
document.getElementById('galRibbonDesc').value = ribbon.description || '';
|
||||
const sf = document.getElementById('galStatsFields');
|
||||
sf.innerHTML = '';
|
||||
(ribbon.stats || []).forEach(function(s) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'flex gap-3 items-center';
|
||||
row.innerHTML =
|
||||
'<input type="text" value="' + escHtml(s.wert||'') + '" placeholder="Wert" data-gs="wert"' +
|
||||
' class="w-24 bg-surface-container-low rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-black text-center"/>' +
|
||||
'<input type="text" value="' + escHtml(s.label||'') + '" placeholder="Bezeichnung" data-gs="label"' +
|
||||
' class="flex-1 bg-surface-container-low rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>';
|
||||
sf.appendChild(row);
|
||||
});
|
||||
} catch(err) { console.error('Galerie page load error:', err); }
|
||||
}
|
||||
|
||||
document.getElementById('galSaveBtn').addEventListener('click', async function() {
|
||||
try {
|
||||
const stRows = document.getElementById('galStatsFields').querySelectorAll('div.flex');
|
||||
const data = {
|
||||
hero: {
|
||||
badge: document.getElementById('galBadge').value,
|
||||
heading_main: document.getElementById('galHeadingMain').value,
|
||||
heading_colored: document.getElementById('galHeadingColored').value,
|
||||
description: document.getElementById('galDescription').value
|
||||
},
|
||||
ribbon: {
|
||||
heading: document.getElementById('galRibbonHeading').value,
|
||||
description: document.getElementById('galRibbonDesc').value,
|
||||
stats: Array.from(stRows).map(function(row) {
|
||||
return {
|
||||
wert: row.querySelector('[data-gs="wert"]').value,
|
||||
label: row.querySelector('[data-gs="label"]').value
|
||||
};
|
||||
})
|
||||
}
|
||||
};
|
||||
const res = await fetch('/api/galerie', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
if (res.ok) showToast('✓ Galerie-Texte gespeichert & Deploy gestartet');
|
||||
} catch(err) { console.error('Galerie save error:', err); }
|
||||
});
|
||||
|
||||
// ─── Gästebuch ────────────────────────────────────────────
|
||||
function createEintragRow(name, rolle, text, farbe, breit) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'bg-surface-container-low rounded-xl p-4 flex flex-col gap-3';
|
||||
row.innerHTML =
|
||||
'<div class="flex gap-3 items-start">' +
|
||||
'<div class="flex-1 grid grid-cols-2 gap-3">' +
|
||||
'<input type="text" value="' + escHtml(name||'') + '" placeholder="Name" data-gb="name"' +
|
||||
' class="bg-white rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm font-bold"/>' +
|
||||
'<input type="text" value="' + escHtml(rolle||'') + '" placeholder="Rolle (z.B. Trainerin)" data-gb="rolle"' +
|
||||
' class="bg-white rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm"/>' +
|
||||
'</div>' +
|
||||
'<button type="button" class="gb-delete shrink-0 w-8 h-8 flex items-center justify-center rounded-lg text-error hover:bg-error/10 transition-all">' +
|
||||
'<span class="material-symbols-outlined text-lg">delete</span></button>' +
|
||||
'</div>' +
|
||||
'<textarea data-gb="text" rows="2" placeholder="Nachricht"' +
|
||||
' class="w-full bg-white rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm resize-none">' + escHtml(text||'') + '</textarea>' +
|
||||
'<div class="flex gap-4 items-center flex-wrap">' +
|
||||
'<label class="flex items-center gap-2 text-sm cursor-pointer">' +
|
||||
'<input type="checkbox" data-gb="breit" ' + (breit ? 'checked' : '') + ' class="rounded"/>' +
|
||||
'<span class="text-on-surface-variant font-medium">Breite Karte</span>' +
|
||||
'</label>' +
|
||||
'<select data-gb="farbe" class="bg-white rounded-DEFAULT px-3 py-2 text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/30 text-sm">' +
|
||||
'<option value="default"' + ((!farbe || farbe === 'default') ? ' selected' : '') + '>Standard (weiß)</option>' +
|
||||
'<option value="secondary"' + (farbe === 'secondary' ? ' selected' : '') + '>Akzent (lila/pink)</option>' +
|
||||
'</select>' +
|
||||
'</div>';
|
||||
row.querySelector('.gb-delete').addEventListener('click', function() { row.remove(); });
|
||||
return row;
|
||||
}
|
||||
|
||||
document.getElementById('gbEintragAdd').addEventListener('click', function() {
|
||||
document.getElementById('gbEintragFields').appendChild(createEintragRow('', '', '', 'default', false));
|
||||
});
|
||||
|
||||
document.getElementById('gbHeroFileInput').addEventListener('change', function() {
|
||||
const file = this.files[0];
|
||||
if (!file) return;
|
||||
document.getElementById('gbHeroPreview').src = URL.createObjectURL(file);
|
||||
document.getElementById('gbHeroPreview').classList.remove('hidden');
|
||||
document.getElementById('gbHeroPlaceholder').classList.add('hidden');
|
||||
document.getElementById('gbHeroUploadBtn').disabled = false;
|
||||
document.getElementById('gbHeroUploadStatus').textContent = file.name;
|
||||
});
|
||||
|
||||
document.getElementById('gbHeroUploadBtn').addEventListener('click', async function() {
|
||||
const file = document.getElementById('gbHeroFileInput').files[0];
|
||||
if (!file) return;
|
||||
this.disabled = true;
|
||||
document.getElementById('gbHeroUploadStatus').textContent = 'Wird hochgeladen…';
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('image', file);
|
||||
const r = await fetch('/api/gaestebuch/image', { method: 'POST', body: fd });
|
||||
if (r.ok) {
|
||||
showToast('✓ Bild gespeichert');
|
||||
document.getElementById('gbHeroUploadStatus').textContent = 'Gespeichert!';
|
||||
} else {
|
||||
document.getElementById('gbHeroUploadStatus').textContent = 'Fehler beim Upload';
|
||||
}
|
||||
} catch(err) {
|
||||
document.getElementById('gbHeroUploadStatus').textContent = 'Verbindungsfehler';
|
||||
}
|
||||
this.disabled = false;
|
||||
});
|
||||
|
||||
async function loadGaestebuch() {
|
||||
try {
|
||||
const r = await fetch('/api/gaestebuch');
|
||||
const d = await r.json();
|
||||
const hero = d.hero || {};
|
||||
document.getElementById('gbBadge').value = hero.badge || '';
|
||||
document.getElementById('gbHeading').value = hero.heading || '';
|
||||
document.getElementById('gbHeadingColored').value = hero.heading_colored || '';
|
||||
document.getElementById('gbDescription').value = hero.description || '';
|
||||
const kontakt = d.kontakt || {};
|
||||
document.getElementById('gbEmail').value = kontakt.email || '';
|
||||
document.getElementById('gbDojo').value = kontakt.dojo || '';
|
||||
if (hero.image) {
|
||||
document.getElementById('gbHeroPreview').src = '/gaestebuch-img/' + hero.image + '?t=' + Date.now();
|
||||
document.getElementById('gbHeroPreview').classList.remove('hidden');
|
||||
document.getElementById('gbHeroPlaceholder').classList.add('hidden');
|
||||
}
|
||||
const ef = document.getElementById('gbEintragFields');
|
||||
ef.innerHTML = '';
|
||||
(d.eintraege || []).forEach(function(e) {
|
||||
ef.appendChild(createEintragRow(e.name, e.rolle, e.text, e.farbe, e.breit));
|
||||
});
|
||||
} catch(err) { console.error('Gaestebuch load error:', err); }
|
||||
}
|
||||
|
||||
document.getElementById('gbSaveBtn').addEventListener('click', async function() {
|
||||
try {
|
||||
const r0 = await fetch('/api/gaestebuch');
|
||||
const existing = await r0.json();
|
||||
const rows = document.getElementById('gbEintragFields').querySelectorAll(':scope > div');
|
||||
const eintraege = Array.from(rows).map(function(row, i) {
|
||||
return {
|
||||
id: String(i + 1),
|
||||
name: row.querySelector('[data-gb="name"]').value,
|
||||
rolle: row.querySelector('[data-gb="rolle"]').value,
|
||||
text: row.querySelector('[data-gb="text"]').value,
|
||||
farbe: row.querySelector('[data-gb="farbe"]').value,
|
||||
breit: row.querySelector('[data-gb="breit"]').checked
|
||||
};
|
||||
});
|
||||
const data = {
|
||||
hero: {
|
||||
badge: document.getElementById('gbBadge').value,
|
||||
heading: document.getElementById('gbHeading').value,
|
||||
heading_colored: document.getElementById('gbHeadingColored').value,
|
||||
description: document.getElementById('gbDescription').value,
|
||||
image: (existing.hero || {}).image || ''
|
||||
},
|
||||
kontakt: {
|
||||
email: document.getElementById('gbEmail').value,
|
||||
dojo: document.getElementById('gbDojo').value
|
||||
},
|
||||
eintraege: eintraege
|
||||
};
|
||||
const res = await fetch('/api/gaestebuch', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
if (res.ok) showToast('✓ Gästebuch gespeichert & Deploy gestartet');
|
||||
} catch(err) { console.error('Gaestebuch save error:', err); }
|
||||
});
|
||||
|
||||
// ─── Social Links ─────────────────────────────────────────
|
||||
async function loadSocialLinks() {
|
||||
try {
|
||||
const r = await fetch('/api/global');
|
||||
const d = await r.json();
|
||||
const social = d.social || {};
|
||||
document.getElementById('socialInstagram').value = social.instagram || '';
|
||||
document.getElementById('socialYoutube').value = social.youtube || '';
|
||||
document.getElementById('socialEmail').value = social.email || '';
|
||||
} catch(err) { console.error('Social load error:', err); }
|
||||
}
|
||||
|
||||
document.getElementById('saveSocialBtn').addEventListener('click', async function() {
|
||||
const status = document.getElementById('socialStatus');
|
||||
try {
|
||||
const r = await fetch('/api/global', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
social: {
|
||||
instagram: document.getElementById('socialInstagram').value,
|
||||
youtube: document.getElementById('socialYoutube').value,
|
||||
email: document.getElementById('socialEmail').value
|
||||
}
|
||||
})
|
||||
});
|
||||
if (r.ok) {
|
||||
showToast('✓ Social Links gespeichert & Deploy gestartet');
|
||||
status.textContent = '';
|
||||
} else {
|
||||
status.textContent = 'Fehler beim Speichern.';
|
||||
}
|
||||
} catch(err) { status.textContent = 'Verbindungsfehler'; }
|
||||
});
|
||||
|
||||
// ─── Init ─────────────────────────────────────────────────
|
||||
loadCategories().then(function () { loadStats(); });
|
||||
loadSiteTitle();
|
||||
loadSocialLinks();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
51
data/erfolge.json
Normal file
51
data/erfolge.json
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"hero": {
|
||||
"badge": "Meine Wettkampf-Geschichte",
|
||||
"heading_main": "JEDER SIEG",
|
||||
"heading_colored": "ZÄHLT.",
|
||||
"description": "Von der ersten Gürtelprüfung bis zur Landesmeisterschaft – hier sammle ich alle Momente, auf die ich besonders stolz bin.",
|
||||
"rang_value": "Blaugurt",
|
||||
"rang_label": "Aktueller Rang",
|
||||
"image": "hero.webp"
|
||||
},
|
||||
"meilenstein": {
|
||||
"event": "Landesmeisterschaft Berlin",
|
||||
"platz": "Gold – Kata U14",
|
||||
"beschreibung": "Mein bisher größter Erfolg. Monatelanges hartes Training gipfelte in einer Vorführung, die meinen Wettkampfgeist unter Beweis stellte.",
|
||||
"jahr": "2024",
|
||||
"ort": "Berlin",
|
||||
"kategorie": "U14"
|
||||
},
|
||||
"weitere_auszeichnungen": [
|
||||
{
|
||||
"titel": "Norddeutsche Meisterschaft",
|
||||
"detail": "Silber – Kata 2024"
|
||||
},
|
||||
{
|
||||
"titel": "Dojo Champion",
|
||||
"detail": "Kiai Berlin, intern"
|
||||
},
|
||||
{
|
||||
"titel": "Fairness-Preis",
|
||||
"detail": "Dojo-Auszeichnung 2023"
|
||||
}
|
||||
],
|
||||
"stats": [
|
||||
{
|
||||
"wert": "5+",
|
||||
"label": "Jahre Training"
|
||||
},
|
||||
{
|
||||
"wert": "32",
|
||||
"label": "Turniere"
|
||||
},
|
||||
{
|
||||
"wert": "12",
|
||||
"label": "Goldmedaillen"
|
||||
}
|
||||
],
|
||||
"zitat": {
|
||||
"text": "Karate ist nicht nur ein Sport. Es ist eine Linse, durch die ich die Welt sehe – mit Präzision, Respekt und unbeugsamer Konzentration.",
|
||||
"autor": "Emy"
|
||||
}
|
||||
}
|
||||
55
data/gaestebuch.json
Normal file
55
data/gaestebuch.json
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"hero": {
|
||||
"badge": "Melde dich bei mir",
|
||||
"heading": "Schreib mir &",
|
||||
"heading_colored": "teile deine Geschichte",
|
||||
"description": "Ob du eine Frage zu meinem Training hast oder einfach eine nette Nachricht hinterlassen möchtest – ich freue mich von dir zu hören!",
|
||||
"image": ""
|
||||
},
|
||||
"kontakt": {
|
||||
"email": "emy@meinewebsite.de",
|
||||
"dojo": "Kiai Dojo Esslingen"
|
||||
},
|
||||
"eintraege": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Trainerin Elena",
|
||||
"rolle": "Sensei",
|
||||
"text": "Deine Konzentration beim letzten Grading war außergewöhnlich. Die Körperkontrolle, die du entwickelst, ist selten für dein Alter. Ich bin stolz auf dich!",
|
||||
"farbe": "default",
|
||||
"breit": false
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "Opa Karl",
|
||||
"rolle": "Familie",
|
||||
"text": "Wir drücken dir von zuhause alle die Daumen! Kann es kaum erwarten, den nächsten Pokal auf dem Regal zu sehen!",
|
||||
"farbe": "default",
|
||||
"breit": true
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "Lea M.",
|
||||
"rolle": "Freundin",
|
||||
"text": "Die Website sieht so professionell aus! Mega cool, alle deine Erfolge an einem Ort zu sehen. Wir müssen bald mal wieder eis essen gehen!",
|
||||
"farbe": "default",
|
||||
"breit": false
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"name": "Trainer Thomas",
|
||||
"rolle": "Dojo Kiai Berlin",
|
||||
"text": "Ich trainiere viele Kinder, aber die kinetische Flüssigkeit in deinen Bewegungen ist etwas Besonderes. Du machst jede Kata zu einem Tanz. Weiter so – der nächste schwarze Gürtel wartet schon!",
|
||||
"farbe": "secondary",
|
||||
"breit": true
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"name": "Herr Braun",
|
||||
"rolle": "Lehrer",
|
||||
"text": "Balance im Sport führt zu Balance im Leben. Halt die Disziplin, die du im Dojo zeigst, auch in der Schule!",
|
||||
"farbe": "default",
|
||||
"breit": false
|
||||
}
|
||||
]
|
||||
}
|
||||
17
data/galerie.json
Normal file
17
data/galerie.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"hero": {
|
||||
"badge": "Visuelle Reise",
|
||||
"heading_main": "Eingefangene",
|
||||
"heading_colored": "Momente.",
|
||||
"description": "Die Kunst der Disziplin durch die Linse. Von intensiven Trainingseinheiten bis zum Triumph bei Gürtelprüfungen."
|
||||
},
|
||||
"ribbon": {
|
||||
"heading": "Hinter der Linse",
|
||||
"description": "Unsere Galerie ist nicht nur Fotos – sie ist ein Zeugnis der Disziplin, die wir jeden Tag im Dojo leben.",
|
||||
"stats": [
|
||||
{ "wert": "24", "label": "Turniere" },
|
||||
{ "wert": "150+", "label": "Schüler" },
|
||||
{ "wert": "85", "label": "Gürtelprüfungen" }
|
||||
]
|
||||
}
|
||||
}
|
||||
7
data/global.json
Normal file
7
data/global.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"social": {
|
||||
"instagram": "#",
|
||||
"youtube": "#",
|
||||
"email": "hallo@miyakarate.de"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,31 @@
|
|||
{
|
||||
"siteTitle": "EmyKarate",
|
||||
"hero": {
|
||||
"badge": "MEINE REISE IN KATA hh",
|
||||
"description": "Entdecke die Welt des Karate durch meine Augen. Von den ersten Schritten im Dojo bis hin zu nationalen Meisterschaften – hier teile ich meine Leidenschaft für Bewegung, Disziplin und Erfolg. hh",
|
||||
"badge": "MEINE REISE IN KATA ",
|
||||
"description": "Entdecke die Welt des Karate durch meine Augen. Von den ersten Schritten im Dojo bis hin zu nationalen Meisterschaften – hier teile ich meine Leidenschaft für Bewegung, Disziplin und Erfolg. ",
|
||||
"image": "hero.webp"
|
||||
},
|
||||
"hero_karte": {
|
||||
"rang": "Blaugurt",
|
||||
"status": "Status 2024"
|
||||
},
|
||||
"stats": [
|
||||
{
|
||||
"value": "7+",
|
||||
"label": "Jahre Training"
|
||||
},
|
||||
{
|
||||
"value": "1",
|
||||
"label": "Gold Medaillen"
|
||||
},
|
||||
{
|
||||
"value": "11",
|
||||
"label": "Turniere"
|
||||
}
|
||||
]
|
||||
}
|
||||
{ "value": "7+", "label": "Jahre Training" },
|
||||
{ "value": "1", "label": "Gold Medaillen" },
|
||||
{ "value": "11", "label": "Turniere" }
|
||||
],
|
||||
"pruefung_karte": {
|
||||
"titel": "Prüfung bestanden",
|
||||
"beschreibung": "Neuer Gürtelgrad erreicht! Jetzt stolze Trägerin des Blaugurts."
|
||||
},
|
||||
"dojo_karte": {
|
||||
"titel": "Dojo Champion",
|
||||
"beschreibung": "Hausinterner Wettbewerb im Dojo \"Kiai Berlin\"."
|
||||
},
|
||||
"cta": {
|
||||
"heading_main": "Bereit für mehr",
|
||||
"heading_colored": "Action?",
|
||||
"description": "Schau dir hunderte Fotos von Trainingseinheiten, Turnieren und Reisen in meiner großen Galerie an.",
|
||||
"button_text": "ZUR GALERIE GEHEN"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"hero": {
|
||||
"badge": "Meine Reise h",
|
||||
"heading_line1": "KINETISCHE h",
|
||||
"heading_line2": "ELEGANZ h",
|
||||
"heading_suffix": "IN JEDEM SCHLAG. h",
|
||||
"badge": "Meine Reise ",
|
||||
"heading_line1": "KINETISCHE",
|
||||
"heading_line2": "ELEGANZ",
|
||||
"heading_suffix": "IN JEDEM SCHLAG.",
|
||||
"description": "Seit ich sechs Jahre alt bin, ist das Dojo mein zweites Zuhause. Für mich ist Karate mehr als Medaillen – es ist eine Symphonie aus Fokus, Disziplin und explosiver Energie in einer einzigen Bewegung. hhh",
|
||||
"image": "portrait.webp",
|
||||
"image_alt": "Miya beim Karate-Kick",
|
||||
|
|
@ -50,11 +50,11 @@
|
|||
]
|
||||
},
|
||||
"haupterfolg": {
|
||||
"titel": "Landesmeisterschaft Berlin h",
|
||||
"platz": "Gold – Kata U14 h",
|
||||
"titel": "Landesmeisterschaft Berlin ",
|
||||
"platz": "Gold – Kata U14 ",
|
||||
"beschreibung": "Mein bisher größter Erfolg. Monatelanges hartes Training gipfelte in einer Vorführung, die meinen Wettkampfgeist unter Beweis stellte. hh ",
|
||||
"jahr": "2024 ",
|
||||
"ort": "Esslingen am Neckar h",
|
||||
"ort": "Esslingen am Neckar ",
|
||||
"kategorie": "U14"
|
||||
},
|
||||
"weitere_erfolge": [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
baseURL = "https://emy.bonzeipunk.de/"
|
||||
languageCode = "de"
|
||||
title = "MiyaKarate"
|
||||
title = "EmyKarate"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>{{ .Title }} | MiyaKarate</title>
|
||||
<title>{{ .Title }} | EmyKarate</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@700;900&family=Be+Vietnam+Pro:wght@400;500&display=swap" rel="stylesheet"/>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Erfolge | MiyaKarate</title>
|
||||
<title>Erfolge | {{ .Site.Data.homepage.siteTitle | default .Site.Title }}</title>
|
||||
<link href="https://fonts.googleapis.com" rel="preconnect"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700;800;900&family=Be+Vietnam+Pro:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
<!-- TopAppBar -->
|
||||
<header class="bg-white/70 dark:bg-zinc-900/70 backdrop-blur-lg fixed top-0 left-0 w-full z-50 shadow-xl shadow-pink-500/5">
|
||||
<div class="flex justify-between items-center h-20 px-6 md:px-12 max-w-screen-2xl mx-auto">
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">MiyaKarate</a>
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</a>
|
||||
<nav class="hidden md:flex items-center space-x-8 font-headline tracking-tight uppercase font-bold">
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium hover:text-pink-500 dark:hover:text-pink-300 transition-colors duration-300" href="/">Home</a>
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium hover:text-pink-500 dark:hover:text-pink-300 transition-colors duration-300" href="/galerie/">Galerie</a>
|
||||
|
|
@ -81,24 +81,30 @@
|
|||
</div>
|
||||
</header>
|
||||
|
||||
{{ $e := .Site.Data.erfolge }}
|
||||
|
||||
<main class="pt-32 pb-20">
|
||||
<!-- Hero -->
|
||||
<section class="max-w-7xl mx-auto px-6 mb-24">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-center">
|
||||
<div class="lg:col-span-7">
|
||||
<span class="text-primary font-bold tracking-[0.2em] uppercase text-sm mb-4 block">Meine Wettkampf-Geschichte</span>
|
||||
<span class="text-primary font-bold tracking-[0.2em] uppercase text-sm mb-4 block">{{ $e.hero.badge }}</span>
|
||||
<h1 class="text-6xl md:text-8xl font-headline font-extrabold text-on-surface leading-[0.9] tracking-tighter mb-8">
|
||||
JEDER SIEG <span class="text-glass-gradient">ZÄHLT.</span>
|
||||
{{ $e.hero.heading_main }} <span class="text-glass-gradient">{{ $e.hero.heading_colored }}</span>
|
||||
</h1>
|
||||
<p class="text-xl text-on-surface-variant leading-relaxed max-w-xl">
|
||||
Von der ersten Gürtelprüfung bis zur Landesmeisterschaft – hier sammle ich alle Momente, auf die ich besonders stolz bin.
|
||||
{{ $e.hero.description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="lg:col-span-5 relative">
|
||||
<div class="aspect-[4/5] rounded-xl overflow-hidden editorial-shadow bg-surface-container-highest">
|
||||
<img class="w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuD_gAlNnXIZRs_NnR68igfJUfHX1ueNZlrjMt15L5xNz3bnL4235YADrLG-nT3wz2ZWYEZy6Dom8-fgsolN77eu_0JF52Xp-YjWEre5kwxN2D6V5LAoXI_T8I2YSU6LI5ZybF1Y1Ynqp8Y2IzCh0DYZOqY_tlPOuzsExGMn7nO0jWw58sR7Ny1674begJzhSNxELjEE7oQfgLjSZaO17dv1vGG5LykvtL9NEqM2JXdOVh0SlsnUN4416utgLZpV8km6wUza_TY7Fg"
|
||||
alt="Miya beim Wettkampf"/>
|
||||
{{ if $e.hero.image }}
|
||||
<img class="w-full h-full object-cover" src="/erfolge-img/{{ $e.hero.image }}" alt="{{ $e.hero.rang_value }} beim Wettkampf"/>
|
||||
{{ else }}
|
||||
<div class="w-full h-full bg-surface-container-high flex items-center justify-center">
|
||||
<span class="material-symbols-outlined text-surface-variant" style="font-size:6rem;">sports_martial_arts</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="absolute -bottom-10 -left-10 bg-white p-8 rounded-lg editorial-shadow hidden md:block">
|
||||
<div class="flex items-center gap-4">
|
||||
|
|
@ -106,8 +112,8 @@
|
|||
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">workspace_premium</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-bold uppercase tracking-widest text-secondary">Aktueller Rang</div>
|
||||
<div class="text-2xl font-headline font-black text-on-surface">Blaugurt</div>
|
||||
<div class="text-sm font-bold uppercase tracking-widest text-secondary">{{ $e.hero.rang_label }}</div>
|
||||
<div class="text-2xl font-headline font-black text-on-surface">{{ $e.hero.rang_value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -119,49 +125,82 @@
|
|||
<section class="bg-surface-container-low py-24 rounded-t-[5rem]">
|
||||
<div class="max-w-7xl mx-auto px-6">
|
||||
<h2 class="text-4xl font-headline font-bold text-on-surface mb-16">Alle Erfolge</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 items-start">
|
||||
{{ range (where .Site.RegularPages "Section" "erfolge") }}
|
||||
<div class="bg-surface-container-lowest rounded-xl p-8 editorial-shadow flex flex-col justify-between relative overflow-hidden group hover:shadow-xl transition-all duration-500">
|
||||
<div class="relative z-10">
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<span class="material-symbols-outlined text-3xl text-primary" style="font-variation-settings: 'FILL' 1;">military_tech</span>
|
||||
<div class="erfolg-card bg-surface-container-lowest rounded-xl editorial-shadow relative overflow-hidden group transition-all duration-500 hover:shadow-xl">
|
||||
<!-- Immer sichtbar -->
|
||||
<div class="p-8 relative z-10">
|
||||
<div class="flex items-center gap-4 mb-5">
|
||||
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0">
|
||||
<span class="material-symbols-outlined text-2xl text-primary" style="font-variation-settings: 'FILL' 1;">military_tech</span>
|
||||
</div>
|
||||
<span class="bg-secondary text-white px-4 py-1 rounded-full text-xs font-bold uppercase tracking-widest">{{ .Params.rang | default "Highlight" }}</span>
|
||||
</div>
|
||||
<h3 class="text-2xl font-headline font-bold text-on-surface mb-3">{{ .Title }}</h3>
|
||||
<p class="text-on-surface-variant mb-6">{{ .Summary }}</p>
|
||||
<a class="flex items-center gap-2 text-primary font-bold hover:gap-4 transition-all" href="{{ .RelPermalink }}">
|
||||
Bericht lesen <span class="material-symbols-outlined">arrow_forward</span>
|
||||
</a>
|
||||
<p class="text-on-surface-variant leading-relaxed mb-6">{{ .Summary }}</p>
|
||||
<button onclick="toggleErfolg(this)"
|
||||
class="flex items-center gap-2 text-primary font-bold text-sm font-headline uppercase tracking-wider hover:gap-3 transition-all">
|
||||
<span class="btn-label">Mehr lesen</span>
|
||||
<span class="material-symbols-outlined transition-transform duration-300 text-base">expand_more</span>
|
||||
</button>
|
||||
</div>
|
||||
<span class="material-symbols-outlined absolute -bottom-10 -right-10 text-[12rem] text-surface-container opacity-10 group-hover:opacity-20 transition-opacity">sports_martial_arts</span>
|
||||
<!-- Aufklappbarer Inhalt -->
|
||||
<div class="erfolg-body overflow-hidden transition-all duration-500 ease-in-out" style="max-height:0">
|
||||
<div class="px-8 pb-8 border-t border-surface-container-high">
|
||||
<div class="pt-6 text-on-surface-variant leading-relaxed space-y-4 text-base">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="material-symbols-outlined absolute -bottom-10 -right-10 text-[12rem] text-surface-container-high opacity-10 group-hover:opacity-20 transition-opacity pointer-events-none">sports_martial_arts</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function toggleErfolg(btn) {
|
||||
var card = btn.closest('.erfolg-card');
|
||||
var body = card.querySelector('.erfolg-body');
|
||||
var icon = btn.querySelector('.material-symbols-outlined');
|
||||
var label = btn.querySelector('.btn-label');
|
||||
var isOpen = body.style.maxHeight && body.style.maxHeight !== '0px';
|
||||
if (isOpen) {
|
||||
body.style.maxHeight = '0';
|
||||
icon.style.transform = '';
|
||||
label.textContent = 'Mehr lesen';
|
||||
} else {
|
||||
body.style.maxHeight = body.scrollHeight + 'px';
|
||||
icon.style.transform = 'rotate(180deg)';
|
||||
label.textContent = 'Weniger anzeigen';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Meilensteine Bento Grid -->
|
||||
<section class="max-w-7xl mx-auto px-6 mt-24">
|
||||
<h2 class="text-5xl font-headline font-black mb-16 tracking-tight">MEILENSTEINE DES <span class="text-primary italic">ERFOLGS</span></h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<!-- Große Karte -->
|
||||
|
||||
<!-- Große Karte: Haupt-Meilenstein -->
|
||||
<div class="md:col-span-2 bg-surface-container-lowest rounded-xl p-10 editorial-shadow flex flex-col justify-between relative overflow-hidden group">
|
||||
<div class="relative z-10">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<span class="material-symbols-outlined text-4xl text-primary" style="font-variation-settings: 'FILL' 1;">military_tech</span>
|
||||
<span class="font-headline font-extrabold text-2xl uppercase italic">Landesmeisterschaft Berlin</span>
|
||||
<span class="font-headline font-extrabold text-2xl uppercase italic">{{ $e.meilenstein.event }}</span>
|
||||
</div>
|
||||
<h3 class="text-4xl font-headline font-bold text-on-surface mb-4">Gold – Kata U14</h3>
|
||||
<p class="text-on-surface-variant max-w-md text-lg">Mein bisher größter Erfolg. Monatelanges hartes Training gipfelte in einer Vorführung, die meinen Wettkampfgeist unter Beweis stellte.</p>
|
||||
<h3 class="text-4xl font-headline font-bold text-on-surface mb-4">{{ $e.meilenstein.platz }}</h3>
|
||||
<p class="text-on-surface-variant max-w-md text-lg">{{ $e.meilenstein.beschreibung }}</p>
|
||||
</div>
|
||||
<div class="mt-12 flex items-center gap-6 relative z-10">
|
||||
<div>
|
||||
<div class="text-3xl font-black text-on-surface">2024</div>
|
||||
<div class="text-xs uppercase tracking-widest font-bold text-primary">Berlin</div>
|
||||
<div class="text-3xl font-black text-on-surface">{{ $e.meilenstein.jahr }}</div>
|
||||
<div class="text-xs uppercase tracking-widest font-bold text-primary">{{ $e.meilenstein.ort }}</div>
|
||||
</div>
|
||||
<div class="h-10 w-[1px] bg-outline-variant/30"></div>
|
||||
<div>
|
||||
<div class="text-3xl font-black text-on-surface">U14</div>
|
||||
<div class="text-3xl font-black text-on-surface">{{ $e.meilenstein.kategorie }}</div>
|
||||
<div class="text-xs uppercase tracking-widest font-bold text-primary">Kategorie</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -171,48 +210,41 @@
|
|||
<!-- Weitere Auszeichnungen -->
|
||||
<div class="bg-primary rounded-xl p-8 text-on-primary flex flex-col gap-8 shadow-2xl shadow-primary/20">
|
||||
<h4 class="font-headline font-bold text-xl border-b border-on-primary/20 pb-4">Weitere Auszeichnungen</h4>
|
||||
{{ $icons := slice "star" "emoji_events" "rewarded_ads" "workspace_premium" "military_tech" "sports_martial_arts" }}
|
||||
{{ range $i, $a := $e.weitere_auszeichnungen }}
|
||||
<div class="flex gap-4">
|
||||
<div class="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center shrink-0">
|
||||
<span class="material-symbols-outlined text-xl">star</span>
|
||||
<span class="material-symbols-outlined text-xl">{{ index $icons (mod $i (len $icons)) }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold">Norddeutsche Meisterschaft</p>
|
||||
<p class="text-sm opacity-80">Silber – Kata 2024</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<div class="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center shrink-0">
|
||||
<span class="material-symbols-outlined text-xl">emoji_events</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold">Dojo Champion</p>
|
||||
<p class="text-sm opacity-80">Kiai Berlin, intern</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<div class="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center shrink-0">
|
||||
<span class="material-symbols-outlined text-xl">rewarded_ads</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold">Fairness-Preis</p>
|
||||
<p class="text-sm opacity-80">Dojo-Auszeichnung 2023</p>
|
||||
<p class="font-bold">{{ $a.titel }}</p>
|
||||
<p class="text-sm opacity-80">{{ $a.detail }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
{{ $stats := $e.stats }}
|
||||
{{ with index $stats 0 }}
|
||||
<div class="bg-secondary-container rounded-xl p-8 flex flex-col justify-center gap-2">
|
||||
<span class="text-on-secondary-container font-headline font-black text-6xl italic">5+</span>
|
||||
<span class="text-secondary font-bold uppercase tracking-[0.2em] text-sm">Jahre Training</span>
|
||||
<span class="text-on-secondary-container font-headline font-black text-6xl italic">{{ .wert }}</span>
|
||||
<span class="text-secondary font-bold uppercase tracking-[0.2em] text-sm">{{ .label }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with index $stats 1 }}
|
||||
<div class="bg-surface-container-highest rounded-xl p-8 flex flex-col justify-center gap-2">
|
||||
<span class="text-on-surface font-headline font-black text-6xl italic">32</span>
|
||||
<span class="text-on-surface-variant font-bold uppercase tracking-[0.2em] text-sm">Turniere</span>
|
||||
<span class="text-on-surface font-headline font-black text-6xl italic">{{ .wert }}</span>
|
||||
<span class="text-on-surface-variant font-bold uppercase tracking-[0.2em] text-sm">{{ .label }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with index $stats 2 }}
|
||||
<div class="bg-white rounded-xl p-8 editorial-shadow flex flex-col justify-center gap-2 border-t-4 border-pink-500">
|
||||
<span class="text-pink-600 font-headline font-black text-6xl italic">12</span>
|
||||
<span class="text-zinc-500 font-bold uppercase tracking-[0.2em] text-sm">Goldmedaillen</span>
|
||||
<span class="text-pink-600 font-headline font-black text-6xl italic">{{ .wert }}</span>
|
||||
<span class="text-zinc-500 font-bold uppercase tracking-[0.2em] text-sm">{{ .label }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -220,22 +252,22 @@
|
|||
<section class="max-w-4xl mx-auto px-6 py-32 text-center">
|
||||
<span class="material-symbols-outlined text-primary text-6xl mb-8" style="font-variation-settings: 'FILL' 1;">format_quote</span>
|
||||
<blockquote class="text-3xl md:text-5xl font-headline font-bold text-on-surface leading-tight tracking-tight italic">
|
||||
"Karate ist nicht nur ein Sport. Es ist eine Linse, durch die ich die Welt sehe – mit Präzision, Respekt und unbeugsamer Konzentration."
|
||||
"{{ $e.zitat.text }}"
|
||||
</blockquote>
|
||||
<p class="mt-8 font-bold uppercase tracking-widest text-on-surface-variant">— Miya</p>
|
||||
<p class="mt-8 font-bold uppercase tracking-widest text-on-surface-variant">— {{ $e.zitat.autor }}</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-zinc-50 dark:bg-zinc-950 w-full rounded-t-[3rem] mt-20">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center py-12 px-8 max-w-7xl mx-auto gap-6 text-sm tracking-wide">
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">MiyaKarate</div>
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</div>
|
||||
<div class="flex gap-8 text-zinc-500">
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="#">Instagram</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="#">YouTube</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="#">Email</a>
|
||||
</div>
|
||||
<div class="text-zinc-500 opacity-80">© 2024 MiyaKarate. Alle Rechte vorbehalten.</div>
|
||||
<div class="text-zinc-500 opacity-80">© 2024 {{ .Site.Data.homepage.siteTitle | default .Site.Title }}. Alle Rechte vorbehalten.</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Gästebuch | MiyaKarate</title>
|
||||
<title>Gästebuch | {{ .Site.Data.homepage.siteTitle | default .Site.Title }}</title>
|
||||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@400;700;800;900&family=Be+Vietnam+Pro:wght@400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||
|
|
@ -57,16 +57,16 @@
|
|||
</style>
|
||||
</head>
|
||||
<body class="bg-surface text-on-surface font-body selection:bg-primary-container selection:text-on-primary-container">
|
||||
|
||||
{{ $gb := .Site.Data.gaestebuch }}
|
||||
<!-- TopAppBar -->
|
||||
<header class="fixed top-0 left-0 w-full z-50 bg-white/70 dark:bg-zinc-900/70 backdrop-blur-lg shadow-xl shadow-pink-500/5">
|
||||
<nav class="flex justify-between items-center h-20 px-6 md:px-12 max-w-screen-2xl mx-auto">
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">MiyaKarate</a>
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</a>
|
||||
<div class="hidden md:flex items-center gap-8">
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 transition-colors duration-300" href="/">Home</a>
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 transition-colors duration-300" href="/galerie/">Galerie</a>
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 transition-colors duration-300" href="/uebermich/">Über mich</a>
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 transition-colors duration-300" href="#">Erfolge</a>
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 transition-colors duration-300" href="/erfolge/">Erfolge</a>
|
||||
<a class="text-pink-600 dark:text-pink-400 border-b-2 border-pink-500 pb-1 font-headline tracking-tight uppercase font-bold" href="/gaestebuch/">Gästebuch</a>
|
||||
</div>
|
||||
<button class="bg-gradient-to-br from-primary to-primary-container text-on-primary px-8 py-3 rounded-xl font-bold uppercase tracking-wider scale-95 active:scale-90 transition-transform shadow-lg shadow-primary/20">
|
||||
|
|
@ -79,16 +79,20 @@
|
|||
<!-- Hero -->
|
||||
<section class="max-w-7xl mx-auto px-6 mb-20">
|
||||
<div class="relative rounded-xl overflow-hidden min-h-[400px] flex items-center p-8 md:p-16">
|
||||
{{ if $gb.hero.image }}
|
||||
<img alt="Gästebuch Hero" class="absolute inset-0 w-full h-full object-cover" src="/gaestebuch-img/{{ $gb.hero.image }}"/>
|
||||
{{ else }}
|
||||
<img alt="Karate Dojo" class="absolute inset-0 w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuDlVHSCQA9wTqwkVgz4Q76piwsWS33jFlIXlTw7TBSDubv3dQTnKkIUtU-rBAoPyO3eJ1BHdeKBNqS_CCcyhfI0XH1VHSDFSgxgH1oDxrICcX8b-GoehyY1x8udqwWfuKtSTI-nNW4i15l0HWDcVvSrtlM4u25KjM63nBbo_pfDq6f-larFS9uVzVlBn5KMcj8uioIHmQqPlVxWqlkETOL_6zr_Y-k_doAHs6brW-DdT4clT2MxJjtDFjxxr-cTzgKALEfMvTTJUg"/>
|
||||
{{ end }}
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-on-surface/80 via-on-surface/40 to-transparent"></div>
|
||||
<div class="relative z-10 max-w-2xl">
|
||||
<span class="inline-block px-4 py-1 rounded-full bg-secondary text-on-secondary font-label text-xs tracking-[0.1em] uppercase mb-4">Melde dich bei mir</span>
|
||||
<span class="inline-block px-4 py-1 rounded-full bg-secondary text-on-secondary font-label text-xs tracking-[0.1em] uppercase mb-4">{{ $gb.hero.badge }}</span>
|
||||
<h1 class="font-headline text-5xl md:text-7xl font-extrabold text-white leading-tight mb-6 tracking-tighter">
|
||||
Schreib mir & <span class="text-primary-container">teile deine Geschichte</span>
|
||||
{{ $gb.hero.heading }} <span class="text-primary-container">{{ $gb.hero.heading_colored }}</span>
|
||||
</h1>
|
||||
<p class="text-lg text-surface font-medium max-w-lg editorial-text">
|
||||
Ob du eine Frage zu meinem Training hast oder einfach eine nette Nachricht hinterlassen möchtest – ich freue mich von dir zu hören!
|
||||
{{ $gb.hero.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -154,7 +158,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-bold uppercase opacity-60">E-Mail</p>
|
||||
<p class="font-bold">hallo@miyakarate.de</p>
|
||||
<p class="font-bold">{{ $gb.kontakt.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
|
|
@ -163,7 +167,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-bold uppercase opacity-60">Dojo</p>
|
||||
<p class="font-bold">Kiai Dojo Berlin</p>
|
||||
<p class="font-bold">{{ $gb.kontakt.dojo }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -175,23 +179,18 @@
|
|||
<h3 class="font-headline text-2xl font-bold">Neuester Eintrag</h3>
|
||||
<a class="text-primary font-bold text-sm hover:underline" href="#gaestebuch-wall">Alle ansehen</a>
|
||||
</div>
|
||||
{{ with index $gb.eintraege 0 }}
|
||||
<div class="glass-card p-6 rounded-lg shadow-sm border border-white/40">
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="w-12 h-12 rounded-full bg-surface-container-highest overflow-hidden">
|
||||
<img alt="Gast Avatar" class="w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuCyr8FcSn01QbwNHFaE4oEJCeSKkIcv6Qjd7WO_jrfclu0LeV9KMmCJ6VqttBmEZM9Cz7ddfK6gmQ8qGQmJ9YWno683_KcaFT_BhaOws3_rpcvPU2j1xquZD0bzluyw84dqcvLLIXsyqWVYMGqlAwXoW78olS5BfpuvMiBkh3bIIgo8kIhWJkq7R1MZB4yCmnTN2UyzrVSy9aUM_vmaU1AZFhWUgk7UOsN1BST2xOACH2NhCB6HP_93OnTDjAAXBja3bufXiAjZkw"/>
|
||||
</div>
|
||||
<div class="w-12 h-12 rounded-full bg-secondary text-on-secondary flex items-center justify-center font-bold text-xl">{{ substr .name 0 1 }}</div>
|
||||
<div>
|
||||
<h4 class="font-bold">Jonas L.</h4>
|
||||
<p class="text-xs text-on-surface-variant font-medium">vor 2 Stunden</p>
|
||||
<h4 class="font-bold">{{ .name }}</h4>
|
||||
<p class="text-xs text-on-surface-variant font-medium">{{ .rolle }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-on-surface-variant leading-relaxed">"Mega Fortschritte bei deiner letzten Kata! Deine Hingabe ist wirklich inspirierend. Weiter so! Oss!"</p>
|
||||
<div class="mt-4 flex gap-2">
|
||||
<span class="px-3 py-1 rounded-full bg-primary/10 text-primary text-[10px] font-bold uppercase">Teamkamerad</span>
|
||||
<span class="px-3 py-1 rounded-full bg-secondary/10 text-secondary text-[10px] font-bold uppercase">Inspiriert</span>
|
||||
</div>
|
||||
<p class="text-on-surface-variant leading-relaxed">"{{ .text }}"</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -203,81 +202,33 @@
|
|||
<p class="text-on-surface-variant max-w-2xl mx-auto">Nachrichten von Trainingspartnern, Familie und Freunden aus aller Welt.</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div class="bg-white rounded-lg p-6 shadow-xl shadow-black/5 hover:-translate-y-2 transition-transform duration-300">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-surface-container overflow-hidden">
|
||||
<img alt="Gast" class="w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuAxxSG4TUDr606KVR8_FBXcG1vZu-IryVXVsyk0ildPn-mTI7Xhf3_kclVMF91JkR_jx9eWesri4dDj4vf9U7gKuzWCMe6W52Bwgndg_mOwNf6WgregdNT9uH1bwxH2reR5LR_M8Stb6dLfl3O1u0qC3l8W_jcpH2FrTQY-onMUIiasTQNndMFCSqJy2Y8NBCjJkq7eSFELqR7CicXvpe3dSLeE_WyzxADxwlGyY3tPS7nYZuYCJvctYZl0hDvGF1HYDhKj3Xw5rg"/>
|
||||
</div>
|
||||
{{ range $gb.eintraege }}
|
||||
{{ $span := "" }}{{ if .breit }}{{ $span = "md:col-span-2" }}{{ end }}
|
||||
{{ if eq .farbe "secondary" }}
|
||||
<div class="bg-gradient-to-br from-secondary/5 to-primary/5 border border-white rounded-lg p-6 shadow-xl shadow-black/5 {{ $span }}">
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="w-12 h-12 rounded-full bg-secondary text-on-secondary flex items-center justify-center font-bold text-xl">{{ substr .name 0 1 }}</div>
|
||||
<div>
|
||||
<p class="font-bold text-sm">Trainerin Elena</p>
|
||||
<p class="text-[10px] uppercase font-bold text-outline">Sensei</p>
|
||||
<p class="font-bold">{{ .name }}</p>
|
||||
<p class="text-xs font-medium text-secondary">{{ .rolle }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<blockquote class="text-on-surface-variant italic text-lg leading-relaxed">"{{ .text }}"</blockquote>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="bg-white rounded-lg p-6 shadow-xl shadow-black/5 hover:-translate-y-2 transition-transform duration-300 {{ $span }}">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-surface-container flex items-center justify-center font-bold text-sm text-on-surface-variant">{{ substr .name 0 1 }}</div>
|
||||
<div>
|
||||
<p class="font-bold text-sm">{{ .name }}</p>
|
||||
<p class="text-[10px] uppercase font-bold text-outline">{{ .rolle }}</p>
|
||||
</div>
|
||||
<span class="ml-auto material-symbols-outlined text-primary text-xl" style="font-variation-settings: 'FILL' 1;">favorite</span>
|
||||
</div>
|
||||
<p class="text-sm text-on-surface-variant leading-relaxed">Deine Konzentration beim letzten Grading war außergewöhnlich. Die Körperkontrolle, die du entwickelst, ist selten für dein Alter. Ich bin stolz auf dich!</p>
|
||||
<p class="text-sm text-on-surface-variant leading-relaxed">{{ .text }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg p-6 shadow-xl shadow-black/5 hover:-translate-y-2 transition-transform duration-300">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-surface-container overflow-hidden">
|
||||
<img alt="Gast" class="w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuCcEhcufxMA4pz_Ukcsfi9JIzXT6dS8M_1HuhSOhs00ftkIx_Dm74awVwHZURNxLYx0JSSosudUn5s21X0gOha6KwIsVz-esI6HO9WqQcgRm3Y6rxuM0eL2QbJtx16wJdxq9y05JLIjBpLGEQB7iemBIX7lH6RF86cxV0Cq0I_KA_vTkcLwxPunt79vO6NUt-zb0v3PP59gVEHOJOfFnnOlRqTe42kS28CfXGeWY5920CQDOjHFpQ6SH45XSQPSKMICsP5ANa3Wdw"/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold text-sm">Opa Karl</p>
|
||||
<p class="text-[10px] uppercase font-bold text-outline">Familie</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-on-surface-variant leading-relaxed">Wir drücken dir von zuhause alle die Daumen! Kann es kaum erwarten, den nächsten Pokal auf dem Regal zu sehen!</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg p-6 shadow-xl shadow-black/5 hover:-translate-y-2 transition-transform duration-300">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-surface-container overflow-hidden">
|
||||
<img alt="Gast" class="w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuCx78Ehwgx2xoiA9H_WHtwOteg8d8slllmcu2c66Ty-RnDNmX6sUEtNNsUXBXtINwZ4tg8WGxUjfbOSbtBWbcAUlaKqTTGgVOicODmvzt6PsT-hNu-JvwoOsmr-MSza1orgDZlUWKAcCY1XSByhyrJ6pFRT964VljwFvJd9KUKJFtd18GKw5qqh5IqcTt9_jrZFtOMFAGio1uK1GT3pyJA3WyGYMyUAbUWucPVTcnB9qo44WUkfg4k4LcmL7soUZK4bvTGxLg_m-g"/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold text-sm">Lea M.</p>
|
||||
<p class="text-[10px] uppercase font-bold text-outline">Freundin</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-on-surface-variant leading-relaxed">Die Website sieht so professionell aus! Mega cool, alle deine Erfolge an einem Ort zu sehen. Wir müssen bald mal wieder eis essen gehen!</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-gradient-to-br from-secondary/5 to-primary/5 border border-white rounded-lg p-6 shadow-xl shadow-black/5 md:col-span-2">
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="w-12 h-12 rounded-full bg-secondary text-on-secondary flex items-center justify-center font-bold text-xl">T</div>
|
||||
<div>
|
||||
<p class="font-bold">Trainer Thomas</p>
|
||||
<p class="text-xs font-medium text-secondary">Dojo Kiai Berlin</p>
|
||||
</div>
|
||||
</div>
|
||||
<blockquote class="text-on-surface-variant italic text-lg leading-relaxed mb-4">
|
||||
"Ich trainiere viele Kinder, aber die kinetische Flüssigkeit in deinen Bewegungen ist etwas Besonderes. Du machst jede Kata zu einem Tanz. Weiter so – der nächste schwarze Gürtel wartet schon!"
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg p-6 shadow-xl shadow-black/5 hover:-translate-y-2 transition-transform duration-300">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-surface-container overflow-hidden">
|
||||
<img alt="Gast" class="w-full h-full object-cover"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuA09PdHK61xpLhrsPtonFk8dj5CKIW26fygdA6IlzV7oS96jGwscnrGsFu947MCZ2oPdbWP8STBciRmN8FDLKPOdHJKd2dBi3-pwlmDsyDAU8Myi4GtGEQLay6v7P_DOoRN64fPfZcEaXRNrje0eYe-DyAiDAXCRfqYVwK_ducZzu4e-ZOQIyXaJRA1LtJwkiF1EHDj2Kcp4z9TmQGWpc9HtLA7D7uQ7XcncDH-HSYLS8ZR3rC4h90gf9_CJfzUfHC8MSeSdQKABg"/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-bold text-sm">Herr Braun</p>
|
||||
<p class="text-[10px] uppercase font-bold text-outline">Lehrer</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-on-surface-variant leading-relaxed">Balance im Sport führt zu Balance im Leben. Halt die Disziplin, die du im Dojo zeigst, auch in der Schule!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-12 text-center">
|
||||
<button class="bg-surface-container-highest hover:bg-surface-container-high px-10 py-4 rounded-xl font-bold transition-colors">
|
||||
Weitere Einträge laden
|
||||
</button>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
|
@ -285,13 +236,14 @@
|
|||
<!-- Footer -->
|
||||
<footer class="w-full rounded-t-[3rem] mt-20 bg-zinc-50 dark:bg-zinc-950">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center py-12 px-8 max-w-7xl mx-auto gap-6 text-sm tracking-wide">
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">MiyaKarate</div>
|
||||
{{ $social := .Site.Data.global.social }}
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</div>
|
||||
<div class="flex gap-8 text-zinc-500">
|
||||
<a class="hover:text-pink-500 transition-opacity hover:underline decoration-pink-500 decoration-2 underline-offset-4" href="#">Instagram</a>
|
||||
<a class="hover:text-pink-500 transition-opacity hover:underline decoration-pink-500 decoration-2 underline-offset-4" href="#">YouTube</a>
|
||||
<a class="hover:text-pink-500 transition-opacity hover:underline decoration-pink-500 decoration-2 underline-offset-4" href="#">Email</a>
|
||||
<a class="hover:text-pink-500 transition-opacity hover:underline decoration-pink-500 decoration-2 underline-offset-4" href="{{ $social.instagram }}">Instagram</a>
|
||||
<a class="hover:text-pink-500 transition-opacity hover:underline decoration-pink-500 decoration-2 underline-offset-4" href="{{ $social.youtube }}">YouTube</a>
|
||||
<a class="hover:text-pink-500 transition-opacity hover:underline decoration-pink-500 decoration-2 underline-offset-4" href="mailto:{{ $social.email }}">Email</a>
|
||||
</div>
|
||||
<div class="text-zinc-500">© 2024 MiyaKarate. Alle Rechte vorbehalten.</div>
|
||||
<div class="text-zinc-500">© 2024 {{ .Site.Data.homepage.siteTitle | default .Site.Title }}. Alle Rechte vorbehalten.</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Galerie | MiyaKarate</title>
|
||||
<title>Galerie | {{ .Site.Data.homepage.siteTitle | default .Site.Title }}</title>
|
||||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;600;700;800;900&family=Be+Vietnam+Pro:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
<!-- TopAppBar -->
|
||||
<header class="fixed top-0 left-0 w-full z-50 bg-white/70 dark:bg-zinc-900/70 backdrop-blur-lg shadow-xl shadow-pink-500/5">
|
||||
<div class="flex justify-between items-center h-20 px-6 md:px-12 max-w-screen-2xl mx-auto">
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">MiyaKarate</a>
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</a>
|
||||
<nav class="hidden md:flex items-center gap-8">
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 transition-colors duration-300" href="/">Home</a>
|
||||
<a class="text-pink-600 dark:text-pink-400 border-b-2 border-pink-500 pb-1 font-headline tracking-tight uppercase font-bold" href="/galerie/">Galerie</a>
|
||||
|
|
@ -78,12 +78,13 @@
|
|||
<main class="pt-32 pb-20 px-6 max-w-7xl mx-auto">
|
||||
<!-- Header -->
|
||||
<header class="mb-16 relative">
|
||||
<span class="font-label text-sm uppercase tracking-[0.2em] font-bold text-primary mb-4 block">Visuelle Reise</span>
|
||||
{{ $gal := .Site.Data.galerie }}
|
||||
<span class="font-label text-sm uppercase tracking-[0.2em] font-bold text-primary mb-4 block">{{ $gal.hero.badge }}</span>
|
||||
<h1 class="font-headline text-5xl md:text-7xl font-black text-on-surface leading-[1.1] tracking-tight mb-6">
|
||||
Eingefangene <br/><span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary">Momente.</span>
|
||||
{{ $gal.hero.heading_main }} <br/><span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary">{{ $gal.hero.heading_colored }}</span>
|
||||
</h1>
|
||||
<p class="max-w-xl text-on-surface-variant text-lg leading-relaxed">
|
||||
Die Kunst der Disziplin durch die Linse. Von intensiven Trainingseinheiten bis zum Triumph bei Gürtelprüfungen.
|
||||
{{ $gal.hero.description }}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
|
@ -159,26 +160,21 @@
|
|||
|
||||
<!-- Stats Ribbon -->
|
||||
<section class="bg-surface-container-low py-20 px-6">
|
||||
{{ $ribbon := $gal.ribbon }}
|
||||
{{ $statColors := slice "text-primary" "text-secondary" "text-primary" }}
|
||||
<div class="max-w-7xl mx-auto flex flex-col md:flex-row justify-between items-center gap-12">
|
||||
<div class="flex-1">
|
||||
<h2 class="font-headline text-3xl font-bold mb-4">Hinter der Linse</h2>
|
||||
<p class="text-on-surface-variant max-w-md">Unsere Galerie ist nicht nur Fotos – sie ist ein Zeugnis der Disziplin, die wir jeden Tag im MiyaKarate Dojo leben.</p>
|
||||
<h2 class="font-headline text-3xl font-bold mb-4">{{ $ribbon.heading }}</h2>
|
||||
<p class="text-on-surface-variant max-w-md">{{ $ribbon.description }}</p>
|
||||
</div>
|
||||
<div class="flex gap-8 overflow-x-auto pb-4 no-scrollbar w-full md:w-auto">
|
||||
{{ range $i, $s := $ribbon.stats }}
|
||||
{{ if gt $i 0 }}<div class="h-12 w-px bg-outline-variant/30 hidden md:block"></div>{{ end }}
|
||||
<div class="flex-shrink-0 text-center">
|
||||
<p class="text-4xl font-black text-primary font-headline">24</p>
|
||||
<p class="text-xs uppercase tracking-widest font-bold opacity-60">Turniere</p>
|
||||
</div>
|
||||
<div class="h-12 w-px bg-outline-variant/30 hidden md:block"></div>
|
||||
<div class="flex-shrink-0 text-center">
|
||||
<p class="text-4xl font-black text-secondary font-headline">150+</p>
|
||||
<p class="text-xs uppercase tracking-widest font-bold opacity-60">Schüler</p>
|
||||
</div>
|
||||
<div class="h-12 w-px bg-outline-variant/30 hidden md:block"></div>
|
||||
<div class="flex-shrink-0 text-center">
|
||||
<p class="text-4xl font-black text-primary font-headline">85</p>
|
||||
<p class="text-xs uppercase tracking-widest font-bold opacity-60">Gürtelprüfungen</p>
|
||||
<p class="text-4xl font-black {{ index $statColors $i }} font-headline">{{ $s.wert }}</p>
|
||||
<p class="text-xs uppercase tracking-widest font-bold opacity-60">{{ $s.label }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -186,13 +182,14 @@
|
|||
<!-- Footer -->
|
||||
<footer class="bg-zinc-50 dark:bg-zinc-950 w-full rounded-t-[3rem] mt-20">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center py-12 px-8 max-w-7xl mx-auto gap-6 text-sm tracking-wide">
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">MiyaKarate</div>
|
||||
{{ $social := .Site.Data.global.social }}
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</div>
|
||||
<div class="flex gap-8">
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="#">Instagram</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="#">YouTube</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="#">Email</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="{{ $social.instagram }}">Instagram</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="{{ $social.youtube }}">YouTube</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="mailto:{{ $social.email }}">Email</a>
|
||||
</div>
|
||||
<div class="text-zinc-500">© 2024 MiyaKarate. Alle Rechte vorbehalten.</div>
|
||||
<div class="text-zinc-500">© 2024 {{ .Site.Data.homepage.siteTitle | default .Site.Title }}. Alle Rechte vorbehalten.</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>{{ .Title }} | MiyaKarate</title>
|
||||
<title>{{ .Title }} | EmyKarate</title>
|
||||
<link href="https://fonts.googleapis.com" rel="preconnect"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700;800;900&family=Be+Vietnam+Pro:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
<nav class="fixed top-0 left-0 w-full z-50 bg-white/70 dark:bg-zinc-900/70 backdrop-blur-lg shadow-xl shadow-pink-500/5">
|
||||
<div class="flex justify-between items-center h-20 px-6 md:px-12 max-w-screen-2xl mx-auto">
|
||||
<div class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">
|
||||
MiyaKarate
|
||||
{{ .Site.Data.homepage.siteTitle | default .Site.Title }}
|
||||
</div>
|
||||
<div class="hidden md:flex items-center gap-8">
|
||||
<a class="text-pink-600 dark:text-pink-400 border-b-2 border-pink-500 pb-1 font-headline tracking-tight uppercase font-bold transition-colors duration-300" href="/">Home</a>
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
<a class="text-zinc-600 dark:text-zinc-400 font-medium font-headline tracking-tight uppercase hover:text-pink-500 dark:hover:text-pink-300 transition-colors duration-300" href="/gaestebuch/">Gästebuch</a>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<button class="bg-gradient-to-br from-primary to-primary-container text-on-primary px-8 py-3 rounded-xl font-bold font-headline tracking-tight uppercase scale-95 active:scale-90 transition-transform">
|
||||
<button onclick="document.getElementById('kontaktModal').classList.remove('hidden')" class="bg-gradient-to-br from-primary to-primary-container text-on-primary px-8 py-3 rounded-xl font-bold font-headline tracking-tight uppercase scale-95 active:scale-90 transition-transform">
|
||||
Kontakt
|
||||
</button>
|
||||
<button class="md:hidden text-primary">
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
{{ if .Site.Data.homepage.hero.image }}
|
||||
<img alt="Miya beim Karate-Tritt" class="w-full h-full object-cover" src="/hero/{{ .Site.Data.homepage.hero.image }}"/>
|
||||
{{ else }}
|
||||
<img alt="Miya beim Karate-Tritt" class="w-full h-full object-cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAHCy-F1uHI1Lq8D0LuZVWXLZA4URfCtFVtXNvimgi_5HnX4ovI2C3Cl_nLp5awhMAL-cwWnK-fL-yQHgwYZ2SWg5JbnH7RkQtVdUqPCb9PcOAFIzdX9haBXQGoCYywwzqNXK4QqQoJ5XxnamSZghNPUK0pOLszlu2jowGPO8VWtQmD7PcJTOGfpOCUxw8tNzeeNTQsCDmPoGD3N8ZjTyTGD6Sk48MrYJrRUgiRvBi9tznnMXIgqMsN8G0v8JA3aQeF5jQlZmJ3kw"/>
|
||||
<img alt="Emy beim Karate-Tritt" class="w-full h-full object-cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAHCy-F1uHI1Lq8D0LuZVWXLZA4URfCtFVtXNvimgi_5HnX4ovI2C3Cl_nLp5awhMAL-cwWnK-fL-yQHgwYZ2SWg5JbnH7RkQtVdUqPCb9PcOAFIzdX9haBXQGoCYywwzqNXK4QqQoJ5XxnamSZghNPUK0pOLszlu2jowGPO8VWtQmD7PcJTOGfpOCUxw8tNzeeNTQsCDmPoGD3N8ZjTyTGD6Sk48MrYJrRUgiRvBi9tznnMXIgqMsN8G0v8JA3aQeF5jQlZmJ3kw"/>
|
||||
{{ end }}
|
||||
<div class="absolute bottom-8 -left-8 bg-white/40 backdrop-blur-xl p-6 rounded-lg shadow-xl border border-white/20 -rotate-6">
|
||||
<div class="flex items-center gap-4">
|
||||
|
|
@ -152,8 +152,8 @@
|
|||
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">stars</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-headline font-bold text-on-surface uppercase leading-none">Blaugurt</p>
|
||||
<p class="text-xs text-on-surface-variant uppercase tracking-widest mt-1">Status 2024</p>
|
||||
<p class="font-headline font-bold text-on-surface uppercase leading-none">{{ .Site.Data.homepage.hero_karte.rang }}</p>
|
||||
<p class="text-xs text-on-surface-variant uppercase tracking-widest mt-1">{{ .Site.Data.homepage.hero_karte.status }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -203,8 +203,8 @@
|
|||
<div class="md:col-span-4 bg-primary text-on-primary rounded-xl p-8 flex flex-col justify-between hover:scale-[1.02] transition-transform shadow-xl shadow-primary/20">
|
||||
<span class="material-symbols-outlined text-4xl" style="font-variation-settings: 'FILL' 1;">military_tech</span>
|
||||
<div>
|
||||
<h3 class="text-2xl font-black font-headline mb-2">Prüfung bestanden</h3>
|
||||
<p class="text-on-primary/80">Neuer Gürtelgrad erreicht! Jetzt stolze Trägerin des Blaugurts.</p>
|
||||
<h3 class="text-2xl font-black font-headline mb-2">{{ .Site.Data.homepage.pruefung_karte.titel }}</h3>
|
||||
<p class="text-on-primary/80">{{ .Site.Data.homepage.pruefung_karte.beschreibung }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -213,8 +213,8 @@
|
|||
<div class="w-12 h-12 bg-white rounded-lg flex items-center justify-center mb-6 shadow-sm">
|
||||
<span class="material-symbols-outlined text-secondary">fitness_center</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-black font-headline mb-2">Dojo Champion</h3>
|
||||
<p class="text-sm text-on-surface-variant italic">Hausinterner Wettbewerb im Dojo "Kiai Berlin".</p>
|
||||
<h3 class="text-xl font-black font-headline mb-2">{{ .Site.Data.homepage.dojo_karte.titel }}</h3>
|
||||
<p class="text-sm text-on-surface-variant italic">{{ .Site.Data.homepage.dojo_karte.beschreibung }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Bild: Team Spirit -->
|
||||
|
|
@ -235,10 +235,10 @@
|
|||
<section class="py-24 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-zinc-900 -z-10"></div>
|
||||
<div class="max-w-7xl mx-auto px-6 text-center text-white">
|
||||
<h2 class="text-5xl md:text-7xl font-black font-headline italic mb-8">Bereit für mehr <span class="text-primary-fixed">Action?</span></h2>
|
||||
<p class="text-xl text-zinc-400 max-w-2xl mx-auto mb-12">Schau dir hunderte Fotos von Trainingseinheiten, Turnieren und Reisen in meiner großen Galerie an.</p>
|
||||
<a class="inline-flex items-center gap-4 bg-primary text-white px-12 py-6 rounded-full font-black font-headline text-xl hover:bg-primary-dim transition-colors group" href="#">
|
||||
ZUR GALERIE GEHEN
|
||||
<h2 class="text-5xl md:text-7xl font-black font-headline italic mb-8">{{ .Site.Data.homepage.cta.heading_main }} <span class="text-primary-fixed">{{ .Site.Data.homepage.cta.heading_colored }}</span></h2>
|
||||
<p class="text-xl text-zinc-400 max-w-2xl mx-auto mb-12">{{ .Site.Data.homepage.cta.description }}</p>
|
||||
<a class="inline-flex items-center gap-4 bg-primary text-white px-12 py-6 rounded-full font-black font-headline text-xl hover:bg-primary-dim transition-colors group" href="/galerie/">
|
||||
{{ .Site.Data.homepage.cta.button_text }}
|
||||
<span class="material-symbols-outlined group-hover:translate-x-2 transition-transform">auto_awesome_motion</span>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -252,18 +252,116 @@
|
|||
<footer class="w-full rounded-t-[3rem] mt-20 bg-zinc-50 dark:bg-zinc-950">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center py-12 px-8 max-w-7xl mx-auto gap-6">
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">
|
||||
MiyaKarate
|
||||
{{ .Site.Data.homepage.siteTitle | default .Site.Title }}
|
||||
</div>
|
||||
<div class="flex gap-8 text-sm tracking-wide">
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="#">Instagram</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="#">YouTube</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="#">Email</a>
|
||||
{{ $social := .Site.Data.global.social }}
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="{{ $social.instagram }}">Instagram</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="{{ $social.youtube }}">YouTube</a>
|
||||
<a class="text-zinc-500 hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity opacity-80 hover:opacity-100" href="mailto:{{ $social.email }}">Email</a>
|
||||
</div>
|
||||
<div class="text-sm tracking-wide text-zinc-500">
|
||||
© 2024 MiyaKarate. Alle Rechte vorbehalten.
|
||||
© 2024 {{ .Site.Data.homepage.siteTitle | default .Site.Title }}. Alle Rechte vorbehalten.
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
<!-- Kontakt Modal -->
|
||||
<div id="kontaktModal" class="hidden fixed inset-0 z-[100] flex items-center justify-center p-4">
|
||||
<div class="absolute inset-0 bg-black/50 backdrop-blur-sm" onclick="closeKontakt()"></div>
|
||||
<div class="relative bg-white rounded-2xl shadow-2xl w-full max-w-lg p-8 animate-none">
|
||||
|
||||
<!-- Header -->
|
||||
<div class="flex items-start justify-between mb-8">
|
||||
<div>
|
||||
<span class="inline-block px-3 py-1 rounded-full bg-secondary-container text-on-secondary-container text-xs font-bold tracking-widest uppercase mb-3 font-label">Schreib mir</span>
|
||||
<h2 class="text-3xl font-black font-headline text-on-surface italic">Kontakt</h2>
|
||||
</div>
|
||||
<button onclick="closeKontakt()" class="text-on-surface-variant hover:text-on-surface transition-colors mt-1">
|
||||
<span class="material-symbols-outlined">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Formular -->
|
||||
<form id="kontaktForm" class="space-y-4" onsubmit="submitKontakt(event)">
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-on-surface-variant mb-1.5 font-label uppercase tracking-wide">Name</label>
|
||||
<input type="text" name="name" required placeholder="Dein Name"
|
||||
class="w-full border-2 border-outline-variant rounded-xl px-4 py-3 text-on-surface focus:outline-none focus:border-primary transition-colors font-body"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-on-surface-variant mb-1.5 font-label uppercase tracking-wide">E-Mail</label>
|
||||
<input type="email" name="email" required placeholder="deine@email.de"
|
||||
class="w-full border-2 border-outline-variant rounded-xl px-4 py-3 text-on-surface focus:outline-none focus:border-primary transition-colors font-body"/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-on-surface-variant mb-1.5 font-label uppercase tracking-wide">Nachricht</label>
|
||||
<textarea name="message" required rows="4" placeholder="Deine Nachricht..."
|
||||
class="w-full border-2 border-outline-variant rounded-xl px-4 py-3 text-on-surface focus:outline-none focus:border-primary transition-colors font-body resize-none"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div id="kontaktStatus" class="hidden text-sm font-bold text-center py-2 rounded-xl"></div>
|
||||
|
||||
<button type="submit" id="kontaktBtn"
|
||||
class="w-full py-4 rounded-xl font-black font-headline text-lg bg-gradient-to-br from-primary to-primary-container text-on-primary shadow-lg shadow-primary/20 hover:scale-[1.02] active:scale-95 transition-transform">
|
||||
Absenden
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function closeKontakt() {
|
||||
document.getElementById('kontaktModal').classList.add('hidden');
|
||||
document.getElementById('kontaktForm').reset();
|
||||
document.getElementById('kontaktStatus').classList.add('hidden');
|
||||
document.getElementById('kontaktBtn').disabled = false;
|
||||
document.getElementById('kontaktBtn').textContent = 'Absenden';
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key === 'Escape') closeKontakt();
|
||||
});
|
||||
|
||||
async function submitKontakt(e) {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('kontaktBtn');
|
||||
const status = document.getElementById('kontaktStatus');
|
||||
const form = document.getElementById('kontaktForm');
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Wird gesendet…';
|
||||
|
||||
const data = Object.fromEntries(new FormData(form));
|
||||
|
||||
try {
|
||||
const res = await fetch('https://formsubmit.co/ajax/{{ .Site.Data.global.social.email }}', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
const json = await res.json();
|
||||
if (json.success === 'true' || json.success === true) {
|
||||
status.textContent = '✓ Nachricht gesendet! Ich melde mich bald.';
|
||||
status.className = 'text-sm font-bold text-center py-2 rounded-xl bg-green-50 text-green-700';
|
||||
status.classList.remove('hidden');
|
||||
form.reset();
|
||||
btn.textContent = 'Gesendet!';
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
} catch {
|
||||
status.textContent = '✗ Fehler beim Senden. Bitte versuche es später nochmal.';
|
||||
status.className = 'text-sm font-bold text-center py-2 rounded-xl bg-red-50 text-red-700';
|
||||
status.classList.remove('hidden');
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Absenden';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Über mich | MiyaKarate</title>
|
||||
<title>Über mich | {{ .Site.Data.homepage.siteTitle | default .Site.Title }}</title>
|
||||
<link href="https://fonts.googleapis.com" rel="preconnect"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700;800;900&family=Be+Vietnam+Pro:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
<!-- TopAppBar -->
|
||||
<header class="bg-white/70 dark:bg-zinc-900/70 backdrop-blur-lg fixed top-0 left-0 w-full z-50 shadow-xl shadow-pink-500/5">
|
||||
<div class="flex justify-between items-center h-20 px-6 md:px-12 max-w-screen-2xl mx-auto">
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">MiyaKarate</a>
|
||||
<a href="/" class="text-2xl font-black text-pink-600 dark:text-pink-400 italic font-headline tracking-tight uppercase">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</a>
|
||||
<nav class="hidden md:flex items-center space-x-8 font-headline tracking-tight uppercase font-bold">
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium hover:text-pink-500 dark:hover:text-pink-300 transition-colors duration-300" href="/">Home</a>
|
||||
<a class="text-zinc-600 dark:text-zinc-400 font-medium hover:text-pink-500 dark:hover:text-pink-300 transition-colors duration-300" href="/galerie/">Galerie</a>
|
||||
|
|
@ -229,13 +229,14 @@
|
|||
<!-- Footer -->
|
||||
<footer class="bg-zinc-50 dark:bg-zinc-950 w-full rounded-t-[3rem] mt-20">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center py-12 px-8 max-w-7xl mx-auto gap-6 text-sm tracking-wide">
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">MiyaKarate</div>
|
||||
{{ $social := .Site.Data.global.social }}
|
||||
<div class="text-lg font-bold text-zinc-900 dark:text-zinc-100 font-headline uppercase italic">{{ .Site.Data.homepage.siteTitle | default .Site.Title }}</div>
|
||||
<div class="flex gap-8 text-zinc-500">
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="#">Instagram</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="#">YouTube</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="#">Email</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="{{ $social.instagram }}">Instagram</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="{{ $social.youtube }}">YouTube</a>
|
||||
<a class="hover:text-pink-500 hover:underline decoration-pink-500 decoration-2 underline-offset-4 transition-opacity" href="mailto:{{ $social.email }}">Email</a>
|
||||
</div>
|
||||
<div class="text-zinc-500 opacity-80">© 2024 MiyaKarate. Alle Rechte vorbehalten.</div>
|
||||
<div class="text-zinc-500 opacity-80">© 2024 {{ .Site.Data.homepage.siteTitle | default .Site.Title }}. Alle Rechte vorbehalten.</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "miyakarate",
|
||||
"name": "EmyKarate",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
|
|
|
|||
Loading…
Reference in a new issue