147 lines
4.7 KiB
JavaScript
147 lines
4.7 KiB
JavaScript
/**
|
|
* Script de compte à rebours pour la page de maintenance
|
|
*/
|
|
|
|
/**
|
|
* Convertit une date ISO 8601 en timestamp, compatible Safari.
|
|
*
|
|
* Safari renvoie Invalid Date pour les formats non strictement ISO
|
|
* (ex. « 2025-10-11 00:00:00 » émis historiquement par PHP) : la chaîne
|
|
* est donc analysée manuellement. Sans fuseau explicite, la date est
|
|
* interprétée en UTC — PHP émet de toute façon toujours un décalage.
|
|
*
|
|
* @param {string|number} value Date ISO 8601 (ou timestamp déjà numérique)
|
|
* @returns {number} Timestamp en millisecondes
|
|
*/
|
|
function parseTargetDate(value) {
|
|
if (typeof value === 'number') {
|
|
return new Date(value).getTime();
|
|
}
|
|
|
|
const match = String(value).match(
|
|
/^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/
|
|
);
|
|
|
|
if (!match) {
|
|
// Repli sur l'analyse native pour les formats inattendus
|
|
return new Date(value).getTime();
|
|
}
|
|
|
|
const [, year, month, day, hours = '0', minutes = '0', seconds = '0', offset] = match;
|
|
|
|
let timestamp = Date.UTC(
|
|
parseInt(year, 10),
|
|
parseInt(month, 10) - 1,
|
|
parseInt(day, 10),
|
|
parseInt(hours, 10),
|
|
parseInt(minutes, 10),
|
|
parseInt(seconds, 10)
|
|
);
|
|
|
|
if (offset && offset !== 'Z') {
|
|
// Un décalage « +02:00 » signifie « 2 h d'avance sur UTC » : on le soustrait
|
|
const sign = offset[0] === '+' ? 1 : -1;
|
|
const offsetDigits = offset.slice(1).replace(':', '');
|
|
const offsetMinutes = sign * (
|
|
parseInt(offsetDigits.slice(0, 2), 10) * 60 + parseInt(offsetDigits.slice(2, 4), 10)
|
|
);
|
|
timestamp -= offsetMinutes * 60 * 1000;
|
|
}
|
|
|
|
return timestamp;
|
|
}
|
|
|
|
class CountdownTimer {
|
|
constructor(targetDate) {
|
|
this.targetDate = parseTargetDate(targetDate);
|
|
this.elements = {
|
|
days: document.getElementById('countdown-days'),
|
|
hours: document.getElementById('countdown-hours'),
|
|
minutes: document.getElementById('countdown-minutes'),
|
|
seconds: document.getElementById('countdown-seconds')
|
|
};
|
|
|
|
this.start();
|
|
}
|
|
|
|
start() {
|
|
// Mise à jour immédiate
|
|
this.updateTimer();
|
|
|
|
// Mise à jour chaque seconde
|
|
this.interval = setInterval(() => {
|
|
this.updateTimer();
|
|
}, 1000);
|
|
}
|
|
|
|
updateTimer() {
|
|
const now = new Date().getTime();
|
|
const distance = this.targetDate - now;
|
|
|
|
if (distance < 0) {
|
|
// Le compte à rebours est terminé
|
|
this.stop();
|
|
this.onComplete();
|
|
return;
|
|
}
|
|
|
|
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
|
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
|
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
|
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
|
|
|
// Mise à jour des éléments du DOM
|
|
if (this.elements.days) this.elements.days.textContent = this.formatNumber(days);
|
|
if (this.elements.hours) this.elements.hours.textContent = this.formatNumber(hours);
|
|
if (this.elements.minutes) this.elements.minutes.textContent = this.formatNumber(minutes);
|
|
if (this.elements.seconds) this.elements.seconds.textContent = this.formatNumber(seconds);
|
|
}
|
|
|
|
formatNumber(num) {
|
|
return num.toString().padStart(2, '0');
|
|
}
|
|
|
|
stop() {
|
|
if (this.interval) {
|
|
clearInterval(this.interval);
|
|
}
|
|
}
|
|
|
|
onComplete() {
|
|
// Rediriger vers la page principale quand le compte à rebours est terminé
|
|
window.location.href = '/';
|
|
}
|
|
}
|
|
|
|
// Animation des éléments au chargement
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialiser le compte à rebours si les éléments existent
|
|
if (document.getElementById('countdown-days')) {
|
|
// La date cible est fournie par PHP
|
|
if (typeof COUNTDOWN_TARGET_DATE !== 'undefined') {
|
|
new CountdownTimer(COUNTDOWN_TARGET_DATE);
|
|
}
|
|
}
|
|
|
|
// Animation d'apparition progressive
|
|
const elements = document.querySelectorAll('.countdown-container > *');
|
|
elements.forEach((element, index) => {
|
|
element.style.opacity = '0';
|
|
element.style.transform = 'translateY(30px)';
|
|
|
|
setTimeout(() => {
|
|
element.style.transition = 'opacity 0.8s ease, transform 0.8s ease';
|
|
element.style.opacity = '1';
|
|
element.style.transform = 'translateY(0)';
|
|
}, 100 * (index + 1));
|
|
});
|
|
});
|
|
|
|
// Gérer la fermeture propre du timer
|
|
window.addEventListener('beforeunload', function() {
|
|
// Arrêter le timer si il existe
|
|
if (window.countdownTimer) {
|
|
window.countdownTimer.stop();
|
|
}
|
|
});
|