- Installed p7h/nas-file-manager package via private VCS repo - Published config/nas-file-manager.php with super_admin middleware restriction - Added NAS env vars to .env.example - Created admin/nas-storage page with connection info panel and file browser widget - Added NAS Storage link to admin sidebar (super_admin only) - Added SuperAdminController@nasStorage method and admin.nas-storage route - Includes all accumulated branch changes: profile wall, 2FA, audit logs, settings panel, country/phone/timezone components, posts, slideshow, playlist shares, video downloads/shares, comment likes, notifications, social links, and more Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
221 lines
8.8 KiB
PHP
221 lines
8.8 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', isset($query) ? 'Search: ' . $query . ' | ' . config('app.name') : config('app.name'))
|
|
|
|
@section('extra_styles')
|
|
<style>
|
|
/* ── Regular video grid ── */
|
|
.yt-video-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 20px;
|
|
}
|
|
@media (max-width: 992px) { .yt-video-grid { grid-template-columns: repeat(2, 1fr); } }
|
|
@media (max-width: 576px) { .yt-video-grid { grid-template-columns: 1fr; gap: 14px; } }
|
|
|
|
|
|
/* ── Playlist count badge (right strip on thumbnail) ── */
|
|
.pl-count-badge {
|
|
position: absolute; inset: 0 0 0 auto;
|
|
width: 72px;
|
|
background: rgba(0,0,0,.78);
|
|
display: flex; flex-direction: column;
|
|
align-items: center; justify-content: center;
|
|
gap: 4px; font-size: 12px; font-weight: 600; color: #fff;
|
|
pointer-events: none;
|
|
}
|
|
.pl-count-badge i { font-size: 20px; }
|
|
|
|
/* ── Playlist type badge (top-left on thumbnail) ── */
|
|
.feed-pl-type-badge {
|
|
position: absolute; top: 8px; left: 8px;
|
|
background: rgba(0,0,0,.75); color: #fff;
|
|
font-size: 11px; font-weight: 700;
|
|
padding: 3px 8px; border-radius: 4px;
|
|
display: flex; align-items: center; gap: 4px;
|
|
text-transform: uppercase; letter-spacing: .4px;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* ── Thumbnail orientation fix ── */
|
|
.yt-video-card .yt-video-thumb img { object-fit: cover; }
|
|
|
|
/* ── Search result helpers ── */
|
|
.search-info { margin-bottom: 20px; padding: 16px; background: var(--bg-secondary); border-radius: 12px; }
|
|
.search-info h2 { font-size: 20px; margin: 0; }
|
|
.search-info p { color: var(--text-secondary); margin: 8px 0 0; }
|
|
.results-section-title {
|
|
font-size: 15px; font-weight: 600; color: var(--text-secondary);
|
|
text-transform: uppercase; letter-spacing: .05em;
|
|
margin: 28px 0 14px;
|
|
display: flex; align-items: center; gap: 8px;
|
|
}
|
|
.results-section-title::after { content: ''; flex: 1; height: 1px; background: var(--border-color); }
|
|
|
|
.yt-empty { text-align: center; padding: 80px 20px; }
|
|
|
|
</style>
|
|
@endsection
|
|
|
|
@section('content')
|
|
|
|
{{-- ── Filter chip bar ── --}}
|
|
@unless(isset($query))
|
|
@php $activeFilter = request('filter', 'all'); @endphp
|
|
<div class="yt-filter-bar">
|
|
<a href="{{ route('videos.index') }}"
|
|
class="yt-chip {{ $activeFilter === 'all' ? 'active' : '' }}">All</a>
|
|
<a href="{{ route('videos.trending') }}"
|
|
class="yt-chip {{ request()->is('trending') ? 'active' : '' }}">Trending</a>
|
|
<a href="{{ route('videos.index', ['filter' => 'music']) }}"
|
|
class="yt-chip {{ $activeFilter === 'music' ? 'active' : '' }}">Music</a>
|
|
<a href="{{ route('videos.index', ['filter' => 'match']) }}"
|
|
class="yt-chip {{ $activeFilter === 'match' ? 'active' : '' }}">Sports</a>
|
|
<a href="{{ route('videos.shorts') }}"
|
|
class="yt-chip {{ request()->is('shorts') ? 'active' : '' }}">Shorts</a>
|
|
<a href="{{ route('videos.index', ['filter' => 'playlists']) }}"
|
|
class="yt-chip {{ $activeFilter === 'playlists' ? 'active' : '' }}">Playlists</a>
|
|
<a href="{{ route('videos.index', ['filter' => 'latest']) }}"
|
|
class="yt-chip {{ $activeFilter === 'latest' ? 'active' : '' }}">New to You</a>
|
|
</div>
|
|
@endunless
|
|
|
|
{{-- ══════════════════════════════════════════════
|
|
SEARCH RESULTS
|
|
══════════════════════════════════════════════ --}}
|
|
@isset($query)
|
|
|
|
@php
|
|
$searchShorts = $shorts ?? collect();
|
|
$searchPlaylists = $playlists ?? collect();
|
|
$totalResults = $videos->count() + $searchShorts->count() + $searchPlaylists->count();
|
|
@endphp
|
|
|
|
<div class="search-info">
|
|
<h2>Search results for "{{ $query }}"</h2>
|
|
<p>
|
|
@if($videos->count()) {{ $videos->count() }} video{{ $videos->count() !== 1 ? 's' : '' }} @endif
|
|
@if($searchShorts->count()) · {{ $searchShorts->count() }} short{{ $searchShorts->count() !== 1 ? 's' : '' }} @endif
|
|
@if($searchPlaylists->count()) · {{ $searchPlaylists->count() }} playlist{{ $searchPlaylists->count() !== 1 ? 's' : '' }} @endif
|
|
@if($totalResults === 0) No results found @endif
|
|
</p>
|
|
</div>
|
|
|
|
@if($videos->count())
|
|
<div class="results-section-title"><i class="bi bi-play-circle"></i> Videos</div>
|
|
<div class="yt-video-grid">
|
|
@foreach($videos as $video)
|
|
@include('components.video-card', ['video' => $video])
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
|
|
@if($searchShorts->count())
|
|
<div class="results-section-title"><i class="bi bi-lightning-charge-fill"></i> Shorts</div>
|
|
<div class="yt-video-grid">
|
|
@foreach($searchShorts as $video)
|
|
@include('components.video-card', ['video' => $video])
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
|
|
@if($searchPlaylists->count())
|
|
<div class="results-section-title"><i class="bi bi-collection-play"></i> Playlists</div>
|
|
<div class="yt-video-grid">
|
|
@foreach($searchPlaylists as $pl)
|
|
@include('components.playlist-card', ['playlist' => $pl])
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
|
|
@if($totalResults === 0)
|
|
<div class="yt-empty">
|
|
<i class="bi bi-search" style="font-size:56px;color:var(--text-secondary);display:block;margin-bottom:12px;"></i>
|
|
<h2>No results for "{{ $query }}"</h2>
|
|
<p style="color:var(--text-secondary);">Try different keywords or browse the gallery.</p>
|
|
</div>
|
|
@endif
|
|
|
|
@endisset
|
|
|
|
{{-- ══════════════════════════════════════════════
|
|
PLAYLISTS-ONLY FILTER
|
|
══════════════════════════════════════════════ --}}
|
|
@if(!isset($query) && isset($filter) && $filter === 'playlists')
|
|
@if(isset($playlists) && $playlists->count())
|
|
<div class="yt-video-grid">
|
|
@foreach($playlists as $pl)
|
|
@include('components.playlist-card', ['playlist' => $pl])
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<div class="yt-empty">
|
|
<i class="bi bi-collection-play" style="font-size:56px;color:var(--text-secondary);display:block;margin-bottom:12px;"></i>
|
|
<h2>No public playlists yet</h2>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- ══════════════════════════════════════════════
|
|
HOME — MIXED FEED
|
|
══════════════════════════════════════════════ --}}
|
|
@elseif(!isset($query) && (!isset($filter) || $filter === 'all'))
|
|
|
|
@if(isset($feedItems) && $feedItems->count())
|
|
<div class="yt-video-grid">
|
|
@foreach($feedItems as $entry)
|
|
@if($entry['kind'] === 'video')
|
|
@include('components.video-card', ['video' => $entry['item']])
|
|
@else
|
|
@php $pl = $entry['item']; @endphp
|
|
@include('components.playlist-card', ['playlist' => $pl, 'showTypeBadge' => true])
|
|
@endif
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<div class="yt-empty">
|
|
<h2>No content yet</h2>
|
|
@auth
|
|
<a href="{{ route('videos.create') }}" class="action-btn action-btn-primary" style="margin-top:12px;">Upload First Video</a>
|
|
@endauth
|
|
</div>
|
|
@endif
|
|
|
|
{{-- ══════════════════════════════════════════════
|
|
SINGLE-TYPE FILTERED VIEWS
|
|
══════════════════════════════════════════════ --}}
|
|
@elseif(!isset($query))
|
|
|
|
@if($videos->isEmpty())
|
|
<div class="yt-empty">
|
|
<i class="bi bi-camera-video" style="font-size:56px;color:var(--text-secondary);display:block;margin-bottom:12px;"></i>
|
|
<h2>Nothing here yet</h2>
|
|
</div>
|
|
@else
|
|
<div class="yt-video-grid">
|
|
@foreach($videos as $video)
|
|
@include('components.video-card', ['video' => $video])
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
|
|
@endif
|
|
|
|
@endsection
|
|
|
|
@section('scripts')
|
|
<script>
|
|
(function () {
|
|
function adjustPlThumb(img) {
|
|
img.style.objectFit = img.naturalWidth < img.naturalHeight ? 'contain' : 'cover';
|
|
}
|
|
document.querySelectorAll('.yt-video-thumb img').forEach(function (img) {
|
|
if (img.complete && img.naturalWidth) {
|
|
adjustPlThumb(img);
|
|
} else {
|
|
img.addEventListener('load', function () { adjustPlThumb(img); });
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
@endsection
|