Implement academy analytics, billing, and web stories updates

This commit is contained in:
2026-05-26 07:27:29 +02:00
parent 456c3d6bb0
commit 0b33a1b074
177 changed files with 27360 additions and 2685 deletions

View File

@@ -227,10 +227,11 @@ final class SimilarArtworksPageController extends Controller
->public()
->published()
->with([
'categories:id,slug,name',
'categories:id,slug,name,content_type_id',
'categories.contentType:id,name,slug',
'user:id,name,username',
'user.profile:user_id,avatar_hash',
'group:id,name,slug,avatar_path',
])
->get()
->keyBy('id');
@@ -268,6 +269,14 @@ final class SimilarArtworksPageController extends Controller
'sort' => ['trending_score_7d:desc', 'created_at:desc'],
])->paginate(self::PER_PAGE, 'page', $page);
$results->getCollection()->load([
'categories:id,slug,name,content_type_id',
'categories.contentType:id,name,slug',
'user:id,name,username',
'user.profile:user_id,avatar_hash',
'group:id,name,slug,avatar_path',
]);
$results->getCollection()->transform(fn ($a) => $this->presentArtwork($a));
return $results;

View File

@@ -51,7 +51,7 @@ final class TagController extends Controller
$artworks = $this->search->byTag($tag->slug, $perPage, $sort);
// Eager-load relations used by the gallery presenter and thumbnails.
$artworks->getCollection()->each(fn($m) => $m->loadMissing(['user.profile', 'categories']));
$artworks->getCollection()->loadMissing(['user.profile', 'categories.contentType']);
// Sidebar: main content type links (same as browse gallery)
$mainCategories = ContentType::ordered()->where('hide_from_menu', false)->get(['name', 'slug'])

View File

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\WorldWebStory;
use App\Services\WebStories\WorldWebStorySeoService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
final class WorldWebStoryController extends Controller
{
public function __construct(private readonly WorldWebStorySeoService $seo)
{
}
public function index(Request $request): View
{
$stories = Cache::remember('web_story_index', 300, fn () => WorldWebStory::query()
->with('world')
->visible()
->orderByDesc('featured')
->orderByDesc('published_at')
->paginate(12)
->withQueryString());
return view('web-stories.index', [
'stories' => $stories,
'seo' => $this->seo->indexSeo(),
'useUnifiedSeo' => true,
]);
}
public function show(string $slug): View
{
$story = Cache::remember('web_story:' . $slug, 300, fn () => WorldWebStory::query()
->with(['world', 'orderedPages.artwork.user'])
->visible()
->where('slug', $slug)
->first());
abort_unless($story instanceof WorldWebStory, 404);
return view('web-stories.show', [
'story' => $story,
'meta' => $this->seo->storyMeta($story),
]);
}
}