225 lines
12 KiB
HTML
225 lines
12 KiB
HTML
<!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 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>
|
||
</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;">
|
||
Only admins. Self-registration is disabled.
|
||
</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 href="index.html" 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 aendern</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="vehicles" role="tab" data-i18n="adminVehicles">Fahrzeuge</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="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> verknuepft.</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="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>
|
||
|
||
<!-- 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>
|
||
<label>
|
||
<span data-i18n="adminPhotoUrl">Foto-URL (wird automatisch gesetzt nach Upload)</span>
|
||
<input type="url" name="photo_url" placeholder="https://..." />
|
||
</label>
|
||
|
||
<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 data-i18n="adminSort">Reihenfolge</span><input type="number" name="sort_order" value="100" /></label>
|
||
</div>
|
||
|
||
<label>
|
||
<span data-i18n="adminLocation">Standort</span>
|
||
<input name="location" value="Steiermark (TBD)" />
|
||
</label>
|
||
|
||
<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>
|
||
</section>
|
||
|
||
<!-- Lead detail / qualify dialog -->
|
||
<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-body" id="leadDialogBody"></div>
|
||
</dialog>
|
||
|
||
<script type="module" src="admin.js"></script>
|
||
</body>
|
||
</html>
|