feat: ship creator journey v2 and profile updates

This commit is contained in:
2026-04-12 21:42:07 +02:00
parent a2457f4e49
commit d5cff21ea2
335 changed files with 20147 additions and 1545 deletions

View File

@@ -6,8 +6,10 @@ namespace App\Http\Controllers\RSS;
use App\Http\Controllers\Controller;
use App\Models\Artwork;
use App\Models\ContentType;
use App\Services\ContentTypes\ContentTypeSlugResolver;
use App\Services\RSS\RSSFeedBuilder;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;
@@ -30,36 +32,53 @@ final class ExploreFeedController extends Controller
'latest' => 300,
];
public function __construct(private readonly RSSFeedBuilder $builder) {}
public function __construct(
private readonly RSSFeedBuilder $builder,
private readonly ContentTypeSlugResolver $contentTypeResolver,
) {}
/** /rss/explore/{type} — defaults to latest */
public function byType(string $type): Response
public function byType(Request $request, string $type): Response|RedirectResponse
{
return $this->feed($type, 'latest');
return $this->feed($request, $type, 'latest');
}
/** /rss/explore/{type}/{mode} */
public function byTypeMode(string $type, string $mode): Response
public function byTypeMode(Request $request, string $type, string $mode): Response|RedirectResponse
{
return $this->feed($type, $mode);
return $this->feed($request, $type, $mode);
}
// ─────────────────────────────────────────────────────────────────────────
private function feed(string $type, string $mode): Response
private function feed(Request $request, string $type, string $mode): Response|RedirectResponse
{
$mode = in_array($mode, ['trending', 'latest', 'best'], true) ? $mode : 'latest';
$ttl = self::SORT_TTL[$mode] ?? 300;
$feedUrl = url('/rss/explore/' . $type . ($mode !== 'latest' ? '/' . $mode : ''));
$label = ucfirst(str_replace('-', ' ', $type));
$resolution = $this->contentTypeResolver->resolve($type, allowVirtual: true);
$artworks = Cache::remember("rss:explore:{$type}:{$mode}", $ttl, function () use ($type, $mode) {
$contentType = ContentType::where('slug', $type)->first();
if (! $resolution->found()) {
abort(404);
}
$mode = in_array($mode, ['trending', 'latest', 'best'], true) ? $mode : 'latest';
$resolvedType = $resolution->isVirtual ? 'artworks' : strtolower((string) $resolution->contentType?->slug);
if ($resolution->requiresRedirect()) {
return redirect()->to(url('/rss/explore/' . $resolvedType . ($mode !== 'latest' ? '/' . $mode : '')) . ($request->getQueryString() ? ('?' . $request->getQueryString()) : ''), 301);
}
$ttl = self::SORT_TTL[$mode] ?? 300;
$feedUrl = url('/rss/explore/' . $resolvedType . ($mode !== 'latest' ? '/' . $mode : ''));
$label = $resolution->isVirtual
? 'All Artworks'
: ($resolution->contentType?->name ?? ucfirst(str_replace('-', ' ', $resolvedType)));
$artworks = Cache::remember("rss:explore:{$resolvedType}:{$mode}", $ttl, function () use ($resolution, $mode) {
$contentType = $resolution->contentType;
$query = Artwork::public()->published()
->with(['user:id,username', 'categories:id,name,slug,content_type_id']);
if ($contentType) {
if (! $resolution->isVirtual && $contentType) {
$query->whereHas('categories', fn ($q) =>
$q->where('content_type_id', $contentType->id)
);