Files
mc_cars_gmbh_infraestructure/frontend/admin.html
T
Lago 3fb0369367 Enhance SEO and performance for MC Cars website
- Added meta tags for SEO optimization across multiple pages including descriptions, robots directives, and Open Graph tags.
- Implemented JSON-LD structured data for better search visibility and rich snippets.
- Configured nginx for improved performance with gzip compression, caching strategies, and security headers.
- Created robots.txt and sitemap.xml for better search engine indexing and crawl management.
- Developed comprehensive SEO documentation including a guide and quick reference for ongoing optimization efforts.
2026-05-09 23:12:25 +02:00

310 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Admin · MC Cars</title>
<link rel="icon" type="image/png" href="/images/mc-cars-logo.png" />
<link rel="apple-touch-icon" href="/images/mc-cars-logo.png" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles.css" />
<script>document.write('<scr'+'ipt src="config.js?v='+Date.now()+'"><\/scr'+'ipt>')</script>
<meta name="robots" content="noindex, nofollow" />
<meta name="description" content="MC Cars Admin Panel - Not for public access" />
</head>
<body>
<!-- Login -->
<section id="loginView" class="admin-login" style="display:none;">
<div class="logo" style="justify-content:center;margin-bottom:1.5rem;">
<span class="logo-mark">MC</span>
<span>MC Cars Admin</span>
</div>
<form id="loginForm" class="admin-form">
<label>
<span>E-Mail</span>
<input type="email" name="email" required autocomplete="username" />
</label>
<label>
<span>Passwort</span>
<input type="password" name="password" required autocomplete="current-password" />
</label>
<button class="btn" type="submit">Anmelden</button>
<p class="form-feedback error" id="loginError"></p>
<p style="color:var(--muted);font-size:0.82rem;text-align:center;">
Nur für Administratoren. Selbstregistrierung ist deaktiviert.
</p>
</form>
</section>
<!-- Forced password rotation (first login OR user-triggered) -->
<section id="rotateView" class="admin-login" style="display:none;">
<div class="logo" style="justify-content:center;margin-bottom:1rem;">
<span class="logo-mark">MC</span>
<span>Passwort setzen</span>
</div>
<p style="color:var(--muted);font-size:0.9rem;text-align:center;max-width:38ch;margin:0 auto 1rem;">
Das Bootstrap-Passwort muss ersetzt werden. Das neue Passwort muss sich vom
Start-Passwort unterscheiden.
</p>
<form id="rotateForm" class="admin-form">
<label>
<span>Neues Passwort (mind. 10 Zeichen)</span>
<input type="password" name="pw1" minlength="10" required autocomplete="new-password" />
</label>
<label>
<span>Wiederholen</span>
<input type="password" name="pw2" minlength="10" required autocomplete="new-password" />
</label>
<button class="btn" type="submit">Speichern</button>
<p class="form-feedback error" id="rotateError"></p>
</form>
</section>
<!-- Admin -->
<section id="adminView" class="admin-page" style="display:none;">
<div class="admin-bar">
<h1>MC Cars · Admin</h1>
<div style="display:flex;gap:0.6rem;align-items:center;flex-wrap:wrap;">
<a id="websiteLink" href="/index.html" target="_blank" class="btn ghost small" data-i18n="adminNavWebsite">Website</a>
<button class="lang-toggle" type="button" aria-label="Sprache wechseln" style="margin-left:auto;">EN</button>
<span id="adminWho" style="color:var(--muted);font-size:0.85rem;margin-left:1rem;"></span>
<button id="changePwBtn" class="btn ghost small" data-i18n="adminChangePw">Passwort ändern</button>
<button id="logoutBtn" class="btn small" data-i18n="adminLogout">Logout</button>
</div>
</div>
<!-- Tabs -->
<div class="admin-tabs" role="tablist">
<button class="tab active" data-tab="leads" role="tab"><span data-i18n="adminLeads">Leads</span> <span id="leadsBadge" class="tab-badge">0</span></button>
<button class="tab" data-tab="customers" role="tab"><span data-i18n="adminCustomers">Kunden</span> <span id="customersBadge" class="tab-badge">0</span></button>
<button class="tab" data-tab="orders" role="tab"><span data-i18n="adminTabOrderHistory">Bestellungen</span> <span id="ordersBadge" class="tab-badge">0</span></button>
<button class="tab" data-tab="vehicles" role="tab" data-i18n="adminVehicles">Fahrzeuge</button>
<button class="tab" data-tab="settings" role="tab" data-i18n="adminSettings">Einstellungen</button>
</div>
<!-- LEADS -->
<div class="tab-panel" id="tab-leads">
<div class="panel">
<div style="display:flex;justify-content:space-between;align-items:center;gap:1rem;flex-wrap:wrap;margin-bottom:1rem;">
<h2 style="margin:0;">Leads</h2>
<div class="sub-tabs" role="tablist">
<button class="sub-tab active" data-lview="active" data-i18n="adminActiveLeads">Aktive Leads</button>
<button class="sub-tab" data-lview="inactive" data-i18n="adminClosedLeads">Abgeschlossen</button>
</div>
</div>
<table class="admin-table" id="leadsTable">
<thead>
<tr>
<th data-i18n="adminReceived">Eingang</th>
<th data-i18n="adminNameEmail">Name / E-Mail</th>
<th data-i18n="adminVehicleTab">Fahrzeug</th>
<th data-i18n="adminPeriod">Zeitraum</th>
<th data-i18n="adminTotalPrice">Gesamtbetrag</th>
<th data-i18n="adminStatus">Status</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
<p id="leadsEmpty" class="muted" style="display:none;text-align:center;padding:2rem 0;">Keine Leads in dieser Ansicht.</p>
</div>
</div>
<!-- CUSTOMERS -->
<div class="tab-panel" id="tab-customers" style="display:none;">
<div class="panel">
<h2>Kunden</h2>
<p class="muted" style="margin-top:-0.4rem;">Entstehen automatisch, sobald ein Lead qualifiziert wird. Die Quelle bleibt als <code>lead_id</code> verknüpft.</p>
<table class="admin-table" id="customersTable">
<thead>
<tr>
<th data-i18n="adminFirstContact">Erster Kontakt</th>
<th data-i18n="adminNameEmail">Name / E-Mail</th>
<th data-i18n="adminPhone">Telefon</th>
<th data-i18n="adminSourceLead">Quelle (Lead)</th>
<th data-i18n="adminLifetimeValueCol">Gesamtwert</th>
<th data-i18n="adminStatus">Status</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
<p id="customersEmpty" class="muted" style="display:none;text-align:center;padding:2rem 0;">Noch keine Kunden.</p>
</div>
</div>
<!-- SALES ORDERS -->
<div class="tab-panel" id="tab-orders" style="display:none;">
<div class="panel">
<h2 data-i18n="adminTabOrderHistory">Bestellungen</h2>
<table class="admin-table" id="ordersTable">
<thead>
<tr>
<th>Nr.</th>
<th data-i18n="adminNameEmail">Name / E-Mail</th>
<th data-i18n="adminVehicleTab">Fahrzeug</th>
<th data-i18n="adminPeriod">Zeitraum</th>
<th data-i18n="adminTotalPrice">Gesamtbetrag</th>
<th>Kaution</th>
<th>Miete</th>
<th data-i18n="adminStatus">Status</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
<p id="ordersEmpty" class="muted" style="display:none;text-align:center;padding:2rem 0;">Keine Bestellungen.</p>
</div>
</div>
<!-- VEHICLES -->
<div class="tab-panel" id="tab-vehicles" style="display:none;">
<div class="admin-grid">
<div class="panel">
<h2 id="formTitle" data-i18n="adminNewVehicle">Neues Fahrzeug</h2>
<form class="admin-form" id="vehicleForm">
<input type="hidden" name="vid" />
<div class="admin-photo-preview" id="photoPreview"></div>
<label>
<span data-i18n="adminPhotoUpload">Foto hochladen (JPG/PNG/WebP, max 50 MB)</span>
<input type="file" id="photoInput" accept="image/*" />
</label>
<input type="hidden" name="photo_url" />
<div class="row2">
<label><span data-i18n="adminBrand">Marke</span><input name="brand" required /></label>
<label><span data-i18n="adminModel">Modell</span><input name="model" required /></label>
</div>
<div class="row3">
<label><span data-i18n="adminPower">PS</span><input type="number" name="power_hp" min="0" /></label>
<label><span data-i18n="adminSpeed">Top-Speed km/h</span><input type="number" name="top_speed_kmh" min="0" /></label>
<label><span data-i18n="adminAccel">0-100</span><input name="acceleration" placeholder="3.2s" /></label>
</div>
<div class="row3">
<label><span data-i18n="adminSeats">Sitze</span><input type="number" name="seats" min="1" value="2" /></label>
<label><span data-i18n="adminPrice">Preis / Tag (€)</span><input type="number" name="daily_price_eur" min="0" required /></label>
<label><span>Wochenendpreis (€)</span><input type="number" name="weekend_price_eur" min="0" /></label>
</div>
<div class="row3">
<label><span>Max. km/Tag</span><input type="number" name="max_daily_km" min="0" value="150" /></label>
<label><span data-i18n="adminKaution">Kaution (€)</span><input type="number" name="kaution_eur" min="1" value="5000" required /></label>
<label><span data-i18n="adminMaxKmWeekend">Max. km/Wochenendtag</span><input type="number" name="max_km_weekend" min="0" placeholder="wie km/Tag" /></label>
</div>
<div class="row2">
<label><span data-i18n="adminSort">Reihenfolge</span><input type="number" name="sort_order" value="100" /></label>
<label><span data-i18n="adminLocation">Standort</span><input name="location" value="Steiermark (TBD)" /></label>
</div>
<label>
<span data-i18n="adminDescDe">Beschreibung (Deutsch)</span>
<textarea name="description_de" rows="3"></textarea>
</label>
<label>
<span data-i18n="adminDescEn">Description (English)</span>
<textarea name="description_en" rows="3"></textarea>
</label>
<label style="flex-direction:row;align-items:center;gap:0.8rem;margin-top:0.5rem;cursor:pointer;">
<div class="toggle-switch">
<input type="checkbox" name="is_active" id="isActiveCheck" checked />
<span class="toggle-slider"></span>
</div>
<span data-i18n="adminActiveVisible" style="user-select:none;">Aktiv / auf Website sichtbar</span>
</label>
<div style="display:flex;gap:0.5rem;margin-top:1rem;">
<button class="btn" type="submit" id="saveBtn" data-i18n="adminSave">Speichern</button>
<button class="btn ghost" type="button" id="resetBtn" data-i18n="adminReset">Neu</button>
</div>
<p class="form-feedback" id="formFeedback"></p>
</form>
</div>
<div class="panel">
<h2 data-i18n="adminAllVehicles">Alle Fahrzeuge</h2>
<table class="admin-table" id="adminTable">
<thead>
<tr>
<th data-i18n="adminPhoto">Foto</th>
<th data-i18n="adminBrandTable">Marke / Modell</th>
<th data-i18n="adminPriceTable">€ / Tag</th>
<th data-i18n="adminActive">Aktiv</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- SETTINGS -->
<div class="tab-panel" id="tab-settings" style="display:none;">
<div class="panel" style="max-width:600px;">
<h2 data-i18n="adminSettings">Einstellungen</h2>
<div class="admin-form">
<label>
<span data-i18n="adminHeroImage">Hauptbild (Hero-Bereich)</span>
<div class="admin-photo-preview" id="heroPreview" style="aspect-ratio:21/9;"></div>
<input type="file" id="heroImageInput" accept="image/jpeg,image/png,image/webp" />
</label>
<p class="muted" style="font-size:0.82rem;" data-i18n="adminHeroImageHint">JPG/PNG/WebP. Wird als Hintergrundbild im Hero-Bereich der Website angezeigt.</p>
<p class="form-feedback" id="heroFeedback"></p>
</div>
<hr style="margin:2rem 0;border-color:var(--border);" />
<div class="admin-form">
<label>
<span data-i18n="adminMietvertragTemplate">Mietvertrag-Vorlage (DOCX)</span>
<div id="mietvertragStatus" class="muted" style="font-size:0.9rem;margin:0.5rem 0;"></div>
<input type="file" id="mietvertragInput" accept="application/vnd.openxmlformats-officedocument.wordprocessingml.document,.docx" />
</label>
<p class="muted" style="font-size:0.82rem;" data-i18n="adminMietvertragHint">DOCX-Vorlage mit Platzhaltern. Wird bei Qualifizierung automatisch ausgefüllt und als PDF per E-Mail versendet.</p>
<p class="form-feedback" id="mietvertragFeedback"></p>
</div>
</div>
</div>
</section>
<!-- Order detail dialog -->
<dialog id="orderDialog">
<div class="dialog-head">
<h3 id="orderDialogTitle" style="margin:0;">Bestellung</h3>
<button class="dialog-close" id="orderDialogClose" aria-label="Close">×</button>
</div>
<div class="dialog-body" id="orderDialogBody"></div>
<div class="dialog-footer" id="orderDialogFooter"></div>
</dialog>
<!-- Lead detail / qualify dialog (tabbed) -->
<dialog id="leadDialog">
<div class="dialog-head">
<h3 id="leadDialogTitle" style="margin:0;">Lead</h3>
<button class="dialog-close" id="leadDialogClose" aria-label="Close">×</button>
</div>
<div class="dialog-tabs" id="leadDialogTabs" role="tablist"></div>
<div class="dialog-body" id="leadDialogBody"></div>
<div class="dialog-footer" id="leadDialogFooter"></div>
</dialog>
<!-- Customer detail dialog (tabbed) -->
<dialog id="customerDialog">
<div class="dialog-head">
<h3 id="customerDialogTitle" style="margin:0;">Kunde</h3>
<button class="dialog-close" id="customerDialogClose" aria-label="Close">×</button>
</div>
<div class="dialog-tabs" id="customerDialogTabs" role="tablist"></div>
<div class="dialog-body" id="customerDialogBody"></div>
<div class="dialog-footer" id="customerDialogFooter"></div>
</dialog>
<script type="module" src="admin.js"></script>
</body>
</html>