✨ feat(assets): Ajoute un loader d'image avec spinner Tailwind et gestion d'erreur.
This commit is contained in:
@@ -45,6 +45,57 @@ const toggleSentry = async (status) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initImageLoader = () => {
|
||||||
|
// On cible uniquement les images à l'intérieur de la balise <main>
|
||||||
|
const mainContainer = document.querySelector('main');
|
||||||
|
if (!mainContainer) return;
|
||||||
|
|
||||||
|
const images = mainContainer.querySelectorAll('img:not(.loaded)');
|
||||||
|
|
||||||
|
|
||||||
|
console.log(images);
|
||||||
|
images.forEach(img => {
|
||||||
|
// Sécurité : si l'image est déjà chargée (cache), on marque et on skip
|
||||||
|
if (img.complete) {
|
||||||
|
img.classList.add('loaded');
|
||||||
|
img.style.opacity = '1';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Préparation du parent (doit être relatif pour le loader absolu)
|
||||||
|
const parent = img.parentElement;
|
||||||
|
if (!parent) return;
|
||||||
|
parent.classList.add('relative', 'overflow-hidden', 'bg-gray-50');
|
||||||
|
|
||||||
|
// 2. Création du Loader (Spinner Tailwind)
|
||||||
|
const loader = document.createElement('div');
|
||||||
|
loader.id = `loader-${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
loader.className = 'absolute inset-0 flex items-center justify-center z-10 bg-gray-50 transition-opacity duration-500';
|
||||||
|
loader.innerHTML = `
|
||||||
|
<div class="flex flex-col items-center gap-2">
|
||||||
|
<div class="w-7 h-7 border-3 border-slate-200 border-t-slate-800 rounded-full animate-spin"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
parent.insertBefore(loader, img);
|
||||||
|
|
||||||
|
// 3. État initial de l'image (invisible)
|
||||||
|
img.classList.add('opacity-0', 'transition-opacity', 'duration-700');
|
||||||
|
|
||||||
|
// 4. Gestionnaire de fin de chargement
|
||||||
|
img.onload = () => {
|
||||||
|
img.classList.replace('opacity-0', 'opacity-100');
|
||||||
|
img.classList.add('loaded');
|
||||||
|
loader.classList.add('opacity-0');
|
||||||
|
setTimeout(() => loader.remove(), 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gestion de l'erreur
|
||||||
|
img.onerror = () => {
|
||||||
|
loader.innerHTML = '<span class="text-[10px] text-gray-400 font-medium uppercase">Erreur</span>';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
// --- LOGIQUE DU LOADER TURBO ---
|
// --- LOGIQUE DU LOADER TURBO ---
|
||||||
const initLoader = () => {
|
const initLoader = () => {
|
||||||
if (document.getElementById('turbo-loader')) return;
|
if (document.getElementById('turbo-loader')) return;
|
||||||
@@ -147,7 +198,7 @@ const initRegisterLogic = () => {
|
|||||||
// --- INITIALISATION GLOBALE ---
|
// --- INITIALISATION GLOBALE ---
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
initLoader();
|
initLoader();
|
||||||
|
initImageLoader();
|
||||||
// Enregistrement Custom Elements
|
// Enregistrement Custom Elements
|
||||||
if (!customElements.get('utm-event')) customElements.define('utm-event', UtmEvent);
|
if (!customElements.get('utm-event')) customElements.define('utm-event', UtmEvent);
|
||||||
if (!customElements.get('utm-account')) customElements.define('utm-account', UtmAccount);
|
if (!customElements.get('utm-account')) customElements.define('utm-account', UtmAccount);
|
||||||
@@ -167,6 +218,7 @@ document.addEventListener('turbo:load', () => {
|
|||||||
initCatalogueSearch();
|
initCatalogueSearch();
|
||||||
initAutoRedirect();
|
initAutoRedirect();
|
||||||
initRegisterLogic();
|
initRegisterLogic();
|
||||||
|
initImageLoader();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("turbo:before-cache", () => {
|
document.addEventListener("turbo:before-cache", () => {
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
main img:not(.loaded) {
|
||||||
|
min-height: 150px; /* Taille minimum le temps du chargement */
|
||||||
|
width: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user