Filament: LMS: Learning Management System

Simple learning management system with managing courses and lessons, and viewing them from the student panel.

Screenshot 2023-10-19 at 10.38.30

Get the Source Code:

How it works

The project has 3 main parts:

  • Filament Admin Panel
    • Courses
    • Lessons are managed inside the course as a nested resource
    • Course has a featured image using Spatie Media Library
    • Course description has a rich text editor
    • Lesson lesson_text has a rich text editor
    • Lessons can be reordered in the lesson list
    • Course and Lessons can be published/unpublished
  • Filament Student Panel
    • Students can browse courses and lessons
    • Lesson can be marked/unmarked as completed
    • When the student navigates to the next lesson current lesson is automatically marked as completed
    • Students can see their courses in progress on the My Courses page
  • Public page
    • Lists published courses and lessons.
    • To view the lesson user student must register/login
    • After registration/login, students will be redirected to the lesson page if they tried to view it before.

Lesson pages have HasParentResource trait:

app/Filament/Traits/HasParentResource.php

namespace App\Filament\Traits;
 
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
 
trait HasParentResource
{
public Model|int|string|null $parent = null;
 
public function bootHasParentResource(): void
{
if ($parent = (request()->route('parent') ?? request()->input('parent'))) {
$parentResource = $this->getParentResource();
 
$this->parent = $parentResource::resolveRecordRouteBinding($parent);
 
if (! $this->parent) {
throw new ModelNotFoundException();
}
}
}
 
public function getParentResource(): string
{
if (! isset(static::$parentResource)) {
throw new Exception('Parent resource is not set for ' . static::class);
}
 
return static::$parentResource;
}
 
protected function applyFiltersToTableQuery(Builder $query): Builder
{
return $query->where(str($this->parent?->getTable())->singular()->append('_id'), $this->parent->getKey());
}
 
public function getBreadcrumbs(): array
{
$resource = $this->getResource();
$parentResource = $this->getParentResource();
 
$breadcrumbs = [
$parentResource::getUrl() => $parentResource::getBreadCrumb(),
'#parent' => $parentResource::getRecordTitle($this->parent),
];
 
// Breadcrumb to child.index or parent.view
$childIndex = $resource::getPluralModelLabel() . '.index';
$parentView = 'view';
 
if ($parentResource::hasPage($childIndex)) {
$url = $parentResource::getUrl($childIndex, ['parent' => $this->parent]);
$breadcrumbs[$url] = $resource::getBreadCrumb();
} elseif ($parentResource::hasPage($parentView)) {
$url = $parentResource::getUrl($parentView, ['record' => $this->parent]);
$breadcrumbs[$url] = $resource::getBreadCrumb();
}
 
if (isset($this->record)) {
$breadcrumbs['#'] = $resource::getRecordTitle($this->record);
}
 
$breadcrumbs[] = $this->getBreadCrumb();
 
return $breadcrumbs;
}
}

Course resource has custom action to manage lessons and has routes for...

The FULL tutorial is available after the purchase: in the Readme file of the official repository you would get invited to.
Get the Source Code: All 50 Premium Examples for $99 Only Project Examples for $59