diff --git a/resources/views/components/video-card.blade.php b/resources/views/components/video-card.blade.php index c8dbc53..5491243 100644 --- a/resources/views/components/video-card.blade.php +++ b/resources/views/components/video-card.blade.php @@ -85,7 +85,14 @@ $sizeClasses = match($size) {
- {{ $video->title ?? 'Video' }} + {{-- width/height let the browser reserve the card's thumb box + BEFORE the image decodes, so a grid of 60 cards doesn't shift + as each thumbnail finishes loading. The ratio is honored by + .yt-video-thumb's aspect-ratio: 16/9 regardless of actual px. --}} + {{ $video->title ?? 'Video' }} @if($video && $video->type === 'match' && $video->sportsMatch) @include('components.partials.vs-mini', ['video' => $video]) @endif @@ -177,9 +184,9 @@ $sizeClasses = match($size) {
@endif -@php $vk = $video->getRouteKey() ?? ''; @endphp - - +{{-- + The per-card edit modal that used to live here (97 lines of markup, 100+ lines of JS) + was dead code — the singleton at resources/views/layouts/partials/edit-video-modal.blade.php + defines a global window.openEditVideoModal that always wins the last-definition race, + so clicking "Edit" on a card has always been going through the singleton. Removing the + per-card copy drops ~6000 lines of HTML from a 60-card feed page. +--}} @include('components.partials.card-styles') @@ -393,155 +312,9 @@ function stopVideo(element) { element.classList.remove('audio-playing'); } -// Edit Modal Functions -let currentEditVideoId = null; - -function openEditVideoModal(videoId) { - currentEditVideoId = videoId; - const modalId = 'editVideoModal' + (videoId || ''); - const modal = new bootstrap.Modal(document.getElementById(modalId)); - modal.show(); - - // Fetch video data - fetch(`/videos/${videoId}/edit`, { - headers: { - 'X-CSRF-TOKEN': '{{ csrf_token() }}', - 'Accept': 'application/json', - 'X-Requested-With': 'XMLHttpRequest' - } - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - const video = data.video; - document.getElementById('edit-title-' + videoId).value = video.title || ''; - document.getElementById('edit-description-' + videoId).value = video.description || ''; - - // Set type - const typeOptions = document.querySelectorAll('#' + modalId + ' .cute-type-option'); - typeOptions.forEach(opt => { - opt.classList.remove('active'); - if (opt.dataset.type === (video.type || 'generic')) { - opt.classList.add('active'); - opt.querySelector('input').checked = true; - } - }); - - // Set privacy - const privacyOptions = document.querySelectorAll('#' + modalId + ' .cute-privacy-option'); - privacyOptions.forEach(opt => { - opt.classList.remove('active'); - if (opt.dataset.privacy === (video.visibility || 'public')) { - opt.classList.add('active'); - opt.querySelector('input').checked = true; - } - }); - - // Set shorts toggle - const shortsCheckbox = document.getElementById('edit-is-shorts-' + videoId); - if (shortsCheckbox) { - shortsCheckbox.checked = video.is_shorts === true || video.is_shorts === 1 || video.is_shorts === '1'; - } - - // Clear status - const statusEl = document.getElementById('edit-status-' + videoId); - statusEl.className = 'cute-status'; - statusEl.textContent = ''; - } - }) - .catch(error => { - console.error('Error:', error); - }); -} - -function closeEditVideoModal(videoId) { - const modalId = 'editVideoModal' + (videoId || ''); - const modalEl = document.getElementById(modalId); - const modal = bootstrap.Modal.getInstance(modalEl); - if (modal) { - modal.hide(); - } -} - -// SPA navigation re-executes this once-protected script on every page swap. -// Guard the document-level listeners so they don't stack up across navs. -if (!window._videoCardListenersBound) { -window._videoCardListenersBound = true; - -// Type option click handlers -document.addEventListener('click', function(e) { - if (e.target.closest('.cute-type-option')) { - const option = e.target.closest('.cute-type-option'); - const parent = option.parentElement; - parent.querySelectorAll('.cute-type-option').forEach(opt => opt.classList.remove('active')); - option.classList.add('active'); - option.querySelector('input').checked = true; - } - if (e.target.closest('.cute-privacy-option')) { - const option = e.target.closest('.cute-privacy-option'); - const parent = option.parentElement; - parent.querySelectorAll('.cute-privacy-option').forEach(opt => opt.classList.remove('active')); - option.classList.add('active'); - option.querySelector('input').checked = true; - } -}); - -// Thumbnail preview -document.addEventListener('change', function(e) { - if (e.target.id && e.target.id.startsWith('edit-thumbnail-')) { - const file = e.target.files[0]; - if (file) { - const videoId = e.target.id.replace('edit-thumbnail-', ''); - const preview = document.getElementById('thumbnail-preview-' + videoId); - preview.innerHTML = `${file.name}`; - } - } -}); - -// Form submission -document.addEventListener('submit', function(e) { - const form = e.target; - if (form.id && form.id.startsWith('edit-video-form-')) { - e.preventDefault(); - const videoId = form.id.replace('edit-video-form-', ''); - const formData = new FormData(form); - const statusEl = document.getElementById('edit-status-' + videoId); - const submitBtn = form.querySelector('.cute-btn-save'); - - submitBtn.disabled = true; - submitBtn.textContent = 'Saving...'; - - fetch(`/videos/${videoId}`, { - method: 'POST', - body: formData, - headers: { - 'X-CSRF-TOKEN': '{{ csrf_token() }}', - 'Accept': 'application/json', - 'X-Requested-With': 'XMLHttpRequest' - } - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - statusEl.className = 'cute-status success'; - statusEl.textContent = '✓ Saved successfully!'; - setTimeout(() => { - closeEditVideoModal(videoId); - window.location.reload(); - }, 1000); - } else { - throw new Error(data.message || 'Update failed'); - } - }) - .catch(error => { - statusEl.className = 'cute-status error'; - statusEl.textContent = '✗ ' + error.message; - submitBtn.disabled = false; - submitBtn.textContent = 'Save'; - }); - } -}); - -} // end _videoCardListenersBound guard +// openEditVideoModal + the type/privacy/thumbnail/submit handlers that used +// to live here were removed with the per-card modal — the singleton at +// layouts/partials/edit-video-modal.blade.php owns the global function and +// handles its own event bindings. @endonce