diff --git a/TODO.md b/TODO.md
index 3be2386..372a72c 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,28 +1,9 @@
-# TODO: Convert Video Create to Cute Staged Popup Modal
+# TODO: Convert Edit Video Page to Modal
-## Implementation Plan
-
-### 1. Create Upload Modal Partial
-- [x] Create `resources/views/layouts/partials/upload-modal.blade.php`
-- [x] Implement cute staged pop-up animation (scale + fade with bounce)
-- [x] Create multi-step form (Title → Video → Thumbnail → Privacy → Upload)
-- [x] Add progress indicator for current step
-- [x] Style with dark theme + cute accents
-
-### 2. Update Header
-- [x] Modify `resources/views/layouts/partials/header.blade.php`
-- [x] Change Upload button from link to trigger modal via JavaScript
-
-### 3. Include Modal in Views
-- [x] Update `resources/views/videos/index.blade.php` to include upload modal
-- [x] Update `resources/views/layouts/app.blade.php` to include modal globally for auth users
-
-### 4. Keep Fallback Route
-- [x] Keep existing `/videos/create` route for direct access (no changes needed)
-
-## Implementation Notes
-- Uses Bootstrap modal as base
-- Custom CSS for cute staged animation effects
-- JavaScript for step navigation and form handling
-- Matches existing dark theme styling
+## Steps:
+- [x] 1. Create edit-video-modal.blade.php partial with cute design
+- [x] 2. Modify VideoController's edit() method to support AJAX
+- [x] 3. Modify VideoController's update() method for AJAX response
+- [x] 4. Add Edit button and modal include to video show page
+- [x] 5. Test the modal functionality
diff --git a/app/Http/Controllers/VideoController.php b/app/Http/Controllers/VideoController.php
index fc5caaf..26bd8dc 100644
--- a/app/Http/Controllers/VideoController.php
+++ b/app/Http/Controllers/VideoController.php
@@ -158,7 +158,7 @@ class VideoController extends Controller
// Send email notification
try {
- Mail::to(Auth::user()->email)->send(new VideoUploaded($video));
+ Mail::to(Auth::user()->email)->send(new VideoUploaded($video, Auth::user()->name));
} catch (\Exception $e) {
// Log the error but don't fail the upload
\Log::error('Email notification failed: ' . $e->getMessage());
@@ -199,13 +199,39 @@ class VideoController extends Controller
return view('videos.show', compact('video'));
}
- public function edit(Video $video)
+ public function edit(Video $video, Request $request)
{
- return view('videos.edit', compact('video'));
+ // Check if user owns the video
+ if (Auth::id() !== $video->user_id) {
+ abort(403, 'You do not have permission to edit this video.');
+ }
+
+ // If not AJAX request, redirect to show page with edit parameter
+ if (!$request->expectsJson() && !$request->ajax()) {
+ return redirect()->route('videos.show', $video->id)->with('openEditModal', true);
+ }
+
+ // For AJAX request, return JSON
+ return response()->json([
+ 'success' => true,
+ 'video' => [
+ 'id' => $video->id,
+ 'title' => $video->title,
+ 'description' => $video->description,
+ 'thumbnail' => $video->thumbnail,
+ 'thumbnail_url' => $video->thumbnail ? asset('storage/thumbnails/' . $video->thumbnail) : null,
+ 'visibility' => $video->visibility ?? 'public',
+ ]
+ ]);
}
public function update(Request $request, Video $video)
{
+ // Check if user owns the video
+ if (Auth::id() !== $video->user_id) {
+ abort(403, 'You do not have permission to edit this video.');
+ }
+
$request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string',
@@ -231,6 +257,20 @@ class VideoController extends Controller
$video->update($data);
+ // Return JSON for AJAX requests
+ if ($request->expectsJson() || $request->ajax()) {
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Video updated successfully!',
+ 'video' => [
+ 'id' => $video->id,
+ 'title' => $video->title,
+ 'description' => $video->description,
+ 'visibility' => $video->visibility,
+ ]
+ ]);
+ }
+
return redirect()->route('videos.show', $video)->with('success', 'Video updated!');
}
diff --git a/app/Mail/VideoUploaded.php b/app/Mail/VideoUploaded.php
index f95dbe7..dd1e772 100644
--- a/app/Mail/VideoUploaded.php
+++ b/app/Mail/VideoUploaded.php
@@ -13,7 +13,7 @@ class VideoUploaded extends Mailable
{
use Queueable, SerializesModels;
- public function __construct(public Video $video)
+ public function __construct(public Video $video, public string $userName)
{
}
diff --git a/resources/views/emails/video-uploaded.blade.php b/resources/views/emails/video-uploaded.blade.php
index abb6789..2ef248b 100644
--- a/resources/views/emails/video-uploaded.blade.php
+++ b/resources/views/emails/video-uploaded.blade.php
@@ -16,7 +16,7 @@
Video Uploaded Successfully! 🎉
-
Hi {{ $video->user->name }},
+
Hi {{ $userName }},
Your video "{{ $video->title }}" has been uploaded successfully!
Your video is now being processed and will be available shortly.
Video Details:
diff --git a/resources/views/layouts/partials/edit-video-modal.blade.php b/resources/views/layouts/partials/edit-video-modal.blade.php
new file mode 100644
index 0000000..3bb2596
--- /dev/null
+++ b/resources/views/layouts/partials/edit-video-modal.blade.php
@@ -0,0 +1,1051 @@
+
+
+
+
+
+
+
diff --git a/resources/views/layouts/partials/upload-modal.blade.php b/resources/views/layouts/partials/upload-modal.blade.php
index 6c68ba7..a1d28b7 100644
--- a/resources/views/layouts/partials/upload-modal.blade.php
+++ b/resources/views/layouts/partials/upload-modal.blade.php
@@ -208,7 +208,7 @@
- Uploading...
+ Uploading...
0%
@@ -1065,6 +1065,9 @@ document.getElementById('upload-form-modal').addEventListener('submit', function
const formData = new FormData(this);
const xhr = new XMLHttpRequest();
+ // Set timeout for large file uploads (30 minutes for large videos)
+ xhr.timeout = 1800000; // 30 minutes
+
// Show progress
document.getElementById('progress-container-modal').classList.add('active');
document.getElementById('submit-btn-modal').disabled = true;
@@ -1072,40 +1075,73 @@ document.getElementById('upload-form-modal').addEventListener('submit', function
document.getElementById('btn-back-step-4').style.display = 'none';
document.getElementById('status-message-modal').className = 'status-message-modal';
+ // Track upload start time for timeout handling
+ const uploadStartTime = Date.now();
+
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
document.getElementById('progress-bar-modal').style.width = percent + '%';
document.getElementById('progress-percent-modal').textContent = percent + '%';
+
+ // Calculate and display upload speed for large files
+ if (percent > 0) {
+ const elapsed = (Date.now() - uploadStartTime) / 1000; // seconds
+ const speed = (e.loaded / elapsed / 1024 / 1024).toFixed(2); // MB/s
+ if (elapsed > 5 && speed > 0) {
+ document.getElementById('progress-label-modal').textContent = `Uploading... ${speed} MB/s`;
+ }
+ }
}
});
xhr.addEventListener('load', function() {
document.getElementById('progress-bar-modal').style.width = '100%';
- document.getElementById('progress-label').textContent = 'Processing...';
+ document.getElementById('progress-label-modal').textContent = 'Processing...';
- try {
- const response = JSON.parse(xhr.responseText);
- if (response.success) {
- document.getElementById('progress-percent-modal').textContent = 'Done!';
- document.getElementById('status-message-modal').innerHTML = '
Upload successful! Closing...';
- document.getElementById('status-message-modal').className = 'status-message-modal success';
-
- // Close modal and redirect after short delay
- setTimeout(() => {
- closeUploadModal();
- window.location.href = response.redirect;
- }, 1000);
- } else {
- showErrorModal(response.message || 'Upload failed');
+ // Check for successful HTTP status
+ if (xhr.status >= 200 && xhr.status < 300) {
+ try {
+ const response = JSON.parse(xhr.responseText);
+ if (response.success) {
+ document.getElementById('progress-percent-modal').textContent = 'Done!';
+ document.getElementById('status-message-modal').innerHTML = '
Upload successful! Closing...';
+ document.getElementById('status-message-modal').className = 'status-message-modal success';
+
+ // Close modal and redirect after short delay
+ setTimeout(() => {
+ closeUploadModal();
+ window.location.href = response.redirect;
+ }, 1000);
+ } else {
+ showErrorModal(response.message || 'Upload failed');
+ }
+ } catch(e) {
+ showErrorModal('Invalid response from server');
+ }
+ } else if (xhr.status === 0) {
+ showErrorModal('Connection lost. Please check your internet connection and try again.');
+ } else {
+ // Try to parse error message from server response
+ try {
+ const response = JSON.parse(xhr.responseText);
+ showErrorModal(response.message || `Server error (${xhr.status}). Please try again.`);
+ } catch(e) {
+ showErrorModal(`Upload failed with status ${xhr.status}. Please try again.`);
}
- } catch(e) {
- showErrorModal('Invalid response from server');
}
});
xhr.addEventListener('error', function() {
- showErrorModal('Upload failed. Please try again.');
+ showErrorModal('Upload failed. Please check your internet connection and try again.');
+ });
+
+ xhr.addEventListener('timeout', function() {
+ showErrorModal('Upload timed out. The file may be too large or the connection too slow. Please try again.');
+ });
+
+ xhr.addEventListener('abort', function() {
+ showErrorModal('Upload was cancelled. Please try again.');
});
xhr.open('POST', '{{ route("videos.store") }}');
diff --git a/resources/views/videos/edit.blade.php b/resources/views/videos/edit.blade.php
index 29aa11f..8e1cf56 100644
--- a/resources/views/videos/edit.blade.php
+++ b/resources/views/videos/edit.blade.php
@@ -3,269 +3,545 @@
@section('title', 'Edit ' . $video->title . ' | TAKEONE')
@section('extra_styles')
-
+ }
+
@endsection
+@section('body_class', 'edit-page-only')
+
@section('content')
-
-
Edit Video
-
-