fix: resolve all DaisyUI audit issues

- settings.js: replace broken CSS vars with getThemeColor() helper
- base.html: add bg-primary text-primary-content active state to drawer
- All templates: btn-small -> btn-sm (DaisyUI standard)
- Delete orphan templates/components/header.html
- auth-utils.js: fix .show class -> use hidden (Tailwind)
- login.html: remove redundant auth-* classes, keep DaisyUI only
- auth-ui.js: update form selector for cleanup
- watchlist.html: fix nav active class styling
- 4 JS files (series-search, tabs, recommendations, anime-details):
  - Replace all old CSS classes with DaisyUI/Tailwind
  - Remove hardcoded colors, use theme-aware classes
  - loading-spinner -> DaisyUI loading component
  - no-results/search-results -> Tailwind utility layout
  - All badges -> DaisyUI badge variants
This commit is contained in:
root
2026-04-11 20:20:26 +00:00
parent 4101d98a41
commit 535005b3d5
12 changed files with 375 additions and 405 deletions
+87 -87
View File
@@ -18,30 +18,28 @@ function renderSeriesRecommendationCard(series) {
}
return `
<div class="anime-card-horizontal recommendation-card">
<div class="recommendation-badge"><i class="fa-solid fa-music"></i> Série TV populaire</div>
<div class="card bg-base-200 border border-base-300 shadow-sm">
<div class="badge badge-primary badge-sm absolute top-2 right-2 z-10"><i class="fa-solid fa-music"></i> Série TV populaire</div>
<div class="anime-card-header">
<div class="anime-card-title">${escapeHtml(series.title)}</div>
</div>
<div class="card-body p-4">
<h4 class="card-title text-base">${escapeHtml(series.title)}</h4>
<div class="anime-card-content">
${coverImage ? `<img src="${escapeHtml(coverImage)}" alt="" class="anime-card-image" onerror="this.style.display='none'">` : ''}
<div class="flex gap-3 mt-1">
${coverImage ? `<img src="${escapeHtml(coverImage)}" alt="" class="w-20 h-28 object-cover rounded-lg" onerror="this.style.display='none'">` : ''}
<div class="anime-card-info">
<div class="anime-card-meta">
<i class="fa-solid fa-tv"></i> Série TV
<div class="text-sm text-base-content/60">
<span class="badge badge-sm badge-ghost"><i class="fa-solid fa-tv"></i> Série TV</span>
</div>
</div>
</div>
<div class="anime-card-actions">
<button class="btn btn-secondary btn-small" onclick="window.open('${escapeHtml(series.url)}', '_blank')">
<i class="fa-solid fa-link"></i> Voir sur FS7
</button>
<button class="btn btn-primary btn-small" onclick="loadSeriesEpisodes('${escapeHtml(series.url)}', '${escapeHtml(series.title)}')">
<i class="fa-solid fa-download"></i> Voir les épisodes
</button>
<div class="card-actions justify-end mt-3">
<button class="btn btn-secondary btn-sm" onclick="window.open('${escapeHtml(series.url)}', '_blank')">
<i class="fa-solid fa-link"></i> Voir sur FS7
</button>
<button class="btn btn-primary btn-sm" onclick="loadSeriesEpisodes('${escapeHtml(series.url)}', '${escapeHtml(series.title)}')">
<i class="fa-solid fa-download"></i> Voir les épisodes
</button>
</div>
</div>
</div>
`;
@@ -82,28 +80,26 @@ function renderSeriesReleaseCard(series) {
}
return `
<div class="anime-card-horizontal release-card">
<div class="anime-card-header">
<div class="anime-card-title">${escapeHtml(series.title)}</div>
</div>
<div class="card bg-base-200 border border-base-300 shadow-sm">
<div class="card-body p-4">
<h4 class="card-title text-base">${escapeHtml(series.title)}</h4>
<div class="anime-card-content">
${coverImage ? `<img src="${escapeHtml(coverImage)}" alt="" class="anime-card-image" onerror="this.style.display='none'">` : ''}
<div class="flex gap-3 mt-1">
${coverImage ? `<img src="${escapeHtml(coverImage)}" alt="" class="w-20 h-28 object-cover rounded-lg" onerror="this.style.display='none'">` : ''}
<div class="anime-card-info">
<div class="anime-card-meta">
<i class="fa-solid fa-tv"></i> Série TV • Nouveau
<div class="text-sm text-base-content/60">
<span class="badge badge-sm badge-warning"><i class="fa-solid fa-tv"></i> Série TV • Nouveau</span>
</div>
</div>
</div>
<div class="anime-card-actions">
<button class="btn btn-secondary btn-small" onclick="window.open('${escapeHtml(series.url)}', '_blank')">
<i class="fa-solid fa-link"></i> Voir sur FS7
</button>
<button class="btn btn-primary btn-small" onclick="loadSeriesEpisodes('${escapeHtml(series.url)}', '${escapeHtml(series.title)}')">
<i class="fa-solid fa-download"></i> Voir les épisodes
</button>
<div class="card-actions justify-end mt-3">
<button class="btn btn-secondary btn-sm" onclick="window.open('${escapeHtml(series.url)}', '_blank')">
<i class="fa-solid fa-link"></i> Voir sur FS7
</button>
<button class="btn btn-primary btn-sm" onclick="loadSeriesEpisodes('${escapeHtml(series.url)}', '${escapeHtml(series.title)}')">
<i class="fa-solid fa-download"></i> Voir les épisodes
</button>
</div>
</div>
</div>
`;
@@ -115,7 +111,7 @@ async function loadSeriesRecommendations() {
const container = document.getElementById('seriesRecommendationsList');
if (!container) return;
container.innerHTML = '<div class="loading-spinner">Chargement des recommandations séries...</div>';
container.innerHTML = '<div class="flex justify-center py-8"><span class="loading loading-spinner loading-md"></span><span class="ml-3 text-base-content/60">Chargement des recommandations séries...</span></div>';
// Search for popular series from all providers (including FS7)
const searchTerms = ['Breaking Bad', 'Game of Thrones', 'Stranger Things', 'The Walking Dead', 'The Last of Us', 'Wednesday', 'Squid Game', 'Peaky Blinders', 'House of the Dragon', 'The Witcher'];
@@ -141,16 +137,16 @@ async function loadSeriesRecommendations() {
}
if (allSeries.length > 0) {
container.innerHTML = `<div class="recommendations-carousel">${allSeries.map(series =>
container.innerHTML = `<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">${allSeries.map(series =>
renderSeriesRecommendationCard(series)
).join('')}</div>`;
} else {
container.innerHTML = '<div class="no-results">Aucune recommandation trouvée</div>';
container.innerHTML = '<div class="text-center py-16 text-base-content/50">Aucune recommandation trouvée</div>';
}
} catch (error) {
console.error('Error loading series recommendations:', error);
const container = document.getElementById('seriesRecommendationsList');
if (container) container.innerHTML = '<div class="no-results">Erreur lors du chargement</div>';
if (container) container.innerHTML = '<div class="text-center py-16 text-base-content/50">Erreur lors du chargement</div>';
}
}
@@ -160,23 +156,23 @@ async function loadAnimeReleases() {
const container = document.getElementById('animeReleasesList');
if (!container) return;
container.innerHTML = '<div class="loading-spinner">Chargement des dernières sorties anime...</div>';
container.innerHTML = '<div class="flex justify-center py-8"><span class="loading loading-spinner loading-md"></span><span class="ml-3 text-base-content/60">Chargement des dernières sorties anime...</span></div>';
// Use the existing releases API
const response = await fetch(`${API_BASE}/releases/latest?limit=12`);
const data = await response.json();
if (data.releases && data.releases.length > 0) {
container.innerHTML = `<div class="recommendations-carousel">${data.releases.map(anime =>
container.innerHTML = `<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">${data.releases.map(anime =>
renderReleaseCard(anime)
).join('')}</div>`;
} else {
container.innerHTML = '<div class="no-results">Aucune sortie trouvée</div>';
container.innerHTML = '<div class="text-center py-16 text-base-content/50">Aucune sortie trouvée</div>';
}
} catch (error) {
console.error('Error loading anime releases:', error);
const container = document.getElementById('animeReleasesList');
if (container) container.innerHTML = '<div class="no-results">Erreur lors du chargement</div>';
if (container) container.innerHTML = '<div class="text-center py-16 text-base-content/50">Erreur lors du chargement</div>';
}
}
@@ -186,7 +182,7 @@ async function loadSeriesReleases() {
const container = document.getElementById('seriesReleasesList');
if (!container) return;
container.innerHTML = '<div class="loading-spinner">Chargement des dernières séries TV...</div>';
container.innerHTML = '<div class="flex justify-center py-8"><span class="loading loading-spinner loading-md"></span><span class="ml-3 text-base-content/60">Chargement des dernières séries TV...</span></div>';
// Search for popular series from all providers (including FS7)
const searchTerms = ['Breaking Bad', 'Game of Thrones', 'Stranger Things', 'The Walking Dead', 'The Last of Us', 'Wednesday', 'Squid Game', 'Peaky Blinders'];
@@ -218,14 +214,14 @@ async function loadSeriesReleases() {
}
if (allSeries.length > 0) {
container.innerHTML = `<div class="releases-carousel">${allSeries.map(series =>
container.innerHTML = `<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">${allSeries.map(series =>
renderSeriesReleaseCard(series)
).join('')}</div>`;
} else {
container.innerHTML = `
<div class="no-results">
<div class="text-center py-16 text-base-content/50">
<p>Aucune série trouvée</p>
<p style="font-size: 12px; margin-top: 10px; opacity: 0.7;">
<p class="text-xs mt-2 opacity-70">
Utilisez l'onglet "Recherche" pour trouver des séries spécifiques
</p>
</div>`;
@@ -235,10 +231,11 @@ async function loadSeriesReleases() {
const container = document.getElementById('seriesReleasesList');
if (container) {
container.innerHTML = `
<div class="no-results">
<p><i class="fa-solid fa-xmark"></i> Erreur lors du chargement des séries</p>
<p style="font-size: 12px; margin-top: 10px; color: #ff6b6b;">${error.message}</p>
<button class="btn btn-secondary btn-small" onclick="loadSeriesReleases()" style="margin-top: 10px;">
<div class="text-center py-16 text-base-content/50">
<i class="fa-solid fa-xmark text-3xl mb-3 block"></i>
<p>Erreur lors du chargement des séries</p>
<p class="text-xs mt-2 text-error">${error.message}</p>
<button class="btn btn-secondary btn-sm mt-3" onclick="loadSeriesReleases()">
<i class="fa-solid fa-rotate"></i> Réessayer
</button>
</div>`;
@@ -252,7 +249,7 @@ async function loadProvidersGrid() {
const container = document.getElementById('providersGrid');
if (!container) return;
container.innerHTML = '<div class="loading-spinner">Chargement des fournisseurs...</div>';
container.innerHTML = '<div class="flex justify-center py-8"><span class="loading loading-spinner loading-md"></span><span class="ml-3 text-base-content/60">Chargement des fournisseurs...</span></div>';
const response = await fetch(`${API_BASE}/providers`);
const data = await response.json();
@@ -260,65 +257,67 @@ async function loadProvidersGrid() {
let html = '';
// Section Anime providers
html += '<div class="section-header"><h3 style="margin-top: 20px;"><i class="fa-solid fa-film"></i> Sites Anime</h3></div>';
html += '<div class="search-results">';
html += '<div class="flex items-center gap-2 mt-5 mb-3"><h3 class="text-lg font-semibold"><i class="fa-solid fa-film"></i> Sites Anime</h3></div>';
html += '<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">';
const animeProviders = Object.entries(data.anime_providers || {});
if (animeProviders.length > 0) {
animeProviders.forEach(([id, provider]) => {
const domains = provider.domains || [];
html += `
<div class="anime-card">
<div class="anime-card-header">
<div class="anime-card-title">${provider.icon} ${provider.name}</div>
</div>
${domains.length > 0 ? `
<div class="anime-metadata" style="margin-bottom: 12px;">
<strong>Domaines:</strong><br>
${domains.map(d => `<code style="background: rgba(0,217,255,0.1); padding: 2px 6px; border-radius: 4px; margin-right: 4px;">${d}</code>`).join('')}
</div>
` : ''}
<div class="anime-card-actions">
<div class="card bg-base-200 border border-base-300 shadow-sm">
<div class="card-body p-4">
<h4 class="card-title text-base">${provider.icon} ${provider.name}</h4>
${domains.length > 0 ? `
<button class="btn btn-primary btn-small" onclick="window.open('https://${domains[0]}', '_blank')">
<i class="fa-solid fa-link"></i> Visiter le site
</button>
<div class="text-sm mb-3">
<strong>Domaines:</strong><br>
<div class="flex flex-wrap gap-1 mt-1">
${domains.map(d => `<code class="badge badge-ghost badge-sm">${d}</code>`).join('')}
</div>
</div>
` : ''}
<button class="btn btn-secondary btn-small" onclick="showProviderSearch('${id}')">
<i class="fa-solid fa-magnifying-glass"></i> Rechercher
</button>
<div class="card-actions justify-end">
${domains.length > 0 ? `
<button class="btn btn-primary btn-sm" onclick="window.open('https://${domains[0]}', '_blank')">
<i class="fa-solid fa-link"></i> Visiter le site
</button>
` : ''}
<button class="btn btn-secondary btn-sm" onclick="showProviderSearch('${id}')">
<i class="fa-solid fa-magnifying-glass"></i> Rechercher
</button>
</div>
</div>
</div>
`;
});
} else {
html += '<div class="no-results">Aucun fournisseur anime disponible</div>';
html += '<div class="col-span-full text-center py-16 text-base-content/50">Aucun fournisseur anime disponible</div>';
}
html += '</div>';
// Section File hosts
html += '<div class="section-header" style="margin-top: 40px;"><h3><i class="fa-solid fa-floppy-disk"></i> Hébergeurs de fichiers</h3></div>';
html += '<div class="search-results">';
html += '<div class="flex items-center gap-2 mt-10 mb-3"><h3 class="text-lg font-semibold"><i class="fa-solid fa-floppy-disk"></i> Hébergeurs de fichiers</h3></div>';
html += '<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">';
const fileHosts = Object.entries(data.file_hosts || {});
if (fileHosts.length > 0) {
fileHosts.forEach(([id, host]) => {
html += `
<div class="anime-card">
<div class="anime-card-header">
<div class="anime-card-title">${host.icon} ${host.name}</div>
</div>
<div class="anime-card-actions">
<button class="btn btn-secondary btn-small" onclick="showDownloadInfo()">
<i class="fa-solid fa-download"></i> Télécharger un fichier
</button>
<div class="card bg-base-200 border border-base-300 shadow-sm">
<div class="card-body p-4">
<h4 class="card-title text-base">${host.icon} ${host.name}</h4>
<div class="card-actions justify-end">
<button class="btn btn-secondary btn-sm" onclick="showDownloadInfo()">
<i class="fa-solid fa-download"></i> Télécharger un fichier
</button>
</div>
</div>
</div>
`;
});
} else {
html += '<div class="no-results">Aucun hébergeur disponible</div>';
html += '<div class="col-span-full text-center py-16 text-base-content/50">Aucun hébergeur disponible</div>';
}
html += '</div>';
@@ -329,10 +328,11 @@ async function loadProvidersGrid() {
const container = document.getElementById('providersGrid');
if (container) {
container.innerHTML = `
<div class="no-results">
<p><i class="fa-solid fa-xmark"></i> Erreur lors du chargement des fournisseurs</p>
<p style="font-size: 12px; margin-top: 10px; color: #ff6b6b;">${error.message}</p>
<button class="btn btn-secondary btn-small" onclick="loadProvidersGrid()" style="margin-top: 10px;">
<div class="text-center py-16 text-base-content/50">
<i class="fa-solid fa-xmark text-3xl mb-3 block"></i>
<p>Erreur lors du chargement des fournisseurs</p>
<p class="text-xs mt-2 text-error">${error.message}</p>
<button class="btn btn-secondary btn-sm mt-3" onclick="loadProvidersGrid()">
<i class="fa-solid fa-rotate"></i> Réessayer
</button>
</div>