Good evening. I’m coming to you because I’m facing an issue with my project.
I’m developing a courses web site and everything is working great, except when changing courses lessons. I mean, if I start playing a video on the platform, it does it just one time, for example, from lesson 1 to lesson 2, or 2 to 1. But it does it just one time, then it doesn’t change de video, change the lesson name, description etc.
This is my Livewire Controller/Model.
<?php
namespace AppLivewire;
use LivewireComponent;
use AppModelsCourse;
use AppModelsLesson;
use IlluminateFoundationAuthAccessAuthorizesRequests;
class CourseStatus extends Component
{
use AuthorizesRequests;
public $course, $current;
public function mount(Course $course){
$this->course = $course;
foreach ($course->lessons as $lesson){
if (!$lesson->completed){
$this->current = $lesson;
break;
}
}
if (!$this->current) {
$this->current = $course->lessons->last();
}
$this->authorize('enrolled', $course);
}
public function render()
{
return view('livewire.course-status');
}
// Métodos
public function changeLesson(Lesson $lesson){
$this->current = $lesson;
}
public function completed(){
if($this->current->completed){
// Eliminar registro
$this->current->users()->detach(auth()->user()->id);
} else {
// Agregar registro
$this->current->users()->attach(auth()->user()->id);
}
$this->current = Lesson::find($this->current->id);
$this->course = Course::find($this->course->id);
}
// Propiedades computadas
public function getIndexProperty(){
return $this->course->lessons->pluck('id')->search($this->current->id);
}
public function getPreviousProperty(){
if ($this->index == 0) {
return null;
} else {
return $this->course->lessons[$this->index - 1];
}
}
public function getNextProperty(){
if ($this->index == $this->course->lessons->count() - 1) {
return null;
} else {
return $this->course->lessons[$this->index + 1];
}
}
public function getAdvanceProperty(){
$i = 0;
foreach ($this->course->lessons as $lesson) {
if ($lesson->completed) {
$i++;
}
}
$advance = ($i * 100)/($this->course->lessons->count());
return round($advance, 2);
}
public function download(){
return response()->download(storage_path('app/' . $this->current->resource->url));
}
}
This is where I get the course id and ofcourse the lesson id. With this i change the lesson with the Next and Previous stuff. Download lesson content and everything related to the play lesson view.
Observer: Lesson Observer
This is where I Create, Update and Delete a Lesson.
<?php
namespace AppObservers;
use AppModelsLesson;
use AppModelsCourse;
use IlluminateSupportFacadesStorage;
class LessonOberver
{
public function creating(Lesson $lesson)
{
$url = $lesson->video_path;
$lesson->video_frame = '<video x-ref="player" playsinline controls data-poster=""><source src="'. $url .'" type="video/mp4" /></video>';
}
public function updating(Lesson $lesson)
{
$url = $lesson->video_path;
$lesson->video_frame = '<video x-ref="player" playsinline controls data-poster=""><source src="'. $url .'" type="video/mp4" /></video>';
}
public function deleting(Lesson $lesson){
if ($lesson->resource) {
Storage::delete($lesson->resource->image_path);
$lesson->resource->delete();
}
}
}
Finally, my view:
<div class="mt-8">
@push('stylesheets')
<link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css" />
@endpush
<div class="container grid grid-cols-1 lg:grid-cols-3 gap-8">
<div class="lg:col-span-2">
{{-- Reproductor de video --}}
<div class="">
@if ($current->video_path)
<div>
<div x-data x-init="let player = new Plyr($refs.player)">
{!! $current->video_frame !!}
</div>
</div>
@endif
</div>
<h1 class="text-3xl text-gray-600 font-bold mt-4">
{{ $current->name }}
</h1>
@if ($current->description)
<div class="text-gray-600 mt-2">
<p class="text-slate-600">{{ $current->description->name }}</p>
</div>
@endif
{{-- Marcar como culminado --}}
<div class="flex justify-between mt-4">
<div class="flex items-center" wire:click="completed">
@if ($current->completed)
<i class="fas fa-toggle-on text-green-500 text-2xl cursor-pointer transition duration-150 ease-out"></i>
@else
<i class="fas fa-toggle-off text-neutral-400 text-2xl cursor-pointer transition duration-150 ease-out"></i>
@endif
<p class="text-sm ml-2 dark:text-neutral-200">Marcar esta unidad como culminada</p>
</div>
@if ($current->resource)
<div wire:click="download" class="flex items-center">
<i class="fa-solid fa-cloud-arrow-down text-neutral-500 hover:text-green-500 text-lg cursor-pointer transition duration-150 ease-out mr-3"></i>
<p class="text-slate-600 hover:text-green-500 transition duration-150 ease-out cursor-pointer">Descargar recurso</p>
</div>
@endif
</div>
<div class="card mt-4">
<div class="card-body flex text-gray-500 font-semibold items-center">
@if ($this->previous)
<a wire:click="changeLesson({{ $this->previous }})" class="cursor-pointer text-sm md:text-base">Lección anterior</a>
@endif
@if ($this->next)
<a wire:click="changeLesson({{ $this->next }})" class="ml-auto cursor-pointer text-sm md:text-base">Siguiente lección</a>
@endif
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<h1 class="text-2xl lead-8 text-center mb-4">{{ $course->title }}</h1>
<div class="flex items-center">
<figure>
<img class="w-12 h-12 object-cover rounded-full mr-4" src="{{ $course->teacher->profile_photo_url }}" alt="">
</figure>
<div>
<p>{{ $course->teacher->name }}</p>
<a class="text-blue-500 text-sm" href="">{{ '@' . Str::slug($course->teacher->name, '') }}</a>
</div>
</div>
<p class="text-neutral-600 text-sm mt-3">{{ $this->advance . '%' }} completado</p>
<div class="relative pt-2">
<div class="overflow-hidden h-2 mb-4 text-xs flex rounded bg-gray-200">
<div style="width:{{ $this->advance . '%' }}" class="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-green-500 transition-all duration-1000"></div>
</div>
</div>
<ul>
@foreach ($course->sections as $section)
<li class="text-gray-600 mb-4">
<a class="font-bold text-base inline-block mb-2" href="">{{ $section->name }}</a>
<ul>
@foreach ($section->lessons as $lesson)
<li class="flex mb-1">
<div>
@if ($lesson->completed)
@if ($current->id == $lesson->id)
<span class="inline-block w-4 h-4 border-2 border-green-300 rounded-full mr-2 mt-1 transition-all duration-1000"></span>
@else
<span class="inline-block w-4 h-4 bg-green-300 rounded-full mr-2 mt-1 transition-all duration-1000"></span>
@endif
@else
@if ($current->id == $lesson->id)
<span class="inline-block w-4 h-4 border-2 border-gray-500 rounded-full mr-2 mt-1 transition-all duration-1000"></span>
@else
<span class="inline-block w-4 h-4 bg-gray-500 rounded-full mr-2 mt-1 transition-all duration-1000"></span>
@endif
@endif
</div>
<a class="cursor-pointer" wire:click="changeLesson({{ $lesson }})">{{ $lesson->name }}</a>
</li>
@endforeach
</ul>
</li>
@endforeach
</ul>
</div>
</div>
</div>
@push('js')
<script src="https://cdn.plyr.io/3.7.8/plyr.js"></script>
<script>
const player = new Plyr('#player');
</script>
@endpush
</div>
Here’s a video to show you what I meaning:
https://drive.google.com/file/d/1OyOeITIILcwz8UTWqhyP1zhswfixS3iT/view?usp=sharing
Thanks in advance.