filoor fb8a35490a feat(adzkaar): voeg fullscreen Adzkaar-functionaliteit toe
Deze commit implementeert een nieuw Adzkaar-scherm dat automatisch verschijnt na de gebedstijden. Belangrijke wijzigingen omvatten:

- Toevoeging van instellingen voor het inschakelen en aanpassen van de duur van het Adzkaar-scherm in `settings.json` en de bijbehorende HTML.
- Implementatie van nieuwe routes `/adzkaar` en `/api/trigger-adzkaar` om respectievelijk het scherm weer te geven en te debuggen.
- Update van de countdown-logica om het Adzkaar-scherm drie seconden na het adhan af te spelen.
- Nieuwe frontend-elementen voor een interactieve, kaart-voor-kaart weergave van de Adzkaar met ondersteuning voor navigatie en toetsenbordbediening.
- Aanpassing van bestaande templates om integratie van de nieuwe functionaliteiten te faciliteren.

Deze toevoegingen verbeteren de gebruikerservaring door meer spirituele betrokkenheid mogelijk te maken na de gebedstijden.
2025-05-28 03:57:40 +02:00

539 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<title>Debug - Gebedstijden Tester</title>
<link rel="stylesheet" href="/static/style.css">
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
body {
margin: 0;
padding: 0;
min-height: 100vh;
overflow-x: hidden;
overflow-y: auto;
}
.debug-container {
max-width: 1200px;
margin: 2rem auto;
padding: 2rem;
background: var(--panel-bg);
border-radius: 15px;
border: 1px solid var(--panel-border);
color: var(--text-color);
min-height: calc(100vh - 4rem);
}
.debug-header {
text-align: center;
margin-bottom: 2rem;
}
.debug-header h1 {
color: var(--accent);
font-family: 'Cairo', sans-serif;
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.debug-header p {
color: var(--text-secondary);
font-size: 1.1rem;
}
.debug-grid {
display: flex;
flex-direction: column;
gap: 2rem;
margin-bottom: 2rem;
}
.debug-panel {
background: var(--card-bg);
padding: 1.5rem;
border-radius: 10px;
border: 1px solid var(--border-color);
color: var(--text-color);
}
.debug-panel h3 {
color: var(--accent);
margin-bottom: 1rem;
font-family: 'Cairo', sans-serif;
font-size: 1.3rem;
}
.time-controls {
display: flex;
flex-direction: column;
gap: 1rem;
}
.time-input {
display: flex;
align-items: center;
gap: 1rem;
}
.time-input label {
color: var(--text-color);
font-weight: 600;
}
.time-input input {
padding: 0.5rem;
border: 1px solid var(--border-color);
border-radius: 5px;
background: var(--input-bg);
color: var(--text-color);
font-size: 1.1rem;
width: 120px;
}
.btn {
padding: 0.7rem 1.5rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
margin: 0.2rem;
font-size: 0.9rem;
}
.btn-primary {
background: var(--accent);
color: var(--bg-color);
}
.btn-secondary {
background: var(--text-secondary);
color: var(--bg-color);
}
.btn-danger {
background: #dc3545;
color: white;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
opacity: 0.9;
}
.prayer-times-list {
list-style: none;
padding: 0;
margin: 0;
}
.prayer-times-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.7rem;
margin-bottom: 0.5rem;
background: var(--input-bg);
border-radius: 5px;
border: 1px solid var(--border-color);
color: var(--text-color);
}
.prayer-times-list li.active {
background: rgba(234, 179, 8, 0.2);
border-color: var(--accent);
}
.status-display {
background: var(--input-bg);
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
color: var(--text-color);
border: 1px solid var(--border-color);
}
.quick-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 1rem;
}
.back-link {
display: inline-block;
margin-bottom: 1rem;
color: var(--accent);
text-decoration: none;
font-weight: 600;
}
.back-link:hover {
color: var(--text-color);
}
@media (max-width: 768px) {
.debug-container {
margin: 1rem;
padding: 1rem;
}
.btn {
font-size: 0.8rem;
padding: 0.5rem 1rem;
}
}
</style>
</head>
<body>
<div class="debug-container">
<a href="/" class="back-link">← Terug naar hoofdpagina</a>
<div class="debug-header">
<h1>🔧 Debug Mode</h1>
<p>Test de adhaan functionaliteit door de tijd aan te passen</p>
</div>
<div class="debug-grid">
<div class="debug-panel">
<h3>⏰ Tijd Controles</h3>
<div class="status-display" id="statusDisplay">
Huidige tijd: <span id="currentDebugTime">--:--</span><br>
Volgende gebed: <span id="nextPrayerDebug">--</span><br>
Status: <span id="debugStatus">Normaal</span>
</div>
<div class="time-controls">
<div class="time-input">
<label>Stel tijd in:</label>
<input type="time" id="manualTime" />
<button class="btn btn-primary" onclick="setManualTime()">Zet Tijd</button>
</div>
<div class="quick-actions">
<button class="btn btn-secondary" onclick="adjustTime(-60)">-1 min</button>
<button class="btn btn-secondary" onclick="adjustTime(-10)">-10 sec</button>
<button class="btn btn-secondary" onclick="adjustTime(10)">+10 sec</button>
<button class="btn btn-secondary" onclick="adjustTime(60)">+1 min</button>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="setTimeToNextPrayer(-1)">1 min voor gebed</button>
<button class="btn btn-primary" onclick="setTimeToNextPrayer(0)">Exact gebedstijd</button>
<button class="btn btn-danger" onclick="resetTime()">Reset naar echte tijd</button>
</div>
</div>
</div>
<div class="debug-panel">
<h3>🕌 Gebedstijden Vandaag</h3>
<ul class="prayer-times-list" id="prayerTimesList">
{% for naam, tijd in gebedstijden.items() %}
<li data-prayer="{{ naam }}" data-time="{{ tijd[:5] }}">
<span>{{ naam }}</span>
<span>{{ tijd[:5] }}</span>
<button class="btn btn-secondary" onclick="setTimeToPrayer('{{ tijd[:5] }}', -1)">-1 min</button>
<button class="btn btn-primary" onclick="setTimeToPrayer('{{ tijd[:5] }}', 0)">Nu</button>
</li>
{% endfor %}
</ul>
</div>
</div>
<div class="debug-panel">
<h3>📊 Debug Log</h3>
<div class="status-display" id="debugLog" style="height: 200px; overflow-y: auto;">
Debug log wordt hier weergegeven...<br>
</div>
<button class="btn btn-secondary" onclick="clearLog()">Wis Log</button>
</div>
<div class="debug-panel">
<h3>🔊 Sonos Status</h3>
<div class="status-display" id="sonosStatus" style="height: 150px; overflow-y: auto;">
Sonos status wordt geladen...<br>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="checkSonosStatus()">🔄 Ververs Status</button>
<button class="btn btn-danger" onclick="stopAllSonos()">⏹️ Stop Alle Audio</button>
</div>
</div>
<div class="debug-panel">
<h3>📿 Adzkaar Testing</h3>
<div class="status-display" id="adzkaarStatus" style="height: 100px; overflow-y: auto;">
Status: {% if settings.adzkaar_enabled %}Ingeschakeld{% else %}Uitgeschakeld{% endif %}<br>
Duur: {{ settings.adzkaar_duration or 5 }} minuten<br>
</div>
<div class="quick-actions">
<button class="btn btn-primary" onclick="testAdzkaar()">📿 Test Adzkaar Scherm</button>
<button class="btn btn-secondary" onclick="openAdzkaarDirect()">🔗 Open Adzkaar Direct</button>
</div>
</div>
</div>
<script>
let debugTimeOffset = 0; // Offset in seconden
let isDebugMode = false;
function log(message) {
const logElement = document.getElementById('debugLog');
const timestamp = new Date().toLocaleTimeString();
logElement.innerHTML += `[${timestamp}] ${message}<br>`;
logElement.scrollTop = logElement.scrollHeight;
}
function clearLog() {
document.getElementById('debugLog').innerHTML = 'Debug log gewist...<br>';
}
function getDebugTime() {
const now = new Date();
if (isDebugMode) {
now.setTime(now.getTime() + (debugTimeOffset * 1000));
}
return now;
}
function updateDebugDisplay() {
const debugTime = getDebugTime();
const timeStr = debugTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById('currentDebugTime').textContent = timeStr;
// Update status
const statusElement = document.getElementById('debugStatus');
statusElement.textContent = isDebugMode ? 'Debug Mode Actief' : 'Normaal';
statusElement.style.color = isDebugMode ? '#ff6b6b' : '#00ff00';
// Check voor gebedstijd
checkPrayerTime(timeStr);
}
function checkPrayerTime(currentTime) {
const prayerTimes = {{ gebedstijden | tojson }};
let nextPrayer = null;
let isExactTime = false;
for (const [name, time] of Object.entries(prayerTimes)) {
const prayerTime = time.substring(0, 5);
if (prayerTime === currentTime) {
isExactTime = true;
log(`🕌 ADHAAN TIJD! ${name} (${prayerTime})`);
// Trigger adhaan
triggerAdhaan(name);
}
if (prayerTime > currentTime && !nextPrayer) {
nextPrayer = `${name} (${prayerTime})`;
}
}
if (!nextPrayer) {
// Volgende dag
const firstPrayer = Object.entries(prayerTimes)[0];
nextPrayer = `${firstPrayer[0]} (${firstPrayer[1].substring(0, 5)}) - morgen`;
}
document.getElementById('nextPrayerDebug').textContent = nextPrayer;
// Update active prayer in list
document.querySelectorAll('.prayer-times-list li').forEach(li => {
li.classList.remove('active');
if (li.dataset.time === currentTime) {
li.classList.add('active');
}
});
}
function triggerAdhaan(prayerName) {
// Speel adhaan af
const audio = document.getElementById('adhanAudio');
if (audio) {
audio.play().catch(e => log(`Fout bij afspelen audio: ${e.message}`));
}
// Verstuur naar Sonos (als niet gemute)
fetch('/api/debug-adhaan', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prayer: prayerName, time: getDebugTime().toLocaleTimeString() })
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`✅ Adhaan verzonden naar Sonos voor ${prayerName}`);
} else {
log(`❌ Fout bij Sonos: ${data.error}`);
}
})
.catch(e => log(`❌ Netwerk fout: ${e.message}`));
}
function setManualTime() {
const timeInput = document.getElementById('manualTime');
if (!timeInput.value) return;
const [hours, minutes] = timeInput.value.split(':');
const now = new Date();
const targetTime = new Date();
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
debugTimeOffset = Math.floor((targetTime - now) / 1000);
isDebugMode = true;
log(`⏰ Tijd handmatig ingesteld op ${timeInput.value}`);
updateDebugDisplay();
}
function adjustTime(seconds) {
debugTimeOffset += seconds;
isDebugMode = true;
const sign = seconds > 0 ? '+' : '';
log(`⏰ Tijd aangepast: ${sign}${seconds} seconden`);
updateDebugDisplay();
}
function setTimeToPrayer(prayerTime, offsetMinutes) {
const [hours, minutes] = prayerTime.split(':');
const now = new Date();
const targetTime = new Date();
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
targetTime.setTime(targetTime.getTime() + (offsetMinutes * 60 * 1000));
debugTimeOffset = Math.floor((targetTime - now) / 1000);
isDebugMode = true;
const offsetText = offsetMinutes === 0 ? 'exact' : `${offsetMinutes} min ervoor`;
log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`);
updateDebugDisplay();
}
function setTimeToNextPrayer(offsetMinutes) {
const prayerTimes = {{ gebedstijden | tojson }};
const currentTime = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
for (const [name, time] of Object.entries(prayerTimes)) {
const prayerTime = time.substring(0, 5);
if (prayerTime > currentTime) {
setTimeToPrayer(prayerTime, offsetMinutes);
return;
}
}
// Als geen gebed meer vandaag, neem eerste van morgen
const firstPrayer = Object.entries(prayerTimes)[0];
setTimeToPrayer(firstPrayer[1].substring(0, 5), offsetMinutes);
}
function resetTime() {
debugTimeOffset = 0;
isDebugMode = false;
log(`🔄 Tijd gereset naar echte tijd`);
updateDebugDisplay();
}
function checkSonosStatus() {
log('🔄 Sonos status controleren...');
fetch('/api/sonos-status')
.then(response => response.json())
.then(data => {
const statusElement = document.getElementById('sonosStatus');
if (data.success) {
let statusHtml = `Sonos API: ${data.api_ip}<br><br>`;
for (const [zone, info] of Object.entries(data.zones)) {
const statusColor = info.status === 'online' ? '#00ff00' : '#ff6b6b';
statusHtml += `<span style="color: ${statusColor}">● ${zone}</span><br>`;
statusHtml += ` Status: ${info.status}<br>`;
if (info.status === 'online') {
statusHtml += ` Afspelen: ${info.playbackState}<br>`;
statusHtml += ` Track: ${info.currentTrack}<br>`;
statusHtml += ` Volume: ${info.volume}%<br>`;
} else if (info.error) {
statusHtml += ` Fout: ${info.error}<br>`;
}
statusHtml += '<br>';
}
statusElement.innerHTML = statusHtml;
log('✅ Sonos status bijgewerkt');
} else {
statusElement.innerHTML = `❌ Fout: ${data.error}`;
log(`❌ Sonos status fout: ${data.error}`);
}
})
.catch(error => {
log(`❌ Netwerk fout bij Sonos status: ${error.message}`);
document.getElementById('sonosStatus').innerHTML = `❌ Netwerk fout: ${error.message}`;
});
}
function stopAllSonos() {
log('⏹️ Alle Sonos audio stoppen...');
fetch('/api/sonos-stop', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`${data.message}`);
// Ververs status na stoppen
setTimeout(checkSonosStatus, 1000);
} else {
log(`❌ Fout bij stoppen: ${data.error}`);
}
})
.catch(error => {
log(`❌ Netwerk fout bij stoppen: ${error.message}`);
});
}
function testAdzkaar() {
log('📿 Adzkaar scherm testen...');
fetch('/api/trigger-adzkaar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
if (data.success) {
log(`${data.message}`);
// Open Adzkaar scherm in nieuw venster/tab
window.open(data.url, '_blank', 'fullscreen=yes,scrollbars=no,resizable=no');
} else {
log(`❌ Adzkaar fout: ${data.error}`);
document.getElementById('adzkaarStatus').innerHTML += `❌ Fout: ${data.error}<br>`;
}
})
.catch(error => {
log(`❌ Netwerk fout bij Adzkaar test: ${error.message}`);
});
}
function openAdzkaarDirect() {
log('🔗 Adzkaar scherm direct openen...');
window.open('/adzkaar', '_blank', 'fullscreen=yes,scrollbars=no,resizable=no');
}
// Update elke seconde
setInterval(updateDebugDisplay, 1000);
// Initiële updates
updateDebugDisplay();
checkSonosStatus();
log('🔧 Debug mode gestart');
</script>
<!-- Hidden audio element for testing -->
<audio id="adhanAudio" src="/static/clips/{{ settings['audio_clip'] }}" preload="auto"></audio>
</body>
</html>