filoor d378511401 refactor(ui): optimaliseer adzkaar.html en index.html voor betere performance
Deze commit verbetert de laadtijden en responsiviteit van de Adhaan-webapp door verschillende optimalisaties. Er is een verbetering in de structuur van HTML en JavaScript. De expliciete onclick-attributen zijn vervangen door event listeners, caching van DOM-elementen is geïntroduceerd, en er zijn debouncing-technieken toegevoegd voor efficiëntere updates van weer- en hadithgegevens. Verder is er sprake van een herschikking van de countdown-timer en andere UI-elementen om logischer te werken, zoals het verbergen van de inhoud om FOUC te voorkomen totdat alles geladen is. Deze wijzigingen samen dragen bij aan een soepeler gebruikerservaring.
2025-05-29 21:34:10 +02:00

404 lines
15 KiB
HTML

<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<title>Gebedstijden Display</title>
<link rel="stylesheet" href="/static/style.css">
<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=Cairo:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script>
// Voorkom FOUC (Flash of Unstyled Content)
document.documentElement.style.visibility = 'hidden';
window.addEventListener('load', function() {
document.documentElement.style.visibility = 'visible';
});
</script>
</head>
<body>
<div class="app">
<!-- Dark/Light toggle -->
<button id="themeToggle" title="Schakel modus"><span id="themeIcon" class="material-icons">brightness_6</span></button>
<div class="left">
<div class="overlay">
<div class="tijdstip">
<div class="tijd-weer-row">
<div class="tijd-column">
<div id="current-time">--:--</div>
</div>
<div class="weer-column">
<!-- Weer sectie naast de tijd -->
<div class="weather-section-left">
<div class="weather-info">
<div class="weather-main">
<span class="weather-temp">{{ weather.temperature }}°C</span>
<span class="weather-desc">{{ weather.description }}</span>
</div>
<div class="weather-details">
<span class="weather-detail">Voelt als {{ weather.feels_like }}°C</span>
<span class="weather-detail">Vochtigheid {{ weather.humidity }}%</span>
<span class="weather-detail">Wind {{ weather.wind_speed }} km/h</span>
</div>
</div>
</div>
</div>
</div>
<div class="datum-sectie">
<div class="gregorian-datum">{{ date_info.gregorian_full }}</div>
<div class="hijri-datum-arabic">{{ date_info.hijri_arabic }}</div>
<div class="hijri-datum-dutch">{{ date_info.hijri_dutch }}</div>
</div>
</div>
</div>
<!-- Huidig gebed sectie onderaan -->
<div class="huidig-gebed-bottom">
<div class="naam">{{ next_name }}</div>
<div id="countdown">--:--:--</div>
</div>
</div>
<!-- Zijmenu met hadith sectie -->
<div class="right new-layout">
<div class="hadith-tijden-row">
<!-- Hadith sectie met witte achtergrond -->
<div class="hadith-center">
<blockquote>
"{{ hadith.text }}"
<footer>— {{ hadith.bron }}</footer>
</blockquote>
</div>
<!-- Compact zijmenu -->
<div class="vertical-tijden">
<ul class="tijden-en-icoontjes">
{% for naam, tijd in gebedstijden.items() %}
<li class="tijden-rij">
<span class="naam">{{ naam }}</span>
<span class="tijd">{{ tijd[:5] }}</span>
</li>
{% endfor %}
<li><a href="/instellingen" title="Instellingen" class="icoon-link"><span class="material-icons">settings</span></a></li>
<li><a href="#" id="muteBtn" title="Mute" class="icoon-link"><span id="muteIcon" class="material-icons">volume_off</span></a></li>
{% if settings.debug_mode %}
<li><a href="/debug" title="Debug Mode" class="icoon-link"><span class="material-icons">bug_report</span></a></li>
{% endif %}
<li><a href="/quran" title="Quran Speler" class="icoon-link"><span class="material-icons">menu_book</span></a></li>
</ul>
</div>
</div>
</div>
</div>
<audio id="adhanAudio" src="/static/clips/{{ settings['audio_clip'] }}" preload="auto"></audio>
<!-- Adzkaar Modal -->
<div id="adzkaarModal" class="adzkaar-modal" style="display: none;">
<div class="adzkaar-container">
<button class="close-button" onclick="closeAdzkaar()" title="Sluiten">
<span class="material-icons">close</span>
</button>
<div class="countdown-timer" id="countdownTimer">
5:00
</div>
<div class="adzkaar-header">
<h1 class="adzkaar-title">أذكار بعد الصلاة</h1>
<p class="adzkaar-subtitle">Adzkaar na het Gebed</p>
</div>
<div class="adzkaar-content">
<div class="dhikr-navigation">
<button class="nav-btn" id="prevBtn" onclick="previousDhikr()" disabled>
<span class="material-icons">arrow_back</span>
</button>
<div class="dhikr-counter">
<span id="currentDhikr">1</span> / <span id="totalDhikr">6</span>
</div>
<button class="nav-btn" id="nextBtn" onclick="nextDhikr()">
<span class="material-icons">arrow_forward</span>
</button>
</div>
<div class="dhikr-container" id="dhikrContainer">
<div class="dhikr-item active" data-index="0">
<div class="dhikr-arabic">أَسْتَغْفِرُ اللَّهَ</div>
<div class="dhikr-transliteration">Astaghfirullah</div>
<div class="dhikr-translation">Ik vraag Allah om vergeving</div>
<div class="dhikr-count">3x</div>
</div>
<div class="dhikr-item" data-index="1">
<div class="dhikr-arabic">اللَّهُمَّ أَنْتَ السَّلاَمُ وَمِنْكَ السَّلاَمُ تَبَارَكْتَ يَا ذَا الْجَلاَلِ وَالإِكْرَامِ</div>
<div class="dhikr-transliteration">Allahumma anta as-salamu wa minka as-salamu, tabarakta ya dhal-jalali wal-ikram</div>
<div class="dhikr-translation">O Allah, U bent de Vrede en van U komt de vrede. Gezegend bent U, O Bezitter van Majesteit en Eer</div>
<div class="dhikr-count">1x</div>
</div>
<div class="dhikr-item" data-index="2">
<div class="dhikr-arabic">سُبْحَانَ اللَّهِ</div>
<div class="dhikr-transliteration">Subhan Allah</div>
<div class="dhikr-translation">Glorie zij Allah</div>
<div class="dhikr-count">33x</div>
</div>
<div class="dhikr-item" data-index="3">
<div class="dhikr-arabic">الْحَمْدُ لِلَّهِ</div>
<div class="dhikr-transliteration">Alhamdulillah</div>
<div class="dhikr-translation">Alle lof zij Allah</div>
<div class="dhikr-count">33x</div>
</div>
<div class="dhikr-item" data-index="4">
<div class="dhikr-arabic">اللَّهُ أَكْبَرُ</div>
<div class="dhikr-transliteration">Allahu Akbar</div>
<div class="dhikr-translation">Allah is de Grootste</div>
<div class="dhikr-count">34x</div>
</div>
<div class="dhikr-item" data-index="5">
<div class="dhikr-arabic">لاَ إِلَهَ إِلاَّ اللَّهُ وَحْدَهُ لاَ شَرِيكَ لَهُ لَهُ الْمُلْكُ وَلَهُ الْحَمْدُ وَهُوَ عَلَى كُلِّ شَيْءٍ قَدِيرٌ</div>
<div class="dhikr-transliteration">La ilaha illa Allah wahdahu la sharika lah, lahu al-mulku wa lahu al-hamdu wa huwa 'ala kulli shay'in qadir</div>
<div class="dhikr-translation">Er is geen god behalve Allah alleen, Hij heeft geen partner. Aan Hem behoort de heerschappij en aan Hem behoort alle lof, en Hij heeft macht over alle dingen</div>
<div class="dhikr-count">1x</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Cache DOM elementen
const currentTimeEl = document.getElementById('current-time');
const countdownEl = document.getElementById('countdown');
const muteBtn = document.getElementById('muteBtn');
const muteIcon = document.getElementById('muteIcon');
const adhanAudio = document.getElementById('adhanAudio');
const adzkaarModal = document.getElementById('adzkaarModal');
// Prayer times data from server
window.prayerTimes = [
{% for naam, tijd in gebedstijden.items() %}
"{{ tijd[:5] }}"{% if not loop.last %},{% endif %}
{% endfor %}
];
window.prayerNames = [
{% for naam, tijd in gebedstijden.items() %}
"{{ naam }}"{% if not loop.last %},{% endif %}
{% endfor %}
];
const nextPrayerTime = "{{ next_time }}";
const hadithInterval = {{ settings.hadith_interval_seconds or 30 }} * 1000;
// Debounce functie voor betere performance
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Optimize weather updates
const updateWeather = debounce(async function() {
try {
const response = await fetch('/api/weather');
const data = await response.json();
updateWeatherUI(data);
} catch (error) {
console.error('Fout bij ophalen weerdata:', error);
}
}, 1000);
// Optimize hadith updates
const updateHadith = debounce(async function() {
try {
const response = await fetch('/api/hadith');
const data = await response.json();
updateHadithUI(data);
} catch (error) {
console.error('Fout bij ophalen hadith:', error);
}
}, 1000);
// Initialize on load
window.addEventListener('load', function() {
updateCurrentTime();
setInterval(updateCurrentTime, 60000);
setupThemeToggle();
startCountdowns(window.prayerTimes, window.prayerNames);
// Update weerdata elke 10 minuten
updateWeather();
setInterval(updateWeather, 600000);
// Update hadith elke X seconden
updateHadith();
setInterval(updateHadith, hadithInterval);
// Setup event listeners
setupEventListeners();
});
// Setup event listeners
function setupEventListeners() {
if (muteBtn) {
muteBtn.addEventListener('click', toggleMute);
}
}
// Toggle mute state
function toggleMute() {
const isMuted = adhanAudio.muted;
adhanAudio.muted = !isMuted;
muteIcon.textContent = isMuted ? 'volume_off' : 'volume_up';
// Update mute state in settings
fetch('/api/mute', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mute: !isMuted })
}).catch(error => console.error('Fout bij updaten mute state:', error));
}
// Theme toggle icon dynamisch aanpassen
function updateThemeIcon() {
const html = document.documentElement;
const icon = document.getElementById('themeIcon');
if (html.className === 'light') {
icon.textContent = 'dark_mode';
} else {
icon.textContent = 'light_mode';
}
}
updateThemeIcon();
document.getElementById('themeToggle').addEventListener('click', updateThemeIcon);
// Adzkaar Modal Functionaliteit
let countdownSeconds = 5 * 60; // 5 minuten standaard
let countdownInterval;
let currentDhikrIndex = 0;
const totalDhikrs = 6;
let autoSwitchInterval;
function showAdzkaarModal(durationMinutes = 5) {
countdownSeconds = durationMinutes * 60;
currentDhikrIndex = 0;
// Toon modal
document.getElementById('adzkaarModal').style.display = 'flex';
// Reset dhikr display
showDhikr(0);
// Start countdown
countdownInterval = setInterval(updateAdzkaarCountdown, 1000);
updateAdzkaarCountdown();
// Start automatische wissel elke 30 seconden
autoSwitchInterval = setInterval(autoSwitchDhikr, 30000);
// Auto-close na ingestelde tijd
setTimeout(closeAdzkaar, countdownSeconds * 1000);
}
function updateAdzkaarCountdown() {
const minutes = Math.floor(countdownSeconds / 60);
const seconds = countdownSeconds % 60;
const display = `${minutes}:${seconds.toString().padStart(2, '0')}`;
document.getElementById('countdownTimer').textContent = display;
if (countdownSeconds <= 0) {
closeAdzkaar();
return;
}
countdownSeconds--;
}
function closeAdzkaar() {
clearInterval(countdownInterval);
clearInterval(autoSwitchInterval);
document.getElementById('adzkaarModal').style.display = 'none';
}
function showDhikr(index) {
// Verberg alle dhikr items
document.querySelectorAll('.dhikr-item').forEach(item => {
item.classList.remove('active');
});
// Toon de geselecteerde dhikr
const targetDhikr = document.querySelector(`[data-index="${index}"]`);
if (targetDhikr) {
targetDhikr.classList.add('active');
}
// Update counter
document.getElementById('currentDhikr').textContent = index + 1;
// Update navigation buttons
document.getElementById('prevBtn').disabled = index === 0;
document.getElementById('nextBtn').disabled = index === totalDhikrs - 1;
}
function nextDhikr() {
if (currentDhikrIndex < totalDhikrs - 1) {
currentDhikrIndex++;
showDhikr(currentDhikrIndex);
}
}
function previousDhikr() {
if (currentDhikrIndex > 0) {
currentDhikrIndex--;
showDhikr(currentDhikrIndex);
}
}
function autoSwitchDhikr() {
if (currentDhikrIndex < totalDhikrs - 1) {
currentDhikrIndex++;
showDhikr(currentDhikrIndex);
} else {
// Als we bij de laatste dhikr zijn, begin opnieuw
currentDhikrIndex = 0;
showDhikr(currentDhikrIndex);
}
}
// Keyboard navigation voor modal
document.addEventListener('keydown', function(event) {
const modal = document.getElementById('adzkaarModal');
if (modal.style.display === 'flex') {
if (event.key === 'ArrowRight' || event.key === ' ') {
event.preventDefault();
nextDhikr();
} else if (event.key === 'ArrowLeft') {
event.preventDefault();
previousDhikr();
} else if (event.key === 'Escape') {
closeAdzkaar();
}
}
});
// Maak functies globaal beschikbaar
window.showAdzkaarModal = showAdzkaarModal;
window.closeAdzkaar = closeAdzkaar;
window.nextDhikr = nextDhikr;
window.previousDhikr = previousDhikr;
</script>
<script src="/static/countdown.js"></script>
</body>
</html>