chore: commit remaining workspace changes

This commit is contained in:
2026-05-08 21:51:29 +02:00
parent 8d108b8a76
commit ff96ef796e
97 changed files with 18020 additions and 2196 deletions

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Http\Controllers\Academy;
use App\Http\Controllers\Controller;
use App\Models\AcademyCourse;
use App\Models\AcademyLesson;
use App\Services\Academy\AcademyAccessService;
use App\Services\Academy\AcademyCacheService;
@@ -35,7 +36,7 @@ final class AcademyLessonController extends Controller
->with('category')
->active()
->published()
->latest('published_at');
->orderedForCourse();
if (filled($filters['q'] ?? null)) {
$query->where(function ($builder) use ($filters): void {
@@ -87,33 +88,73 @@ final class AcademyLessonController extends Controller
->firstOrFail();
$payload = $this->access->lessonPayload($lesson, $request->user(), true);
$relatedLessons = $lesson->category_id !== null
? AcademyLesson::query()
->with('category')
->active()
->published()
->where('category_id', $lesson->category_id)
->where('id', '!=', $lesson->id)
->orderByDesc('published_at')
->limit(6)
->get()
->map(fn (AcademyLesson $relatedLesson): array => $this->access->lessonPayload($relatedLesson, $request->user()))
->values()
->all()
: [];
$courseQuery = AcademyLesson::query()
->with('category')
->active()
->published();
if (filled($lesson->series_name)) {
$courseQuery->where('series_name', $lesson->series_name);
} elseif ($lesson->category_id !== null) {
$courseQuery->where('category_id', $lesson->category_id);
} else {
$courseQuery->whereKey($lesson->id);
}
$courseLessons = $courseQuery
->orderedForCourse()
->get()
->filter(fn (AcademyLesson $courseLesson): bool => $this->access->canAccessLesson($request->user(), $courseLesson))
->values();
$currentIndex = $courseLessons->search(fn (AcademyLesson $courseLesson): bool => $courseLesson->is($lesson));
$previousLesson = is_int($currentIndex) && $currentIndex > 0
? $courseLessons->get($currentIndex - 1)
: null;
$nextLesson = is_int($currentIndex) && $currentIndex < ($courseLessons->count() - 1)
? $courseLessons->get($currentIndex + 1)
: null;
$relatedLessons = $courseLessons
->reject(fn (AcademyLesson $courseLesson): bool => $courseLesson->is($lesson))
->take(6)
->map(fn (AcademyLesson $relatedLesson): array => $this->access->lessonPayload($relatedLesson, $request->user()))
->values()
->all();
$relatedCourses = AcademyCourse::query()
->published()
->ordered()
->whereHas('courseLessons', fn ($builder) => $builder->where('lesson_id', $lesson->id))
->limit(3)
->get()
->map(fn (AcademyCourse $course): array => $this->access->coursePayload($course, $request->user()))
->values()
->all();
$canonical = route('academy.lessons.show', ['slug' => $lesson->slug]);
$description = Str::limit(trim((string) ($lesson->seo_description ?? $lesson->excerpt ?? 'Skinbase Academy lesson.')), 160, '...');
$seo = app(SeoFactory::class)->collectionPage(
$seo = app(SeoFactory::class)->academyLessonPage(
(string) ($lesson->seo_title ?? ($lesson->title.' — Skinbase Academy')),
$description,
$canonical,
$lesson->cover_image,
(string) ($payload['article_cover_image_url'] ?? $payload['cover_image_url'] ?? $lesson->cover_image ?? ''),
[
['name' => 'Academy', 'url' => route('academy.index')],
['name' => 'Lessons', 'url' => route('academy.lessons.index')],
['name' => (string) $lesson->title, 'url' => $canonical],
],
array_values((array) ($payload['tags'] ?? [])),
$lesson->published_at?->toAtomString(),
$lesson->updated_at?->toAtomString(),
(string) ($lesson->series_name ?: $lesson->category?->name ?: 'Academy'),
)->toArray();
return Inertia::render('Academy/Show', [
'pageType' => 'lesson',
'item' => $payload,
'relatedLessons' => $relatedLessons,
'relatedCourses' => $relatedCourses,
'previousLesson' => $previousLesson ? $this->access->lessonPayload($previousLesson, $request->user()) : null,
'nextLesson' => $nextLesson ? $this->access->lessonPayload($nextLesson, $request->user()) : null,
'seo' => $seo,
'pricingUrl' => route('academy.pricing'),
'completeUrl' => $request->user() ? route('academy.lessons.complete', ['lesson' => $lesson->id]) : null,