Files
ohm_streaming/templates/components/anime_search_results.html
T
root 9e53579b36
CI / Test (Python 3.11) (pull_request) Has been cancelled
CI / Test (Python 3.12) (pull_request) Has been cancelled
CI / Lint (pull_request) Has been cancelled
CI / Type Check (pull_request) Has been cancelled
CI / Summary (pull_request) Has been cancelled
feat: flat design Sunset Glitch palette + Font Awesome icons
2026-04-04 07:59:46 +00:00

158 lines
10 KiB
HTML

{% set accent = "#FF9F1C" %}
{% set default_lang = settings.default_lang if settings else 'vostfr' %}
{% 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 (item.metadata.poster_image if item.metadata else "") or "",
"synopsis": (item.metadata.synopsis if item.metadata and item.metadata.synopsis else ""),
"rating": item.metadata.rating if item.metadata and item.metadata.rating else "",
"genres": item.metadata.genres if item.metadata and item.metadata.genres 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 %}
{% if not _existing.synopsis and item.metadata and item.metadata.synopsis %}
{% set _ = _existing.update({"synopsis": item.metadata.synopsis}) %}
{% endif %}
{% if not _existing.rating and item.metadata and item.metadata.rating %}
{% set _ = _existing.update({"rating": item.metadata.rating}) %}
{% endif %}
{% set _ = _existing["providers"].append({"id": item.provider_id or pid, "url": item.url}) %}
{% endif %}
{% endfor %}
{% endfor %}
<div class="sr-list" 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="sr-card" style="--sr-accent: {{ accent }};">
<a class="sr-poster-link" href="{{ first_url }}" target="_blank" rel="noopener">
<img class="sr-poster-img" src="{{ group.cover or 'https://placehold.co/240x360/29274c/7e52a0?text=No+Image' }}"
alt="{{ group.title }}" loading="lazy" referrerpolicy="no-referrer"
onerror="this.src='https://placehold.co/240x360/29274c/7e52a0?text=Error'; this.onerror=null;">
</a>
<div class="sr-body">
<div class="sr-top">
<h3 class="sr-title">{{ group.title }}</h3>
{% if group.rating %}
<span class="sr-rating"><i class="fas fa-star"></i> {{ group.rating }}</span>
{% endif %}
</div>
{% if group.synopsis %}
<p class="sr-synopsis">{{ group.synopsis }}</p>
{% endif %}
{% if group.genres %}
<div class="sr-tags">
{% for g in group.genres[:5] %}
<span class="sr-tag">{{ g }}</span>
{% endfor %}
</div>
{% endif %}
<div class="sr-providers">
{% for p in group.providers %}
<a class="sr-provider-badge" href="{{ p.url }}" target="_blank" rel="noopener">{{ p.id | upper }}</a>
{% endfor %}
</div>
<div class="sr-actions">
<a class="sr-btn sr-btn-watch" href="{{ first_url }}" target="_blank" rel="noopener">
<i class="fas fa-play"></i> Regarder
</a>
<div class="sr-dropdown" @click.outside="openDropdown = null">
<button class="sr-btn sr-btn-dl" @click.stop="openDropdown = (openDropdown === '{{ first_url | urlencode }}') ? null : '{{ first_url | urlencode }}'">
<i class="fas fa-download"></i> Telecharger <i class="fas fa-chevron-down" style="font-size:0.6rem;margin-left:4px;"></i>
</button>
<div class="sr-dropdown-menu" x-show="openDropdown === '{{ first_url | urlencode }}'" x-transition>
<button class="sr-dropdown-item"
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>
<button class="sr-dropdown-item"
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>
</div>
</div>
<button class="sr-btn sr-btn-follow"
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.add('sr-btn-followed')}">
<i class="fas fa-plus"></i> Suivre
</button>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="sr-empty">
<i class="fas fa-search"></i>
<p>Aucun anime trouve pour votre recherche.</p>
</div>
{% endif %}
</div>
<style>
.sr-list { display: flex; flex-direction: column; gap: 16px; }
.sr-card {
display: flex; gap: 20px;
background: var(--bg-card); border-radius: var(--card-radius);
padding: 20px; border: 1px solid #2a2d32;"
transition: var(--transition);
}
.sr-card:hover { border-color: var(--sr-accent); }
.sr-poster-link { flex-shrink: 0; display: block; width: 120px; aspect-ratio: 2/3; border-radius: 4px; overflow: hidden; background: #000; }
.sr-poster-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sr-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.sr-top { display: flex; align-items: baseline; gap: 12px; }
.sr-title { font-size: 1.1rem; font-weight: 700; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sr-rating { flex-shrink: 0; font-size: 0.8rem; font-weight: 700; color: #ffcc00; }
.sr-synopsis { font-size: 0.85rem; color: var(--text-dim); margin: 0; line-height: 1.5; }
.sr-tags { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; }
.sr-tag { font-size: 0.65rem; font-weight: 600; padding: 2px 8px; border-radius: 4px; background: var(--bg-elevated); color: var(--text-dim); }
.sr-providers { display: flex; flex-wrap: wrap; gap: 6px; }
.sr-provider-badge { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; padding: 4px 12px; border-radius: 20px; border: 1px solid var(--sr-accent); color: var(--sr-accent); background: transparent; cursor: pointer; transition: var(--transition); letter-spacing: 0.5px; text-decoration: none; }
.sr-provider-badge:hover { background: var(--sr-accent); color: #fff; }
.sr-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.sr-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 16px; border-radius: 4px; font-size: 0.8rem; font-weight: 600; border: 1px solid #2a2d32; cursor: pointer; transition: var(--transition); text-decoration: none; background: transparent; color: var(--text-main); min-height: 34px; }
.sr-btn:hover { border-color: var(--text-main); background: var(--bg-card); }
.sr-btn-dl { border-color: var(--secondary); color: var(--secondary); }
.sr-btn-dl:hover { background: var(--secondary); color: #ffffff; }
.sr-btn-watch { border-color: var(--sr-accent); color: var(--sr-accent); }
.sr-btn-watch:hover { background: var(--sr-accent); color: #fff; }
.sr-btn-follow { border-color: var(--accent); color: var(--accent); }
.sr-btn-follow:hover { background: var(--accent); color: #fff; }
.sr-btn-followed { border-color: var(--accent); color: var(--accent); background: rgba(255,191,105,0.1); pointer-events: none; }
.sr-dropdown { position: relative; }
.sr-dropdown-menu { position: absolute; top: calc(100% + 6px); left: 0; min-width: 200px; background: var(--bg-card); border: 1px solid #2a2d32; border-radius: 4px; padding: 4px; z-index: 100; }
.sr-dropdown-item { display: flex; align-items: center; gap: 8px; width: 100%; padding: 10px 12px; border: none; background: transparent; color: var(--text-main); font-size: 0.8rem; cursor: pointer; border-radius: 4px; transition: var(--transition); text-align: left; }
.sr-dropdown-item:hover { background: var(--bg-elevated); }
.sr-empty { text-align: center; padding: 100px 20px; color: var(--text-dim); }
.sr-empty i { font-size: 4rem; margin-bottom: 20px; display: block; opacity: 0.2; }
@media (max-width: 768px) {
.sr-card { flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 16px; }
.sr-poster-link { width: 160px; }
.sr-top { justify-content: center; }
.sr-tags { justify-content: center; }
.sr-providers { justify-content: center; }
.sr-actions { justify-content: center; }
}
</style>