Files
hstream/resources/views/livewire/nav-live-search.blade.php
2026-07-25 12:38:00 +02:00

171 lines
12 KiB
PHP

<div class="flex items-center relative">
<form method="POST" action="{{ route('hentai.searchredirect') }}" class="w-full">
@csrf
<div class="relative group">
<label for="live-search" class="sr-only">Search</label>
<div class="relative w-full sm:min-w-[200px] md:min-w-[300px] lg:min-w-[400px] xl:min-w-[500px]">
{{-- Search Icon --}}
<div class="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
<svg class="w-4 h-4 text-gray-400 dark:text-gray-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
</svg>
</div>
{{-- Search Input --}}
<input
wire:model.live.debounce.600ms="navSearch"
type="search"
id="live-search"
name="live-search"
class="block w-full pl-10 pr-28 py-3 text-sm rounded-2xl border border-gray-200 bg-white/80 dark:bg-neutral-900/50 dark:border-neutral-700 placeholder-gray-400 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-rose-600 focus:border-rose-700 transition"
placeholder="@if(request()->path() !== 'search'){{ __('search.search-hentai') }}@endif"
required
@if(request()->path() == 'search') disabled @endif
aria-autocomplete="list"
aria-label="Search"
>
{{-- Submit button to redirect to advanced search --}}
<button
type="submit"
class="absolute right-1 top-1/2 -translate-y-1/2 px-4 py-2 text-sm font-medium rounded-xl bg-rose-700 text-white hover:bg-rose-800 focus:outline-none focus:ring-2 focus:ring-rose-300 disabled:bg-gray-300 disabled:hover:bg-gray-300 disabled:dark:bg-gray-500 disabled:dark:hover:bg-gray-500"
@if(request()->path() == 'search') disabled @endif
>{{ __('search.search') }}</button>
</div>
@if((! $hide) && request()->path() != 'search' && request()->path() != 'download-search')
<div
class="pointer-events-auto absolute left-0 right-0 mt-3 z-50 flex justify-center"
aria-live="polite"
>
<div
class="w-full max-h-[70vh] overflow-auto rounded-2xl bg-white dark:bg-neutral-900 border border-gray-200 dark:border-neutral-700 shadow-xl transition-all transform hidden group-focus-within:block group-focus-within:translate-y-0">
{{-- Header --}}
<div class="flex items-center justify-between px-5 py-3 border-b border-gray-100 dark:border-neutral-800">
<div class="text-sm text-gray-700 dark:text-gray-200 font-medium">
@if($episodes->count())
{{ __('Search result for ') }}<span class="text-rose-600 dark:text-rose-400 font-semibold">"{{ $query ?: $navSearch }}"</span>
@else
{{ __('No results') }}
@endif
</div>
{{-- Loading indicator using Livewire --}}
<div class="flex items-center gap-2">
<div wire:loading.class.remove="hidden" class="hidden">
<svg class="w-5 h-5 animate-spin text-rose-600" viewBox="0 0 24 24" fill="none">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-opacity="0.2" stroke-width="4"></circle>
<path d="M22 12a10 10 0 0 1-10 10" stroke="currentColor" stroke-width="4" stroke-linecap="round"></path>
</svg>
</div>
</div>
</div>
{{-- Results List --}}
<div>
@if($episodes->count())
<ul class="divide-y divide-gray-100 dark:divide-neutral-800" role="listbox">
@foreach($episodes as $episode)
<li role="option" aria-selected="false">
<a href="{{ route('hentai.index', ['title' => $episode->slug ]) }}"
class="flex items-center gap-4 px-5 py-2 group/row hover:bg-rose-50/60 dark:hover:bg-rose-950/30 transition-colors duration-150"
>
{{-- Left: Cover Image --}}
<div class="flex-shrink-0 relative">
<div class="w-16 h-[6rem] rounded-lg overflow-hidden ring-1 ring-gray-200/80 dark:ring-neutral-700/80 shadow-sm group-hover/row:ring-rose-300 dark:group-hover/row:ring-rose-700 group-hover/row:shadow-md transition-all duration-200">
<img
alt="{{ $episode->title }} - {{ $episode->episode }}"
loading="lazy"
class="object-cover w-full h-full group-hover/row:scale-105 transition-transform duration-300"
src="{{ $episode->cover_url }}"
>
</div>
<span class="absolute -top-1.5 -right-1.5 bg-rose-600 text-white text-[0.6rem] font-bold leading-none px-1.5 py-0.5 rounded-md shadow-sm">
E{{ $episode->episode }}
</span>
</div>
{{-- Center: Title, Publisher, Tags --}}
<div class="flex-1 min-w-0">
{{-- Row 1: Title --}}
<h3 class="text-sm font-semibold text-gray-900 dark:text-white truncate group-hover/row:text-rose-700 dark:group-hover/row:text-rose-400 transition-colors duration-150">
{{ $episode->title }}
</h3>
{{-- Row 2: Publisher --}}
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1 truncate">
<i class="fa-regular fa-building mr-1 text-[0.65rem] opacity-70"></i>
{{ $episode->studio?->name ?? __('Unknown') }}
</p>
{{-- Row 3: Tags --}}
<div class="mt-1.5 flex items-center gap-1 flex-wrap">
@php
$tags = $episode->tagNames();
$visibleTags = array_slice($tags, 0, 3);
$remainingCount = count($tags) - 3;
@endphp
@foreach($visibleTags as $tag)
<span class="inline-flex items-center px-1.5 py-0 text-[0.6rem] font-medium leading-tight rounded-md bg-rose-100/80 text-rose-700 dark:bg-rose-900/50 dark:text-rose-300 ring-1 ring-inset ring-rose-200/60 dark:ring-rose-800/60">
{{ $tag }}
</span>
@endforeach
@if($remainingCount > 0)
<span class="inline-flex items-center px-1.5 py-0 text-[0.6rem] font-medium leading-tight rounded-md bg-gray-100 text-gray-500 dark:bg-neutral-800 dark:text-gray-400">
+{{ $remainingCount }}
</span>
@endif
</div>
</div>
{{-- Right: View Count, Like Count --}}
<div class="flex-shrink-0 flex flex-col items-end gap-1.5">
<div class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400 tabular-nums" title="{{ __('Views') }}">
<i class="fa-regular fa-eye text-[0.65rem] opacity-70"></i>
<span class="font-medium text-gray-700 dark:text-gray-300">{{ $episode->viewCountFormatted() }}</span>
</div>
<div class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400 tabular-nums" title="{{ __('Likes') }}">
<i class="fa-regular fa-heart text-[0.65rem] opacity-70 text-rose-500 dark:text-rose-400"></i>
<span class="font-medium text-gray-700 dark:text-gray-300">{{ number_format($episode->likeCount()) }}</span>
</div>
</div>
</a>
</li>
@endforeach
{{-- Advanced Search footer --}}
<li>
<a href="{{ route('hentai.search', ['search' => $query]) }}"
class="block px-5 py-3.5 text-center group/advanced hover:bg-rose-50/60 dark:hover:bg-rose-950/30 transition-colors duration-150"
>
<div class="flex items-center justify-center gap-2">
<span class="text-sm font-semibold text-gray-700 dark:text-gray-200 group-hover/advanced:text-rose-700 dark:group-hover/advanced:text-rose-400 transition-colors">
{{ __('Advanced Search') }}
</span>
<span class="text-xs text-gray-400 dark:text-gray-500">{{ __('View all results') }}</span>
<svg class="w-4 h-4 text-gray-400 group-hover/advanced:text-rose-600 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</div>
</a>
</li>
</ul>
@else
{{-- Empty state --}}
<div class="py-12 text-center text-sm text-gray-600 dark:text-gray-300">
<div class="mb-3">{{ __('No results found for') }} <span class="font-semibold text-rose-600">"{{ $query ?: $navSearch }}"</span></div>
<a href="{{ route('hentai.search', ['search' => $navSearch ?: $query]) }}" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-rose-700 text-white text-sm font-medium hover:bg-rose-800 transition shadow-sm hover:shadow-md">
<span>{{ __('Try advanced search') }}</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</a>
</div>
@endif
</div>
</div>
</div>
@endif
</div>
</form>
</div>