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:
+39
-37
@@ -16,7 +16,7 @@ async function handleSeriesSearch() {
|
||||
}
|
||||
|
||||
try {
|
||||
resultsContainer.innerHTML = '<div class="loading-spinner">Recherche de séries TV en cours...</div>';
|
||||
resultsContainer.innerHTML = '<div class="flex justify-center py-8"><span class="loading loading-spinner loading-md"></span><span class="ml-3 text-base-content/60">Recherche de séries TV en cours...</span></div>';
|
||||
|
||||
// Search on series providers using the dedicated endpoint
|
||||
const response = await fetch(`${API_BASE}/series/search?q=${encodeURIComponent(query)}&lang=vf`);
|
||||
@@ -25,10 +25,10 @@ async function handleSeriesSearch() {
|
||||
if (data.results && data.results['fs7'] && data.results['fs7'].length > 0) {
|
||||
const series = data.results['fs7'];
|
||||
let html = `
|
||||
<div class="streaming-results-header">
|
||||
<h3><i class="fa-solid fa-tv"></i> Résultats pour "${escapeHtml(query)}"</h3>
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<h3 class="text-lg font-semibold"><i class="fa-solid fa-tv"></i> Résultats pour "${escapeHtml(query)}"</h3>
|
||||
</div>
|
||||
<div class="search-results" style="margin-top: 20px;">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
`;
|
||||
|
||||
series.forEach(s => {
|
||||
@@ -43,25 +43,27 @@ async function handleSeriesSearch() {
|
||||
}
|
||||
|
||||
html += `
|
||||
<div class="anime-card" id="series-fs7-${encodeURIComponent(s.url)}">
|
||||
<div class="anime-card-header">
|
||||
<div class="anime-card-title">${escapeHtml(s.title)}</div>
|
||||
<div class="anime-card-provider"><i class="fa-solid fa-tv"></i> French Stream</div>
|
||||
</div>
|
||||
${coverImage ? `
|
||||
<div style="text-align: center; margin: 10px 0;">
|
||||
<img src="${escapeHtml(coverImage)}" alt="" style="max-width: 200px; border-radius: 4px;" onerror="this.style.display='none'">
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm" id="series-fs7-${encodeURIComponent(s.url)}">
|
||||
<div class="card-body p-4">
|
||||
<div class="flex justify-between items-start">
|
||||
<h4 class="font-semibold text-base">${escapeHtml(s.title)}</h4>
|
||||
<span class="badge badge-sm badge-ghost"><i class="fa-solid fa-tv"></i> French Stream</span>
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="anime-card-actions">
|
||||
<button class="btn btn-secondary btn-small" onclick="window.open('${escapeHtml(s.url)}', '_blank')">
|
||||
<i class="fa-solid fa-link"></i> Voir sur FS7
|
||||
</button>
|
||||
<button class="btn btn-primary btn-small" onclick="loadSeriesEpisodesDirect('${escapeHtml(s.url)}', '${escapeHtml(s.title)}')">
|
||||
<i class="fa-solid fa-download"></i> Voir les épisodes
|
||||
</button>
|
||||
${coverImage ? `
|
||||
<div class="flex justify-center my-2">
|
||||
<img src="${escapeHtml(coverImage)}" alt="" class="max-w-[200px] rounded-lg" onerror="this.style.display='none'">
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="card-actions justify-end mt-2">
|
||||
<button class="btn btn-secondary btn-sm" onclick="window.open('${escapeHtml(s.url)}', '_blank')">
|
||||
<i class="fa-solid fa-link"></i> Voir sur FS7
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm" onclick="loadSeriesEpisodesDirect('${escapeHtml(s.url)}', '${escapeHtml(s.title)}')">
|
||||
<i class="fa-solid fa-download"></i> Voir les épisodes
|
||||
</button>
|
||||
</div>
|
||||
<div id="episodes-fs7-${encodeURIComponent(s.url)}" class="mt-2"></div>
|
||||
</div>
|
||||
<div id="episodes-fs7-${encodeURIComponent(s.url)}" style="margin-top: 10px;"></div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
@@ -70,9 +72,10 @@ async function handleSeriesSearch() {
|
||||
resultsContainer.innerHTML = html;
|
||||
} else {
|
||||
resultsContainer.innerHTML = `
|
||||
<div class="no-results">
|
||||
<p><i class="fa-solid fa-xmark"></i> Aucune série trouvée pour "${escapeHtml(query)}"</p>
|
||||
<p style="font-size: 12px; margin-top: 10px; opacity: 0.7;">
|
||||
<div class="text-center py-16 text-base-content/50">
|
||||
<i class="fa-solid fa-xmark text-3xl mb-3 block"></i>
|
||||
<p>Aucune série trouvée pour "${escapeHtml(query)}"</p>
|
||||
<p class="text-xs mt-2 opacity-70">
|
||||
Essayez avec un autre titre ou vérifiez l'orthographe
|
||||
</p>
|
||||
</div>`;
|
||||
@@ -80,9 +83,10 @@ async function handleSeriesSearch() {
|
||||
} catch (error) {
|
||||
console.error('Error searching series:', error);
|
||||
resultsContainer.innerHTML = `
|
||||
<div class="no-results">
|
||||
<p><i class="fa-solid fa-xmark"></i> Erreur lors de la recherche</p>
|
||||
<p style="font-size: 12px; margin-top: 10px; color: #ff6b6b;">${error.message}</p>
|
||||
<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 de la recherche</p>
|
||||
<p class="text-xs mt-2 text-error">${error.message}</p>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
@@ -94,38 +98,36 @@ async function loadSeriesEpisodesDirect(url, title) {
|
||||
if (!episodesContainer) return;
|
||||
|
||||
try {
|
||||
episodesContainer.innerHTML = '<div class="loading-spinner">Chargement des épisodes...</div>';
|
||||
episodesContainer.innerHTML = '<div class="flex justify-center py-4"><span class="loading loading-spinner loading-sm"></span><span class="ml-2 text-base-content/60 text-sm">Chargement des épisodes...</span></div>';
|
||||
|
||||
const response = await fetch(`${API_BASE}/anime/episodes?url=${encodeURIComponent(url)}&lang=vf`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.episodes && data.episodes.length > 0) {
|
||||
let html = `
|
||||
<div style="margin-top: 15px;">
|
||||
<label style="font-size: 12px; color: #FF9F1C; margin-bottom: 5px; display: block;">
|
||||
<div class="mt-3">
|
||||
<label class="label-text text-xs mb-1 block text-warning">
|
||||
<i class="fa-solid fa-tv"></i> Sélectionner un épisode:
|
||||
</label>
|
||||
<select id="select-episodes-${encodeURIComponent(url)}" style="width: 100%; padding: 8px; border-radius: 4px; border: 1px solid #2a2d32; background: #202327; color: #F2F2F2;">
|
||||
<select id="select-episodes-${encodeURIComponent(url)}" class="select select-bordered select-sm w-full">
|
||||
<option value="">Sélectionner un épisode</option>
|
||||
${data.episodes.map(ep => `
|
||||
<option value="${escapeHtml(ep.url)}">Épisode ${escapeHtml(ep.episode)}</option>
|
||||
`).join('')}
|
||||
</select>
|
||||
<button class="btn btn-primary" style="margin-top: 10px; width: 100%;" onclick="downloadSeriesEpisode('${escapeHtml(url)}', '${escapeHtml(title)}')">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" style="width:14px;height:14px;margin-right:4px;">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path>
|
||||
</svg>
|
||||
<button class="btn btn-primary btn-sm w-full mt-2" onclick="downloadSeriesEpisode('${escapeHtml(url)}', '${escapeHtml(title)}')">
|
||||
<i class="fa-solid fa-download"></i>
|
||||
Télécharger l'épisode
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
episodesContainer.innerHTML = html;
|
||||
} else {
|
||||
episodesContainer.innerHTML = '<div class="no-results" style="margin-top: 10px;">Aucun épisode disponible</div>';
|
||||
episodesContainer.innerHTML = '<div class="text-center py-4 text-base-content/50 text-sm">Aucun épisode disponible</div>';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading episodes:', error);
|
||||
episodesContainer.innerHTML = `<div class="no-results" style="margin-top: 10px; color: #ff6b6b;">Erreur: ${error.message}</div>`;
|
||||
episodesContainer.innerHTML = `<div class="text-center py-4 text-sm text-error">Erreur: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user