4101d98a41
Design system overhaul using DaisyUI v5 on Tailwind CSS v4: - Custom 'ohmstream' dark theme with orange primary (#FF9F1C), magenta secondary, gold accent matching existing palette - Tailwind CSS-first config (input.css source, style.css built output) - DaisyUI components: navbar, drawer, cards, badges, alerts, tables, progress bars, tabs, toggles, stats, form controls, tooltips - Mobile-first responsive layout with drawer navigation - Eliminated ~500+ lines of embedded CSS across 15+ template files - Removed all inline style spam from admin_panel and settings_section - Preserved all HTMX triggers, Alpine.js state, and Jinja2 logic - Updated auth-ui.js for DaisyUI tab-active class compatibility Build: npm run build:css (minified) / npm run watch:css (dev)
110 lines
6.8 KiB
HTML
110 lines
6.8 KiB
HTML
{% set default_lang = settings.default_lang if settings else 'vf' %}
|
|
|
|
{% set _groups = namespace(items={}) %}
|
|
{% for pid, items in (results or {}).items() %}
|
|
{% for item in items %}
|
|
{% set _key = item.title | lower | trim %}
|
|
{% if _key not in _groups.items %}
|
|
{% set _ = _groups.items.update({_key: {
|
|
"title": item.title,
|
|
"cover": item.cover_image or "",
|
|
"synopsis": (item.metadata.synopsis if item.metadata and item.metadata.synopsis else ""),
|
|
"providers": [{ "id": item.provider_id or pid, "url": item.url }]
|
|
}}) %}
|
|
{% else %}
|
|
{% set _existing = _groups.items[_key] %}
|
|
{% if not _existing.cover and item.cover_image %}
|
|
{% set _ = _existing.update({"cover": item.cover_image}) %}
|
|
{% endif %}
|
|
{% set _ = _existing["providers"].append({"id": item.provider_id or pid, "url": item.url}) %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endfor %}
|
|
|
|
<div class="flex flex-col gap-4" x-data="{ openDropdown: null }">
|
|
{% if _groups.items.values() | list | length > 0 %}
|
|
{% for group in _groups.items.values() | list %}
|
|
{% set first_url = group.providers[0].url %}
|
|
<div class="card bg-base-200 border border-base-300 hover:border-primary transition-colors">
|
|
<div class="card-body p-5 flex-row gap-5">
|
|
<figure class="w-28 shrink-0">
|
|
<a href="{{ first_url }}" target="_blank" rel="noopener">
|
|
<img src="{{ group.cover or 'https://placehold.co/240x360/29274c/7e52a0?text=No+Image' }}"
|
|
alt="{{ group.title }}" loading="lazy" referrerpolicy="no-referrer"
|
|
class="rounded-lg w-full aspect-[2/3] object-cover"
|
|
onerror="this.src='https://placehold.co/240x360/29274c/7e52a0?text=Error'; this.onerror=null;">
|
|
</a>
|
|
</figure>
|
|
<div class="flex-1 min-w-0 flex flex-col gap-2">
|
|
<div class="flex items-baseline gap-3">
|
|
<h3 class="card-title text-base truncate">{{ group.title }}</h3>
|
|
</div>
|
|
|
|
{% if group.synopsis %}
|
|
<p class="text-sm text-base-content/60 line-clamp-3">{{ group.synopsis }}</p>
|
|
{% endif %}
|
|
|
|
<div class="flex flex-wrap gap-1.5">
|
|
{% for p in group.providers %}
|
|
<a href="{{ p.url }}" target="_blank" rel="noopener"
|
|
class="badge badge-primary badge-outline text-xs uppercase tracking-wider hover:bg-primary hover:text-primary-content hover:border-primary transition-colors cursor-pointer">
|
|
{{ p.id | upper }}
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="flex flex-wrap gap-2 mt-1">
|
|
<a href="{{ first_url }}" target="_blank" rel="noopener"
|
|
class="btn btn-sm btn-primary">
|
|
<i class="fas fa-play"></i> Regarder
|
|
</a>
|
|
<div class="dropdown" @click.outside="openDropdown = null">
|
|
<div tabindex="0" role="button"
|
|
@click.stop="openDropdown = (openDropdown === '{{ first_url | urlencode }}') ? null : '{{ first_url | urlencode }}'">
|
|
<span class="btn btn-sm btn-secondary">
|
|
<i class="fas fa-download"></i> Telecharger <i class="fas fa-chevron-down text-[0.6rem] ml-1"></i>
|
|
</span>
|
|
</div>
|
|
<ul tabindex="0"
|
|
class="dropdown-content z-[1] menu p-2 shadow bg-base-200 rounded-box w-52 border border-base-300"
|
|
x-show="openDropdown === '{{ first_url | urlencode }}'"
|
|
x-transition>
|
|
<li>
|
|
<button class="flex items-center gap-2 text-sm"
|
|
hx-post="/api/anime/download-season?url={{ first_url | urlencode }}&lang={{ default_lang }}"
|
|
hx-swap="none"
|
|
hx-on::after-request="openDropdown = null">
|
|
<i class="fas fa-layer-group"></i> Saison complete
|
|
</button>
|
|
</li>
|
|
<li>
|
|
<button class="flex items-center gap-2 text-sm"
|
|
hx-get="/api/anime/episodes?url={{ first_url | urlencode }}&lang={{ default_lang }}&html=1"
|
|
hx-target="#player-container"
|
|
hx-swap="innerHTML"
|
|
hx-on::after-request="openDropdown = null; document.getElementById('player-container').scrollIntoView({behavior: 'smooth'})">
|
|
<i class="fas fa-list-ol"></i> Choisir des episodes
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<button class="btn btn-sm btn-accent btn-outline"
|
|
hx-post="/api/watchlist"
|
|
hx-vals='{"anime_url": "{{ first_url }}", "anime_title": "{{ group.title }}", "provider_id": "{{ group.providers[0].id }}", "lang": "{{ default_lang }}", "poster_image": "{{ group.cover }}"}'
|
|
hx-swap="none"
|
|
hx-on::after-request="if(event.detail.successful){this.innerHTML='<i class=\'fas fa-check\'></i> Suivi';this.disabled=true;this.classList.remove('btn-accent','btn-outline');this.classList.add('btn-accent','btn-ghost','pointer-events-none')}">
|
|
<i class="fas fa-plus"></i> Suivre
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="text-center py-20 text-base-content/40">
|
|
<i class="fas fa-search text-6xl mb-5 block opacity-20"></i>
|
|
<p>Aucune serie TV trouvee pour votre recherche.</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|