Files
KeySelector/public/index.html
T

165 lines
7.0 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" data-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>KeySelector — Harmonic DJ Assistant</title>
<link rel="icon" type="image/png" href="favicon.png">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<!-- Topbar -->
<div class="topbar">
<div class="topbar-left">
<div class="brand">KEYSELECTOR</div>
<div class="audio-source-wrapper">
<select id="audio-source-select" class="source-select" onchange="changeAudioSource(this.value)">
<option value="system">🖥️ PC / System-Audio (VLC, DJ, YouTube)</option>
<option value="mic">🎤 Mikrofon (Raum / Pult)</option>
<option value="device">🎙️ Spezifisches Eingabegerät...</option>
</select>
<select id="audio-device-select" class="source-select" style="display: none;" onchange="selectSpecificDevice(this.value)">
<option value="">Gerät wählen...</option>
</select>
</div>
</div>
<div class="topbar-right">
<!-- Live Audio Level Meter -->
<div class="audio-meter-container" title="Audio-Eingangspegel">
<div class="audio-meter-bar" id="audio-meter-fill"></div>
</div>
<div class="status" id="listening-status" onclick="toggleListening()" title="Klicken zum Pausieren / Fortsetzen">
<i class="fa-solid fa-microphone"></i>
<span id="listening-text">Bereit</span>
</div>
<button class="theme-toggle" id="theme-btn" onclick="toggleTheme()">Light</button>
</div>
</div>
<!-- Live Search Bar -->
<div class="search-box-container">
<div class="search-input-wrapper">
<i class="fa-solid fa-magnifying-glass search-icon"></i>
<input type="text" id="search-input" placeholder="Song oder Artist suchen (z. B. Daft Punk, Fisher, Avicii)..." autocomplete="off">
<button id="search-clear-btn" class="search-clear" onclick="clearSearch()" style="display:none">×</button>
</div>
<div id="search-results-dropdown" class="search-results-dropdown" style="display:none"></div>
</div>
<!-- Hero Card -->
<div class="hero" id="hero">
<div class="cover" id="cover" onclick="toggleCover()" title="Klicken zum Vergrößern">
<div class="cover-placeholder">
<span class="note">♪</span>
<span>No Cover</span>
</div>
</div>
<div class="info">
<div class="info-top">
<div class="track-title" id="track-title">Warte auf Audio...</div>
<div class="track-artist" id="track-artist">Starte PC-Audio oder Mikrofon oben rechts</div>
</div>
<div class="info-mid">
<div class="stats-row">
<div class="stat" onclick="openKeyBpmModal()" title="Klicken zum Korrigieren von Key & BPM">
<div class="stat-header">
<span class="stat-label">Key</span>
<i class="fa-solid fa-pen-to-square edit-btn"></i>
</div>
<div class="stat-value k" id="stat-key">-</div>
<div class="stat-sub" id="stat-key-sub">-</div>
</div>
<div class="stat" onclick="openKeyBpmModal()" title="Klicken zum Korrigieren von Key & BPM">
<div class="stat-header">
<span class="stat-label">BPM</span>
<i class="fa-solid fa-pen-to-square edit-btn"></i>
</div>
<div class="stat-value b" id="stat-bpm">-</div>
<div class="stat-sub" id="stat-bpm-sub">± 0</div>
</div>
<div class="stat">
<div class="stat-header">
<span class="stat-label">Status</span>
</div>
<div class="stat-value m" id="stat-match">-</div>
<div class="stat-sub" id="stat-source-sub">Lokal / DB</div>
</div>
</div>
<div class="tags-row" id="tags-row"></div>
</div>
<div class="info-bot">
<div class="wheel-container" id="wheel-container" onclick="toggleWheel()" title="Klicken für Vollansicht des Camelot Wheels">
<svg viewBox="-110 -110 220 220" id="wheel-small" preserveAspectRatio="xMidYMid meet"></svg>
</div>
</div>
</div>
<button class="close-btn" id="close-btn" onclick="resetHero()" title="Schließen">×</button>
</div>
<!-- Suggestions Grid -->
<div class="section-title">Harmonisch passende Folge-Tracks (Up Next)</div>
<div class="suggestions" id="suggestions">
<div style="color:var(--text-dim);font-size:12px;font-family:'JetBrains Mono',monospace;">Wähle oder spiele einen Track ab, um harmonische Übergänge zu berechnen.</div>
</div>
<div style="text-align: center; margin-top: 40px; font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--text-dim);">
KeySelector — Local-First PostgreSQL DJ Suite
<br>
<span style="opacity: 0.5;">v2.0.0</span>
</div>
</div>
<!-- Key & BPM Correction Modal -->
<div id="edit-modal" class="modal-overlay" style="display:none;" onclick="closeModalOnOverlay(event)">
<div class="modal-card">
<div class="modal-header">
<h3 id="modal-track-title">Track-Daten korrigieren</h3>
<button class="modal-close" onclick="closeKeyBpmModal()">×</button>
</div>
<div class="modal-body">
<p class="modal-desc">Werte werden dauerhaft in deiner lokalen PostgreSQL-Datenbank gespeichert und haben bei künftigen Suchen/Erkennungen Vorrang.</p>
<div class="form-group">
<label for="edit-key-select">Camelot Key:</label>
<select id="edit-key-select" class="form-input"></select>
</div>
<div class="form-group">
<label for="edit-bpm-input">BPM:</label>
<input type="number" id="edit-bpm-input" class="form-input" min="60" max="220" step="1">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeKeyBpmModal()">Abbrechen</button>
<button class="btn btn-primary" onclick="saveKeyBpmCorrection()">In PostgreSQL speichern</button>
</div>
</div>
</div>
<script src="../shared/mixing-rules.js"></script>
<script src="../shared/color-matrix.js"></script>
<script src="../shared/camelot-angle.js"></script>
<script src="../shared/camelot-to-musickey.js"></script>
<script src="wheel.js"></script>
<script src="cover.js"></script>
<script src="search.js"></script>
<script src="app.js"></script>
</body>
</html>