more fixes
This commit is contained in:
@@ -1,6 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\DashboardController;
|
||||
|
||||
Route::middleware(['web', 'auth'])->prefix('dashboard')->name('api.dashboard.')->group(function () {
|
||||
Route::get('activity', [DashboardController::class, 'activity'])->name('activity');
|
||||
Route::get('analytics', [DashboardController::class, 'analytics'])->name('analytics');
|
||||
Route::get('trending-artworks', [DashboardController::class, 'trendingArtworks'])->name('trending-artworks');
|
||||
Route::get('recommended-creators', [DashboardController::class, 'recommendedCreators'])->name('recommended-creators');
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'auth', 'creator.access'])->prefix('stories')->name('api.stories.')->group(function () {
|
||||
Route::post('create', [\App\Http\Controllers\StoryController::class, 'apiCreate'])->name('create');
|
||||
Route::put('update', [\App\Http\Controllers\StoryController::class, 'apiUpdate'])->name('update');
|
||||
Route::post('autosave', [\App\Http\Controllers\StoryController::class, 'apiAutosave'])->name('autosave');
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'auth', 'creator.access'])->prefix('story')->name('api.story.')->group(function () {
|
||||
Route::post('upload-image', [\App\Http\Controllers\StoryController::class, 'apiUploadImage'])->name('upload-image');
|
||||
Route::get('artworks', [\App\Http\Controllers\StoryController::class, 'apiArtworks'])->name('artworks');
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'auth', 'normalize.username'])->prefix('profile/cover')->name('api.profile.cover.')->group(function () {
|
||||
Route::post('upload', [\App\Http\Controllers\User\ProfileCoverController::class, 'upload'])->middleware('throttle:20,1')->name('upload');
|
||||
Route::post('position', [\App\Http\Controllers\User\ProfileCoverController::class, 'updatePosition'])->middleware('throttle:30,1')->name('position');
|
||||
Route::delete('/', [\App\Http\Controllers\User\ProfileCoverController::class, 'destroy'])->middleware('throttle:20,1')->name('destroy');
|
||||
});
|
||||
|
||||
// ── Per-artwork signal tracking (public) ────────────────────────────────────
|
||||
// GET /api/art/{id}/similar → up to 12 similar artworks (Meilisearch)
|
||||
@@ -89,10 +114,14 @@ Route::prefix('v1')->name('api.v1.')->group(function () {
|
||||
->name('feed');
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'normalize.username', 'throttle:30,1'])
|
||||
Route::middleware(['web', 'normalize.username', 'throttle:username-check'])
|
||||
->get('username/availability', \App\Http\Controllers\Api\UsernameAvailabilityController::class)
|
||||
->name('api.username.availability');
|
||||
|
||||
Route::middleware(['web', 'normalize.username', 'throttle:username-check'])
|
||||
->get('username/check', \App\Http\Controllers\Api\UsernameAvailabilityController::class)
|
||||
->name('api.username.check');
|
||||
|
||||
// Artwork navigation — prev/next neighbors for the fullscreen viewer
|
||||
Route::middleware(['throttle:60,1'])
|
||||
->get('artworks/navigation/{id}', [\App\Http\Controllers\Api\ArtworkNavigationController::class, 'neighbors'])
|
||||
|
||||
@@ -109,3 +109,8 @@ Schedule::command('nova:recalculate-rankings --sync-rank-scores')
|
||||
->name('ranking-v2')
|
||||
->withoutOverlapping()
|
||||
->runInBackground();
|
||||
|
||||
Schedule::command('forum:scan-posts')
|
||||
->everyTenMinutes()
|
||||
->name('forum-scan-posts')
|
||||
->withoutOverlapping();
|
||||
|
||||
163
routes/legacy.php
Normal file
163
routes/legacy.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Legacy routes — old site URL compatibility layer.
|
||||
*
|
||||
* These routes exist purely to keep old bookmarks / external links working.
|
||||
* Most are 301 redirects to their canonical replacements, or thin wrappers
|
||||
* around controllers that were never updated to use new URL patterns.
|
||||
*
|
||||
* Do NOT add new features here. When a legacy route is no longer needed,
|
||||
* remove it from this file.
|
||||
*/
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\Web\ArtController;
|
||||
use App\Http\Controllers\Misc\AvatarController as LegacyAvatarController;
|
||||
use App\Http\Controllers\Web\CategoryController;
|
||||
use App\Http\Controllers\Web\FeaturedArtworksController;
|
||||
use App\Http\Controllers\Web\DailyUploadsController;
|
||||
use App\Http\Controllers\Community\ChatController;
|
||||
use App\Http\Controllers\Community\LatestController;
|
||||
use App\Http\Controllers\Community\LatestCommentsController;
|
||||
use App\Http\Controllers\User\TopFavouritesController;
|
||||
use App\Http\Controllers\User\FavouritesController;
|
||||
use App\Http\Controllers\User\TopAuthorsController;
|
||||
use App\Http\Controllers\User\TodayInHistoryController;
|
||||
use App\Http\Controllers\User\TodayDownloadsController;
|
||||
use App\Http\Controllers\User\MonthlyCommentatorsController;
|
||||
use App\Http\Controllers\User\MembersController;
|
||||
use App\Http\Controllers\User\StatisticsController;
|
||||
use App\Http\Controllers\User\ProfileController;
|
||||
use App\Http\Controllers\Web\BrowseCategoriesController;
|
||||
use App\Http\Controllers\Web\BrowseGalleryController;
|
||||
use App\Http\Controllers\Web\GalleryController;
|
||||
use App\Http\Controllers\Web\RssFeedController;
|
||||
//use App\Http\Controllers\Dashboard\ManageController;
|
||||
//use App\Http\Controllers\User\ReceivedCommentsController;
|
||||
|
||||
// ── AVATARS ───────────────────────────────────────────────────────────────────
|
||||
Route::get('/avatar/{id}/{name?}', [LegacyAvatarController::class, 'show'])
|
||||
->where('id', '\d+')
|
||||
->name('legacy.avatar');
|
||||
|
||||
// ── ARTWORK (legacy comment URL) ──────────────────────────────────────────────
|
||||
Route::match(['get','post'], '/art/{id}/comment', [ArtController::class, 'show'])
|
||||
->where('id', '\d+');
|
||||
|
||||
// ── CATEGORIES / SECTIONS ─────────────────────────────────────────────────────
|
||||
Route::get('/categories', [CategoryController::class, 'index'])->name('legacy.categories');
|
||||
Route::get('/sections', [\App\Http\Controllers\Web\SectionsController::class, 'index'])->name('sections');
|
||||
Route::get('/browse-categories', [BrowseCategoriesController::class, 'index'])->name('browse.categories');
|
||||
|
||||
// Legacy category URL pattern: /category/group/slug/id
|
||||
Route::get('/category/{group}/{slug?}/{id?}', [BrowseGalleryController::class, 'legacyCategory'])
|
||||
->name('legacy.category');
|
||||
|
||||
// ── BROWSE / FEATURED / DAILY ─────────────────────────────────────────────────
|
||||
Route::get('/browse', [BrowseGalleryController::class, 'browse'])->name('legacy.browse');
|
||||
//Route::get('/browse', fn () => redirect('/explore', 301))->name('legacy.browse');
|
||||
Route::get('/browse-redirect', fn () => redirect('/explore', 301))->name('legacy.browse.redirect');
|
||||
Route::get('/wallpapers-redirect', fn () => redirect('/explore/wallpapers', 301))->name('legacy.wallpapers.redirect');
|
||||
Route::get('/featured', [FeaturedArtworksController::class, 'index'])->name('legacy.featured');
|
||||
Route::get('/featured-artworks',[FeaturedArtworksController::class, 'index'])->name('legacy.featured_artworks');
|
||||
Route::get('/daily-uploads', [DailyUploadsController::class, 'index'])->name('legacy.daily_uploads');
|
||||
|
||||
// ── CHAT ──────────────────────────────────────────────────────────────────────
|
||||
Route::get('/chat', [ChatController::class, 'index'])->name('legacy.chat');
|
||||
Route::post('/chat_post', [ChatController::class, 'post'])->name('legacy.chat.post');
|
||||
|
||||
// ── UPLOADS / COMMENTS / DOWNLOADS (SEO alias pages) ─────────────────────────
|
||||
Route::get('/uploads/latest', [LatestController::class, 'index'])->name('uploads.latest');
|
||||
Route::get('/uploads/daily', [DailyUploadsController::class, 'index'])->name('uploads.daily');
|
||||
Route::get('/members/photos', [MembersController::class, 'photos'])->name('members.photos');
|
||||
Route::get('/authors/top', [TopAuthorsController::class, 'index'])->name('authors.top');
|
||||
Route::get('/comments/latest', [LatestCommentsController::class, 'index'])->name('comments.latest');
|
||||
Route::get('/comments/monthly', [MonthlyCommentatorsController::class, 'index'])->name('comments.monthly');
|
||||
Route::get('/downloads/today', [TodayDownloadsController::class, 'index'])->name('downloads.today');
|
||||
|
||||
Route::get('/latest', [LatestController::class, 'index'])->name('legacy.latest');
|
||||
Route::get('/latest-comments', [LatestCommentsController::class, 'index'])->name('legacy.latest_comments');
|
||||
Route::get('/today-in-history', [TodayInHistoryController::class, 'index'])->name('legacy.today_in_history');
|
||||
Route::get('/today-downloads', [TodayDownloadsController::class, 'index'])->name('legacy.today_downloads');
|
||||
Route::get('/monthly-commentators', [MonthlyCommentatorsController::class, 'index'])->name('legacy.monthly_commentators');
|
||||
Route::get('/members', [MembersController::class, 'index'])->name('legacy.members');
|
||||
Route::get('/top-favourites', [TopFavouritesController::class, 'index'])->name('legacy.top_favourites');
|
||||
|
||||
// ── REDIRECTS: top-authors, interviews, apply, bug-report ────────────────────
|
||||
Route::get('/top-authors', fn () => redirect('/creators/top', 301))->name('legacy.top_authors');
|
||||
Route::get('/interviews', fn () => redirect('/stories', 301))->name('legacy.interviews');
|
||||
Route::get('/apply', fn () => redirect('/contact', 301))->name('legacy.apply.redirect');
|
||||
Route::match(['get','post'], '/bug-report', fn () => redirect('/contact', 301))->name('bug-report.redirect');
|
||||
|
||||
// ── BUDDIES / MYBUDDIES ───────────────────────────────────────────────────────
|
||||
Route::middleware('auth')->get('/mybuddies.php', [\App\Http\Controllers\User\MyBuddiesController::class, 'index'])->name('legacy.mybuddies.php');
|
||||
Route::middleware('auth')->get('/mybuddies', [\App\Http\Controllers\User\MyBuddiesController::class, 'index'])->name('legacy.mybuddies');
|
||||
Route::middleware('auth')->delete('/mybuddies/{id}', [\App\Http\Controllers\User\MyBuddiesController::class, 'destroy'])->name('legacy.mybuddies.delete');
|
||||
|
||||
Route::middleware('auth')->get('/buddies.php', [\App\Http\Controllers\User\BuddiesController::class, 'index'])->name('legacy.buddies.php');
|
||||
Route::middleware('auth')->get('/buddies', [\App\Http\Controllers\User\BuddiesController::class, 'index'])->name('legacy.buddies');
|
||||
|
||||
// ── FAVOURITES / GALLERY ──────────────────────────────────────────────────────
|
||||
Route::get('/favourites/{id?}/{username?}', [FavouritesController::class, 'index'])->name('legacy.favourites');
|
||||
Route::post('/favourites/{userId}/delete/{artworkId}', [FavouritesController::class, 'destroy'])->name('legacy.favourites.delete');
|
||||
|
||||
Route::middleware('ensure.onboarding.complete')
|
||||
->get('/gallery/{id}/{username?}', [GalleryController::class, 'show'])
|
||||
->name('legacy.gallery');
|
||||
|
||||
// ── PROFILE (legacy URL patterns) ────────────────────────────────────────────
|
||||
Route::get('/user/{username}', [ProfileController::class, 'legacyByUsername'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('legacy.user.profile');
|
||||
|
||||
Route::get('/profile/{id}/{username?}', [ProfileController::class, 'legacyById'])
|
||||
->where('id', '\d+')
|
||||
->name('legacy.profile.id');
|
||||
|
||||
Route::get('/profile/{username}', [ProfileController::class, 'legacyByUsername'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('legacy.profile');
|
||||
|
||||
// Keep legacy `/user` as a permanent redirect to the canonical dashboard path.
|
||||
Route::middleware(['auth'])->match(['get','post'], '/user', function () {
|
||||
return redirect()->route('dashboard.profile', [], 301);
|
||||
})->name('legacy.user.redirect');
|
||||
|
||||
// ── COMMENTS / STATISTICS ─────────────────────────────────────────────────────
|
||||
//Route::middleware('auth')->get('/recieved-comments', [ReceivedCommentsController::class, 'index'])->name('legacy.received_comments');
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/statistics', [StatisticsController::class, 'index'])->name('legacy.statistics');
|
||||
});
|
||||
|
||||
// ── MANAGE (old artwork management pages) ─────────────────────────────────────
|
||||
/*
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/manage', [ManageController::class, 'index'])->name('manage');
|
||||
Route::get('/manage/edit/{id}', [ManageController::class, 'edit'])->name('manage.edit');
|
||||
Route::post('/manage/update/{id}', [ManageController::class, 'update'])->name('manage.update');
|
||||
Route::post('/manage/delete/{id}', [ManageController::class, 'destroy'])->name('manage.destroy');
|
||||
});
|
||||
*/
|
||||
|
||||
// ── LEGACY FORUM REDIRECT (/forum.php?topic=X) ───────────────────────────────
|
||||
/*
|
||||
Route::middleware('ensure.onboarding.complete')
|
||||
->get('/forum.php', function (\Illuminate\Http\Request $request) {
|
||||
$threadId = (int) ($request->query('topic') ?? $request->query('tid') ?? 0);
|
||||
if ($threadId < 1) {
|
||||
return redirect()->route('forum.index', [], 301);
|
||||
}
|
||||
|
||||
$thread = \App\Models\ForumThread::query()->find($threadId);
|
||||
$slug = $thread?->slug ?: ('thread-' . $threadId);
|
||||
|
||||
return redirect()->route('forum.thread.show', ['thread' => $threadId, 'slug' => $slug], 301);
|
||||
})->name('forum.legacy.redirect');
|
||||
*/
|
||||
// ── LEGACY RSS (.xml feeds — old site compatibility) ──────────────────────────
|
||||
Route::get('/rss/latest-uploads.xml', [RssFeedController::class, 'latestUploads'])->name('rss.uploads');
|
||||
Route::get('/rss/latest-skins.xml', [RssFeedController::class, 'latestSkins'])->name('rss.skins');
|
||||
Route::get('/rss/latest-wallpapers.xml', [RssFeedController::class, 'latestWallpapers'])->name('rss.wallpapers');
|
||||
Route::get('/rss/latest-photos.xml', [RssFeedController::class, 'latestPhotos'])->name('rss.photos');
|
||||
512
routes/web.php
512
routes/web.php
@@ -4,46 +4,22 @@ use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\User\ProfileController;
|
||||
use App\Models\ContentType;
|
||||
use App\Http\Controllers\User\AvatarController;
|
||||
use App\Http\Controllers\Dashboard\ManageController;
|
||||
use App\Http\Controllers\Dashboard\ArtworkController as DashboardArtworkController;
|
||||
use App\Http\Controllers\Web\HomeController;
|
||||
use App\Http\Controllers\Web\ArtController;
|
||||
use App\Http\Controllers\Web\ArtworkPageController;
|
||||
use App\Http\Controllers\Misc\AvatarController as LegacyAvatarController;
|
||||
use App\Http\Controllers\Forum\ForumController;
|
||||
use App\Http\Controllers\Community\NewsController;
|
||||
use App\Http\Controllers\Web\CategoryController;
|
||||
use App\Http\Controllers\Web\FeaturedArtworksController;
|
||||
use App\Http\Controllers\Web\DailyUploadsController;
|
||||
use App\Http\Controllers\Community\ChatController;
|
||||
use App\Http\Controllers\User\TopFavouritesController;
|
||||
use App\Http\Controllers\User\FavouritesController;
|
||||
use App\Http\Controllers\User\TopAuthorsController;
|
||||
use App\Http\Controllers\User\TodayInHistoryController;
|
||||
use App\Http\Controllers\User\TodayDownloadsController;
|
||||
use App\Http\Controllers\User\MonthlyCommentatorsController;
|
||||
use App\Http\Controllers\User\MembersController;
|
||||
use App\Http\Controllers\Community\LatestController;
|
||||
use App\Http\Controllers\Community\LatestCommentsController;
|
||||
use App\Http\Controllers\Community\InterviewController;
|
||||
use App\Http\Controllers\User\StatisticsController;
|
||||
use App\Http\Controllers\User\ReceivedCommentsController;
|
||||
|
||||
use App\Http\Controllers\Web\BrowseCategoriesController;
|
||||
use App\Http\Controllers\Web\GalleryController;
|
||||
use App\Http\Controllers\ArtworkDownloadController;
|
||||
use App\Http\Controllers\Web\BrowseGalleryController;
|
||||
use App\Http\Controllers\Web\DiscoverController;
|
||||
use App\Http\Controllers\Web\ExploreController;
|
||||
use App\Http\Controllers\Web\BlogController;
|
||||
use App\Http\Controllers\Web\PageController;
|
||||
use App\Http\Controllers\Web\StoriesController;
|
||||
use App\Http\Controllers\Web\StoryController;
|
||||
use App\Http\Controllers\Web\StoriesTagController;
|
||||
use App\Http\Controllers\Web\StoriesAuthorController;
|
||||
use App\Http\Controllers\StoryController;
|
||||
use App\Http\Controllers\Web\HomeController;
|
||||
use App\Http\Controllers\Web\FooterController;
|
||||
use App\Http\Controllers\Web\StaffController;
|
||||
use App\Http\Controllers\Web\RssFeedController;
|
||||
use App\Http\Controllers\Web\ApplicationController;
|
||||
use App\Http\Controllers\News\NewsController as FrontendNewsController;
|
||||
use App\Http\Controllers\News\NewsRssController;
|
||||
use App\Http\Controllers\RSS\GlobalFeedController;
|
||||
use App\Http\Controllers\RSS\DiscoverFeedController;
|
||||
use App\Http\Controllers\RSS\ExploreFeedController;
|
||||
@@ -51,11 +27,16 @@ use App\Http\Controllers\RSS\TagFeedController;
|
||||
use App\Http\Controllers\RSS\CreatorFeedController;
|
||||
use App\Http\Controllers\RSS\BlogFeedController;
|
||||
use App\Http\Controllers\Web\StaffApplicationAdminController;
|
||||
use App\Http\Controllers\Studio\StudioController;
|
||||
use App\Http\Controllers\DashboardController;
|
||||
use App\Models\Artwork;
|
||||
use Inertia\Inertia;
|
||||
|
||||
// ── DISCOVER routes (/discover/*) — DiscoverLayout ────────────────────────────
|
||||
Route::get('/', [HomeController::class, 'index'])->name('index');
|
||||
Route::get('/home', [HomeController::class, 'index']);
|
||||
|
||||
// ── DISCOVER (/discover/*) ────────────────────────────────────────────────────
|
||||
Route::prefix('discover')->name('discover.')->group(function () {
|
||||
// /discover → redirect to /discover/trending (§6.2 canonical)
|
||||
Route::get('/', fn () => redirect('/discover/trending', 301));
|
||||
|
||||
Route::get('/trending', [DiscoverController::class, 'trending'])->name('trending');
|
||||
@@ -65,16 +46,15 @@ Route::prefix('discover')->name('discover.')->group(function () {
|
||||
Route::get('/most-downloaded', [DiscoverController::class, 'mostDownloaded'])->name('most-downloaded');
|
||||
Route::get('/on-this-day', [DiscoverController::class, 'onThisDay'])->name('on-this-day');
|
||||
|
||||
// Artworks from people you follow (auth required)
|
||||
Route::middleware('auth')->get('/following', [DiscoverController::class, 'following'])->name('following');
|
||||
|
||||
// Personalised "For You" feed (auth required; guests → redirect)
|
||||
Route::middleware('auth')->get('/for-you', [DiscoverController::class, 'forYou'])->name('for-you');
|
||||
Route::middleware('auth')->get('/for-you', [DiscoverController::class, 'forYou'])->name('for-you');
|
||||
});
|
||||
|
||||
// ── EXPLORE routes (/explore/*) — ExploreLayout ───────────────────────────────
|
||||
// ── EXPLORE (/explore/*) ──────────────────────────────────────────────────────
|
||||
Route::prefix('explore')->name('explore.')->group(function () {
|
||||
Route::get('/', [ExploreController::class, 'index'])->name('index');
|
||||
Route::get('/members', fn () => redirect('/members', 301))->name('members.redirect');
|
||||
Route::get('/memebers', fn () => redirect('/members', 301))->name('memebers.redirect');
|
||||
Route::get('/{type}', [ExploreController::class, 'byType'])
|
||||
->where('type', 'artworks|wallpapers|skins|photography|other')
|
||||
->name('type');
|
||||
@@ -84,61 +64,46 @@ Route::prefix('explore')->name('explore.')->group(function () {
|
||||
->name('type.mode');
|
||||
});
|
||||
|
||||
// ── BLOG routes (/blog/*) — ContentLayout ─────────────────────────────────────
|
||||
// ── BLOG (/blog/*) ────────────────────────────────────────────────────────────
|
||||
Route::prefix('blog')->name('blog.')->group(function () {
|
||||
Route::get('/', [BlogController::class, 'index'])->name('index');
|
||||
Route::get('/{slug}', [BlogController::class, 'show'])->where('slug', '[a-z0-9\-]+')
|
||||
->name('show');
|
||||
Route::get('/', [BlogController::class, 'index'])->name('index');
|
||||
Route::get('/{slug}', [BlogController::class, 'show'])->where('slug', '[a-z0-9\-]+')->name('show');
|
||||
});
|
||||
|
||||
// ── PAGES (DB-driven static pages) — ContentLayout ────────────────────────────
|
||||
Route::get('/pages/{slug}', [PageController::class, 'show'])->where('slug', '[a-z0-9\-]+')
|
||||
// ── PAGES (DB-driven static pages) ───────────────────────────────────────────
|
||||
Route::get('/pages/{slug}', [PageController::class, 'show'])
|
||||
->where('slug', '[a-z0-9\-]+')
|
||||
->name('pages.show');
|
||||
|
||||
// Root-level marketing pages (About, Help, Contact)
|
||||
Route::get('/about', [PageController::class, 'marketing'])->defaults('slug', 'about')->name('about');
|
||||
Route::get('/help', [PageController::class, 'marketing'])->defaults('slug', 'help')->name('help');
|
||||
Route::get('/contact', [PageController::class, 'marketing'])->defaults('slug', 'contact')->name('contact');
|
||||
|
||||
// Legal pages
|
||||
Route::get('/legal/{section}', [PageController::class, 'legal'])
|
||||
->where('section', 'terms|privacy|cookies')
|
||||
->name('legal');
|
||||
|
||||
// ── FOOTER pages ─────────────────────────────────────────────────────────────
|
||||
// Legacy /bug-report now redirects to the universal contact form
|
||||
Route::match(['get','post'], '/bug-report', fn() => redirect('/contact', 301))->name('bug-report.redirect');
|
||||
Route::get('/rss-feeds', [RssFeedController::class, 'index'])->name('rss-feeds');
|
||||
Route::get('/faq', [FooterController::class, 'faq'])->name('faq');
|
||||
// ── FOOTER ────────────────────────────────────────────────────────────────────
|
||||
Route::get('/rss-feeds', [RssFeedController::class, 'index'])->name('rss-feeds');
|
||||
Route::get('/faq', [FooterController::class, 'faq'])->name('faq');
|
||||
Route::get('/rules-and-guidelines', [FooterController::class, 'rules'])->name('rules');
|
||||
Route::get('/privacy-policy', [FooterController::class, 'privacyPolicy'])->name('privacy-policy');
|
||||
Route::get('/terms-of-service', [FooterController::class, 'termsOfService'])->name('terms-of-service');
|
||||
Route::get('/staff', [StaffController::class, 'index'])->name('staff');
|
||||
// Contact form (formerly /apply)
|
||||
Route::get('/contact', [ApplicationController::class, 'show'])->name('contact.show');
|
||||
Route::get('/privacy-policy', [FooterController::class, 'privacyPolicy'])->name('privacy-policy');
|
||||
Route::get('/terms-of-service', [FooterController::class, 'termsOfService'])->name('terms-of-service');
|
||||
Route::get('/staff', [StaffController::class, 'index'])->name('staff');
|
||||
|
||||
Route::get('/contact', [ApplicationController::class, 'show'])->name('contact.show');
|
||||
Route::post('/contact', [ApplicationController::class, 'submit'])->middleware('throttle:6,1')->name('contact.submit');
|
||||
|
||||
// Backwards-compatibility: redirect old /apply to /contact
|
||||
Route::get('/apply', fn() => redirect('/contact', 301))->name('legacy.apply.redirect');
|
||||
|
||||
// Admin: staff application submissions
|
||||
// ── ADMIN: Staff applications ─────────────────────────────────────────────────
|
||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
||||
Route::get('/applications', [StaffApplicationAdminController::class, 'index'])->name('applications.index');
|
||||
Route::get('/applications/{staffApplication}', [StaffApplicationAdminController::class, 'show'])->name('applications.show');
|
||||
Route::get('/applications', [StaffApplicationAdminController::class, 'index'])->name('applications.index');
|
||||
Route::get('/applications/{staffApplication}', [StaffApplicationAdminController::class, 'show'])->name('applications.show');
|
||||
});
|
||||
|
||||
// RSS XML feeds (legacy .xml routes — kept for backward compatibility)
|
||||
Route::get('/rss/latest-uploads.xml', [RssFeedController::class, 'latestUploads'])->name('rss.uploads');
|
||||
Route::get('/rss/latest-skins.xml', [RssFeedController::class, 'latestSkins'])->name('rss.skins');
|
||||
Route::get('/rss/latest-wallpapers.xml', [RssFeedController::class, 'latestWallpapers'])->name('rss.wallpapers');
|
||||
Route::get('/rss/latest-photos.xml', [RssFeedController::class, 'latestPhotos'])->name('rss.photos');
|
||||
|
||||
// ── RSS 2.0 Nova feeds (/rss/*) ───────────────────────────────────────────────
|
||||
// ── RSS 2.0 feeds (/rss/*) ────────────────────────────────────────────────────
|
||||
Route::middleware('throttle:60,1')->group(function () {
|
||||
// Global feed
|
||||
Route::get('/rss', GlobalFeedController::class)->name('rss.global');
|
||||
|
||||
// Discover feeds
|
||||
Route::prefix('rss/discover')->name('rss.discover.')->group(function () {
|
||||
Route::get('/', [DiscoverFeedController::class, 'index'])->name('index');
|
||||
Route::get('/trending', [DiscoverFeedController::class, 'trending'])->name('trending');
|
||||
@@ -146,7 +111,6 @@ Route::middleware('throttle:60,1')->group(function () {
|
||||
Route::get('/rising', [DiscoverFeedController::class, 'rising'])->name('rising');
|
||||
});
|
||||
|
||||
// Explore category feeds
|
||||
Route::prefix('rss/explore')->name('rss.explore.')->group(function () {
|
||||
Route::get('/{type}', [ExploreFeedController::class, 'byType'])
|
||||
->where('type', 'artworks|wallpapers|skins|photography|other')
|
||||
@@ -157,130 +121,95 @@ Route::middleware('throttle:60,1')->group(function () {
|
||||
->name('type.mode');
|
||||
});
|
||||
|
||||
// Tag feeds
|
||||
Route::get('/rss/tag/{slug}', TagFeedController::class)
|
||||
->where('slug', '[a-z0-9\-]+')
|
||||
->name('rss.tag');
|
||||
|
||||
// Creator feeds
|
||||
Route::get('/rss/creator/{username}', CreatorFeedController::class)
|
||||
->where('username', '[A-Za-z0-9_\-]{3,20}')
|
||||
->name('rss.creator');
|
||||
|
||||
// Blog feed
|
||||
Route::get('/rss/blog', BlogFeedController::class)->name('rss.blog');
|
||||
});
|
||||
|
||||
// ── 301 REDIRECTS: Legacy → Canonical URLs ────────────────────────────────────
|
||||
// §6.1 — /browse → /explore
|
||||
Route::get('/browse-redirect', fn () => redirect('/explore', 301))->name('legacy.browse.redirect');
|
||||
// §6.1 — /wallpapers as standalone → /explore/wallpapers
|
||||
Route::get('/wallpapers-redirect', fn () => redirect('/explore/wallpapers', 301))->name('legacy.wallpapers.redirect');
|
||||
|
||||
// ── CREATORS routes (/creators/*) ─────────────────────────────────────────────
|
||||
// ── CREATORS (/creators/*) ────────────────────────────────────────────────────
|
||||
Route::prefix('creators')->name('creators.')->group(function () {
|
||||
// Top Creators → reuse existing top-authors controller
|
||||
Route::get('/top', [\App\Http\Controllers\User\TopAuthorsController::class, 'index'])->name('top');
|
||||
// Rising Creators → newest creators with recent uploads
|
||||
Route::get('/rising', [\App\Http\Controllers\Web\DiscoverController::class, 'risingCreators'])->name('rising');
|
||||
Route::get('/rising', [DiscoverController::class, 'risingCreators'])->name('rising');
|
||||
});
|
||||
|
||||
// ── STORIES routes (/stories/*) — Nova Stories System ────────────────────────
|
||||
// ── STORIES (/stories/*) ──────────────────────────────────────────────────────
|
||||
Route::prefix('stories')->name('stories.')->group(function () {
|
||||
Route::get('/', [StoriesController::class, 'index'])->name('index');
|
||||
Route::get('/tag/{tag}', [StoriesTagController::class, 'show'])
|
||||
Route::get('/', [StoryController::class, 'index'])->name('index');
|
||||
Route::get('/tag/{tag}', [StoryController::class, 'tag'])
|
||||
->where('tag', '[a-z0-9\-]+')
|
||||
->name('tag');
|
||||
Route::get('/author/{username}', [StoriesAuthorController::class, 'show'])
|
||||
Route::get('/creator/{username}', [StoryController::class, 'creator'])
|
||||
->where('username', '[A-Za-z0-9_\-]{1,50}')
|
||||
->name('creator');
|
||||
Route::get('/author/{username}', fn (string $username) => redirect()->route('stories.creator', ['username' => $username], 301))
|
||||
->where('username', '[A-Za-z0-9_\-]{1,50}')
|
||||
->name('author');
|
||||
Route::get('/category/{category}', [StoryController::class, 'category'])
|
||||
->where('category', 'creator_story|tutorial|interview|project_breakdown|announcement|resource')
|
||||
->name('category');
|
||||
Route::get('/{slug}', [StoryController::class, 'show'])
|
||||
->where('slug', '[a-z0-9\-]+')
|
||||
->name('show');
|
||||
});
|
||||
|
||||
// Tags listing page
|
||||
Route::get('/tags', [\App\Http\Controllers\Web\TagController::class, 'index'])->name('tags.index');
|
||||
Route::middleware(['auth', 'ensure.onboarding.complete', 'creator.access'])->prefix('creator/stories')->name('creator.stories.')->group(function () {
|
||||
Route::get('/', [StoryController::class, 'dashboard'])->name('index');
|
||||
Route::get('/create', [StoryController::class, 'create'])->name('create');
|
||||
Route::post('/', [StoryController::class, 'store'])->name('store');
|
||||
Route::get('/artworks/search', [StoryController::class, 'searchArtworks'])->name('artworks.search');
|
||||
Route::post('/upload-image', [StoryController::class, 'uploadImage'])->name('upload-image');
|
||||
Route::get('/{story}/edit', [StoryController::class, 'edit'])->name('edit');
|
||||
Route::put('/{story}', [StoryController::class, 'update'])->name('update');
|
||||
Route::delete('/{story}', [StoryController::class, 'destroy'])->name('destroy');
|
||||
Route::post('/{story}/autosave', [StoryController::class, 'autosave'])->name('autosave');
|
||||
Route::post('/{story}/submit-review', [StoryController::class, 'submitForReview'])->name('submit-review');
|
||||
Route::post('/{story}/publish', [StoryController::class, 'publishNow'])->name('publish-now');
|
||||
Route::get('/{story}/preview', [StoryController::class, 'preview'])->name('preview');
|
||||
Route::get('/{story}/analytics', [StoryController::class, 'analytics'])->name('analytics');
|
||||
});
|
||||
|
||||
// Following redirect (convenience shortcut for authenticated users)
|
||||
// ── TAGS ──────────────────────────────────────────────────────────────────────
|
||||
Route::get('/tags', [\App\Http\Controllers\Web\TagController::class, 'index'])->name('tags.index');
|
||||
Route::get('/tag/{tag:slug}', [\App\Http\Controllers\Web\TagController::class, 'show'])
|
||||
->where('tag', '[a-z0-9\-]+')
|
||||
->name('tags.show');
|
||||
Route::get('/tags/{tag}', [\App\Http\Controllers\Web\Posts\HashtagFeedController::class, 'index'])
|
||||
->where('tag', '[A-Za-z][A-Za-z0-9_]{1,63}')
|
||||
->name('feed.hashtag');
|
||||
|
||||
// ── FOLLOWING (shortcut) ──────────────────────────────────────────────────────
|
||||
Route::middleware('auth')->get('/following', function () {
|
||||
return redirect()->route('dashboard.following');
|
||||
})->name('following.redirect');
|
||||
|
||||
// Legacy route set migrated from routes/legacy.php into this file.
|
||||
Route::get('/', [HomeController::class, 'index'])->name('legacy.home');
|
||||
Route::get('/home', [HomeController::class, 'index']);
|
||||
// ── ART / ARTWORKS ────────────────────────────────────────────────────────────
|
||||
Route::get('/art/{id}/{slug?}', [ArtworkPageController::class, 'show'])
|
||||
->where('id', '\d+')
|
||||
->name('art.show');
|
||||
|
||||
Route::get('/art/{id}/{slug?}', [ArtworkPageController::class, 'show'])->where('id', '\\d+')->name('art.show');
|
||||
Route::match(['get','post'], '/art/{id}/comment', [ArtController::class, 'show'])->where('id', '\\d+');
|
||||
Route::get('/download/artwork/{id}', ArtworkDownloadController::class)
|
||||
->whereNumber('id')
|
||||
->middleware('throttle:downloads')
|
||||
->name('art.download');
|
||||
|
||||
Route::get('/avatar/{id}/{name?}', [LegacyAvatarController::class, 'show'])->where('id', '\\d+')->name('legacy.avatar');
|
||||
|
||||
Route::middleware('ensure.onboarding.complete')->prefix('forum')->name('forum.')->group(function () {
|
||||
Route::get('/', [ForumController::class, 'index'])->name('index');
|
||||
Route::get('/thread/{thread}-{slug?}', [ForumController::class, 'showThread'])->name('thread.show');
|
||||
Route::get('/{category:slug}', [ForumController::class, 'showCategory'])->name('category.show');
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::get('/{category:slug}/new', [ForumController::class, 'createThreadForm'])->name('thread.create');
|
||||
Route::post('/{category:slug}/new', [ForumController::class, 'storeThread'])->name('thread.store');
|
||||
Route::post('/thread/{thread}/reply', [ForumController::class, 'reply'])->name('thread.reply');
|
||||
Route::post('/post/{post}/report', [ForumController::class, 'reportPost'])->name('post.report');
|
||||
Route::get('/post/{post}/edit', [ForumController::class, 'editPostForm'])->name('post.edit');
|
||||
Route::put('/post/{post}', [ForumController::class, 'updatePost'])->name('post.update');
|
||||
});
|
||||
|
||||
Route::middleware(['auth', 'can:moderate-forum'])->group(function () {
|
||||
Route::post('/thread/{thread}/lock', [ForumController::class, 'lockThread'])->name('thread.lock');
|
||||
Route::post('/thread/{thread}/unlock', [ForumController::class, 'unlockThread'])->name('thread.unlock');
|
||||
Route::post('/thread/{thread}/pin', [ForumController::class, 'pinThread'])->name('thread.pin');
|
||||
Route::post('/thread/{thread}/unpin', [ForumController::class, 'unpinThread'])->name('thread.unpin');
|
||||
});
|
||||
// ── NEWS (/news/*) ────────────────────────────────────────────────────────────
|
||||
Route::prefix('news')->name('news.')->group(function () {
|
||||
Route::get('/', [FrontendNewsController::class, 'index'])->name('index');
|
||||
Route::get('category/{slug}', [FrontendNewsController::class, 'category'])->name('category');
|
||||
Route::get('tag/{slug}', [FrontendNewsController::class, 'tag'])->name('tag');
|
||||
Route::get('{slug}', [FrontendNewsController::class, 'show'])
|
||||
->where('slug', '[a-z0-9\-]+')
|
||||
->name('show');
|
||||
});
|
||||
Route::get('/rss/news', [NewsRssController::class, 'feed'])->name('news.rss');
|
||||
|
||||
Route::middleware('ensure.onboarding.complete')->get('/forum.php', function (\Illuminate\Http\Request $request) {
|
||||
$threadId = (int) ($request->query('topic') ?? $request->query('tid') ?? 0);
|
||||
if ($threadId < 1) {
|
||||
return redirect()->route('forum.index', [], 301);
|
||||
}
|
||||
|
||||
$thread = \App\Models\ForumThread::query()->find($threadId);
|
||||
$slug = $thread?->slug ?: ('thread-' . $threadId);
|
||||
|
||||
return redirect()->route('forum.thread.show', ['thread' => $threadId, 'slug' => $slug], 301);
|
||||
})->name('forum.legacy.redirect');
|
||||
|
||||
// News/Announcements listing — redirect to forum index until a dedicated page exists
|
||||
Route::get('/news', function () {
|
||||
return redirect()->route('forum.index', [], 301);
|
||||
})->name('news.index');
|
||||
|
||||
Route::get('/news/{id}/{slug?}', [NewsController::class, 'show'])->where('id', '\\d+')->name('legacy.news.show');
|
||||
|
||||
Route::get('/categories', [CategoryController::class, 'index'])->name('legacy.categories');
|
||||
Route::get('/sections', [\App\Http\Controllers\Web\SectionsController::class, 'index'])->name('sections');
|
||||
|
||||
// Clean SEO-friendly URL aliases
|
||||
Route::get('/uploads/latest', [LatestController::class, 'index'])->name('uploads.latest');
|
||||
Route::get('/uploads/daily', [DailyUploadsController::class, 'index'])->name('uploads.daily');
|
||||
Route::get('/members/photos', [MembersController::class, 'photos'])->name('members.photos');
|
||||
Route::get('/authors/top', [TopAuthorsController::class, 'index'])->name('authors.top');
|
||||
Route::get('/comments/latest', [LatestCommentsController::class, 'index'])->name('comments.latest');
|
||||
Route::get('/comments/monthly', [MonthlyCommentatorsController::class, 'index'])->name('comments.monthly');
|
||||
Route::get('/downloads/today', [TodayDownloadsController::class, 'index'])->name('downloads.today');
|
||||
|
||||
Route::get('/category/{group}/{slug?}/{id?}', [BrowseGalleryController::class, 'legacyCategory'])->name('legacy.category');
|
||||
|
||||
// §6.1 — /browse → 301 to /explore (canonical)
|
||||
Route::get('/browse', fn () => redirect('/explore', 301))->name('legacy.browse');
|
||||
Route::get('/featured', [FeaturedArtworksController::class, 'index'])->name('legacy.featured');
|
||||
Route::get('/featured-artworks', [FeaturedArtworksController::class, 'index'])->name('legacy.featured_artworks');
|
||||
Route::get('/daily-uploads', [DailyUploadsController::class, 'index'])->name('legacy.daily_uploads');
|
||||
Route::get('/chat', [ChatController::class, 'index'])->name('legacy.chat');
|
||||
Route::post('/chat_post', [ChatController::class, 'post'])->name('legacy.chat.post');
|
||||
|
||||
Route::get('/browse-categories', [BrowseCategoriesController::class, 'index'])->name('browse.categories');
|
||||
|
||||
// ── PROFILES (@username) ──────────────────────────────────────────────────────
|
||||
Route::get('/@{username}', [ProfileController::class, 'showByUsername'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('profile.show');
|
||||
@@ -293,115 +222,72 @@ Route::middleware('auth')->post('/@{username}/comment', [ProfileController::clas
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('profile.comment');
|
||||
|
||||
Route::get('/user/{username}', [ProfileController::class, 'legacyByUsername'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('legacy.user.profile');
|
||||
// ── DASHBOARD ─────────────────────────────────────────────────────────────────
|
||||
Route::get('/dashboard', [DashboardController::class, 'index'])
|
||||
->middleware(['auth', 'verified'])
|
||||
->name('dashboard');
|
||||
|
||||
Route::get('/profile/{id}/{username?}', [ProfileController::class, 'legacyById'])
|
||||
->where('id', '\\d+')
|
||||
->name('legacy.profile.id');
|
||||
|
||||
Route::get('/profile/{username}', [ProfileController::class, 'legacyByUsername'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('legacy.profile');
|
||||
|
||||
Route::get('/top-favourites', [TopFavouritesController::class, 'index'])->name('legacy.top_favourites');
|
||||
// /top-authors → 301 redirect to canonical /creators/top
|
||||
Route::get('/top-authors', function () {
|
||||
return redirect('/creators/top', 301);
|
||||
})->name('legacy.top_authors');
|
||||
|
||||
Route::middleware('auth')->get('/mybuddies.php', [\App\Http\Controllers\User\MyBuddiesController::class, 'index'])->name('legacy.mybuddies.php');
|
||||
Route::middleware('auth')->get('/mybuddies', [\App\Http\Controllers\User\MyBuddiesController::class, 'index'])->name('legacy.mybuddies');
|
||||
Route::middleware('auth')->delete('/mybuddies/{id}', [\App\Http\Controllers\User\MyBuddiesController::class, 'destroy'])->name('legacy.mybuddies.delete');
|
||||
|
||||
Route::middleware('auth')->get('/buddies.php', [\App\Http\Controllers\User\BuddiesController::class, 'index'])->name('legacy.buddies.php');
|
||||
Route::middleware('auth')->get('/buddies', [\App\Http\Controllers\User\BuddiesController::class, 'index'])->name('legacy.buddies');
|
||||
|
||||
Route::get('/favourites/{id?}/{username?}', [FavouritesController::class, 'index'])->name('legacy.favourites');
|
||||
Route::post('/favourites/{userId}/delete/{artworkId}', [FavouritesController::class, 'destroy'])->name('legacy.favourites.delete');
|
||||
|
||||
Route::middleware('ensure.onboarding.complete')->get('/gallery/{id}/{username?}', [GalleryController::class, 'show'])->name('legacy.gallery');
|
||||
|
||||
Route::middleware('auth')->get('/recieved-comments', [ReceivedCommentsController::class, 'index'])->name('legacy.received_comments');
|
||||
|
||||
// Canonical dashboard profile route: Inertia-powered Settings page.
|
||||
Route::middleware(['auth'])->get('/dashboard/profile', [ProfileController::class, 'editSettings'])->name('dashboard.profile');
|
||||
|
||||
// Keep legacy `/user` as a permanent redirect to the canonical dashboard path.
|
||||
Route::middleware(['auth'])->match(['get','post'], '/user', function () {
|
||||
return redirect()->route('dashboard.profile', [], 301);
|
||||
})->name('legacy.user.redirect');
|
||||
|
||||
Route::get('/today-in-history', [TodayInHistoryController::class, 'index'])->name('legacy.today_in_history');
|
||||
Route::get('/today-downloads', [TodayDownloadsController::class, 'index'])->name('legacy.today_downloads');
|
||||
|
||||
Route::get('/monthly-commentators', [MonthlyCommentatorsController::class, 'index'])->name('legacy.monthly_commentators');
|
||||
Route::get('/members', [MembersController::class, 'index'])->name('legacy.members');
|
||||
Route::get('/latest', [LatestController::class, 'index'])->name('legacy.latest');
|
||||
Route::get('/latest-comments', [LatestCommentsController::class, 'index'])->name('legacy.latest_comments');
|
||||
// /interviews → 301 redirect to canonical /stories
|
||||
Route::get('/interviews', function () {
|
||||
return redirect('/stories', 301);
|
||||
})->name('legacy.interviews');
|
||||
|
||||
Route::get('/authors/top', [\App\Http\Controllers\User\TopAuthorsController::class, 'index'])->name('authors.top');
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/statistics', [StatisticsController::class, 'index'])->name('legacy.statistics');
|
||||
Route::middleware(['auth', 'creator.access'])->prefix('creator')->name('creator.')->group(function () {
|
||||
Route::get('/artworks', fn () => redirect()->route('dashboard.artworks.index'))->name('artworks');
|
||||
Route::get('/analytics', fn () => redirect()->route('studio.analytics'))->name('analytics');
|
||||
});
|
||||
|
||||
Route::get('/dashboard', function () {
|
||||
return view('dashboard');
|
||||
})->middleware(['auth', 'verified'])->name('dashboard');
|
||||
|
||||
Route::middleware(['auth', \App\Http\Middleware\NoIndexDashboard::class])->prefix('dashboard')->name('dashboard.')->group(function () {
|
||||
Route::get('/artworks', [DashboardArtworkController::class, 'index'])->name('artworks.index');
|
||||
Route::get('/artworks', [DashboardArtworkController::class, 'index'])->name('artworks.index');
|
||||
Route::get('/artworks/{id}/edit', [DashboardArtworkController::class, 'edit'])->whereNumber('id')->name('artworks.edit');
|
||||
Route::put('/artworks/{id}', [DashboardArtworkController::class, 'update'])->whereNumber('id')->name('artworks.update');
|
||||
Route::delete('/artworks/{id}', [DashboardArtworkController::class, 'destroy'])->whereNumber('id')->name('artworks.destroy');
|
||||
// Favorites (user's own favourites)
|
||||
Route::get('/favorites', [\App\Http\Controllers\Dashboard\FavoriteController::class, 'index'])->name('favorites');
|
||||
Route::put('/artworks/{id}', [DashboardArtworkController::class, 'update'])->whereNumber('id')->name('artworks.update');
|
||||
Route::delete('/artworks/{id}', [DashboardArtworkController::class, 'destroy'])->whereNumber('id')->name('artworks.destroy');
|
||||
|
||||
Route::get('/favorites', [\App\Http\Controllers\Dashboard\FavoriteController::class, 'index'])->name('favorites');
|
||||
Route::delete('/favorites/{artwork}', [\App\Http\Controllers\Dashboard\FavoriteController::class, 'destroy'])->name('favorites.destroy');
|
||||
// Followers / Following / Comments (dashboard)
|
||||
|
||||
Route::get('/followers', [\App\Http\Controllers\Dashboard\FollowerController::class, 'index'])->name('followers');
|
||||
Route::get('/following', [\App\Http\Controllers\Dashboard\FollowingController::class, 'index'])->name('following');
|
||||
Route::get('/comments', [\App\Http\Controllers\Dashboard\CommentController::class, 'index'])->name('comments');
|
||||
// Gallery (user uploads)
|
||||
Route::get('/gallery', [\App\Http\Controllers\Dashboard\DashboardGalleryController::class, 'index'])->name('gallery');
|
||||
// Awards received on the user's own artworks
|
||||
Route::get('/awards', [\App\Http\Controllers\Dashboard\DashboardAwardsController::class, 'index'])->name('awards');
|
||||
Route::get('/comments', [\App\Http\Controllers\Dashboard\CommentController::class, 'index'])->name('comments');
|
||||
Route::get('/gallery', [\App\Http\Controllers\Dashboard\DashboardGalleryController::class, 'index'])->name('gallery');
|
||||
Route::get('/awards', [\App\Http\Controllers\Dashboard\DashboardAwardsController::class, 'index'])->name('awards');
|
||||
});
|
||||
|
||||
// ── Studio Pro (Creator Artwork Manager) ────────────────────────────────────
|
||||
use App\Http\Controllers\Studio\StudioController;
|
||||
// Canonical dashboard profile / settings
|
||||
Route::middleware(['auth'])->get('/dashboard/profile', [ProfileController::class, 'editSettings'])->name('dashboard.profile');
|
||||
Route::middleware(['auth'])->get('/settings/profile', [ProfileController::class, 'editSettings'])->name('settings.profile');
|
||||
|
||||
// ── STUDIO Pro (/studio/*) ────────────────────────────────────────────────────
|
||||
Route::middleware(['auth', 'ensure.onboarding.complete'])->prefix('studio')->name('studio.')->group(function () {
|
||||
Route::get('/', [StudioController::class, 'index'])->name('index');
|
||||
Route::get('/artworks', [StudioController::class, 'artworks'])->name('artworks');
|
||||
Route::get('/artworks/drafts', [StudioController::class, 'drafts'])->name('drafts');
|
||||
Route::get('/artworks/archived', [StudioController::class, 'archived'])->name('archived');
|
||||
Route::get('/artworks/{id}/edit', [StudioController::class, 'edit'])->whereNumber('id')->name('artworks.edit');
|
||||
Route::get('/artworks/{id}/analytics', [StudioController::class, 'analytics'])->whereNumber('id')->name('artworks.analytics');
|
||||
Route::get('/analytics', [StudioController::class, 'analyticsOverview'])->name('analytics');
|
||||
Route::get('/', [StudioController::class, 'index'])->name('index');
|
||||
Route::get('/artworks', [StudioController::class, 'artworks'])->name('artworks');
|
||||
Route::get('/artworks/drafts', [StudioController::class, 'drafts'])->name('drafts');
|
||||
Route::get('/artworks/archived', [StudioController::class, 'archived'])->name('archived');
|
||||
Route::get('/artworks/{id}/edit', [StudioController::class, 'edit'])->whereNumber('id')->name('artworks.edit');
|
||||
Route::get('/artworks/{id}/analytics', [StudioController::class, 'analytics'])->whereNumber('id')->name('artworks.analytics');
|
||||
Route::get('/analytics', [StudioController::class, 'analyticsOverview'])->name('analytics');
|
||||
});
|
||||
|
||||
// ── SETTINGS / PROFILE EDIT ───────────────────────────────────────────────────
|
||||
Route::middleware(['auth', 'normalize.username', 'ensure.onboarding.complete'])->group(function () {
|
||||
// Redirect legacy `/profile` edit path to canonical dashboard profile route.
|
||||
Route::get('/profile', function () {
|
||||
return redirect()->route('dashboard.profile', [], 301);
|
||||
})->name('legacy.profile.redirect');
|
||||
// Backwards-compatible settings path used by some layouts/links
|
||||
Route::get('/settings', [ProfileController::class, 'edit'])->name('settings');
|
||||
// Backwards-compatible route name expected by some packages/views
|
||||
Route::get('/profile', fn () => redirect()->route('dashboard.profile', [], 301))->name('legacy.profile.redirect');
|
||||
Route::get('/settings', [ProfileController::class, 'edit'])->name('settings');
|
||||
Route::get('/profile/edit', [ProfileController::class, 'edit'])->name('profile.edit');
|
||||
Route::match(['post','put','patch'], '/profile', [ProfileController::class, 'update'])->name('profile.update');
|
||||
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
|
||||
// Password change endpoint (accepts POST or PUT from legacy and new forms)
|
||||
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
|
||||
Route::match(['post', 'put'], '/profile/password', [ProfileController::class, 'password'])->name('profile.password');
|
||||
// Avatar upload (backend only) - processes and stores avatars
|
||||
Route::post('/avatar/upload', [AvatarController::class, 'upload'])->middleware('throttle:20,1')->name('avatar.upload');
|
||||
|
||||
Route::post('/settings/profile/update', [ProfileController::class, 'updateProfileSection'])->name('settings.profile.update');
|
||||
Route::post('/settings/account/username', [ProfileController::class, 'updateUsername'])->name('settings.account.username');
|
||||
Route::post('/settings/account/update', [ProfileController::class, 'updateAccountSection'])->name('settings.account.update');
|
||||
Route::post('/settings/email/request', [ProfileController::class, 'requestEmailChange'])
|
||||
->middleware('throttle:email-change-request')
|
||||
->name('settings.email.request');
|
||||
Route::post('/settings/email/verify', [ProfileController::class, 'verifyEmailChange'])
|
||||
->middleware('throttle:10,1')
|
||||
->name('settings.email.verify');
|
||||
Route::post('/settings/personal/update', [ProfileController::class, 'updatePersonalSection'])->name('settings.personal.update');
|
||||
Route::post('/settings/notifications/update', [ProfileController::class, 'updateNotificationsSection'])->name('settings.notifications.update');
|
||||
Route::post('/settings/security/password', [ProfileController::class, 'updateSecurityPassword'])->name('settings.security.password');
|
||||
});
|
||||
|
||||
// ── UPLOAD ────────────────────────────────────────────────────────────────────
|
||||
Route::middleware(['auth', 'ensure.onboarding.complete'])->group(function () {
|
||||
Route::get('/upload', function () {
|
||||
$contentTypes = ContentType::with(['rootCategories.children'])->get()->map(function ($ct) {
|
||||
@@ -462,120 +348,104 @@ Route::middleware(['auth', 'ensure.onboarding.complete'])->group(function () {
|
||||
})->whereUuid('id')->name('upload.draft');
|
||||
});
|
||||
|
||||
|
||||
|
||||
// ── AUTH ──────────────────────────────────────────────────────────────────────
|
||||
require __DIR__.'/auth.php';
|
||||
|
||||
Route::get('/search', [\App\Http\Controllers\Web\SearchController::class, 'index'])
|
||||
->name('search');
|
||||
// ── LEGACY ROUTES ─────────────────────────────────────────────────────────────
|
||||
require __DIR__.'/legacy.php';
|
||||
|
||||
// Public instructions page used by OAuth providers for user data deletion requests
|
||||
Route::view('/data-deletion', 'privacy.data-deletion')
|
||||
->name('privacy.data_deletion');
|
||||
|
||||
Route::get('/tag/{tag:slug}', [\App\Http\Controllers\Web\TagController::class, 'show'])
|
||||
->where('tag', '[a-z0-9\-]+')
|
||||
->name('tags.show');
|
||||
// ── SEARCH ────────────────────────────────────────────────────────────────────
|
||||
Route::get('/search', [\App\Http\Controllers\Web\SearchController::class, 'index'])->name('search');
|
||||
|
||||
// ── MISC ──────────────────────────────────────────────────────────────────────
|
||||
Route::view('/data-deletion', 'privacy.data-deletion')->name('privacy.data_deletion');
|
||||
Route::view('/blank', 'blank')->name('blank');
|
||||
|
||||
// Bind the artwork route parameter to a model if it exists, otherwise return null
|
||||
use App\Models\Artwork;
|
||||
Route::bind('artwork', function ($value) {
|
||||
// firstOrFail triggers ModelNotFoundException → caught by exception handler
|
||||
// which renders contextual artwork-not-found or generic 404 view.
|
||||
return Artwork::where('slug', $value)->firstOrFail();
|
||||
});
|
||||
|
||||
// Universal content router: handles content-type roots, nested categories and artwork slugs.
|
||||
// Keep the explicit /photography route above (if present) so the legacy controller can continue
|
||||
// to serve photography's root page. This catch-all route delegates to a controller that
|
||||
// will forward to the appropriate existing controller (artwork or category handlers).
|
||||
// Provide a named route alias for legacy artwork URL generation used in tests.
|
||||
Route::get('/{contentTypeSlug}/{categoryPath}/{artwork}', [\App\Http\Controllers\Web\BrowseGalleryController::class, 'showArtwork'])
|
||||
->where('contentTypeSlug', 'photography|wallpapers|skins|other')
|
||||
->where('categoryPath', '[^/]+(?:/[^/]+)*')
|
||||
->name('artworks.show');
|
||||
|
||||
Route::get('/{contentTypeSlug}/{path?}', [\App\Http\Controllers\Web\BrowseGalleryController::class, 'content'])
|
||||
->where('contentTypeSlug', 'photography|wallpapers|skins|other')
|
||||
->where('path', '.*')
|
||||
->name('content.route');
|
||||
|
||||
|
||||
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/manage', [ManageController::class, 'index'])->name('manage');
|
||||
Route::get('/manage/edit/{id}', [ManageController::class, 'edit'])->name('manage.edit');
|
||||
Route::post('/manage/update/{id}', [ManageController::class, 'update'])->name('manage.update');
|
||||
Route::post('/manage/delete/{id}', [ManageController::class, 'destroy'])->name('manage.destroy');
|
||||
});
|
||||
|
||||
// Admin routes for artworks (separated from public routes)
|
||||
// ── ADMIN ─────────────────────────────────────────────────────────────────────
|
||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
||||
Route::get('uploads/moderation', function () {
|
||||
return Inertia::render('Admin/UploadQueue');
|
||||
})->middleware('admin.moderation')->name('uploads.moderation');
|
||||
Route::get('uploads/moderation', fn () => Inertia::render('Admin/UploadQueue'))
|
||||
->middleware('admin.moderation')
|
||||
->name('uploads.moderation');
|
||||
|
||||
Route::get('usernames/moderation', function () {
|
||||
return Inertia::render('Admin/UsernameQueue');
|
||||
})->middleware('admin.moderation')->name('usernames.moderation');
|
||||
Route::get('usernames/moderation', fn () => Inertia::render('Admin/UsernameQueue'))
|
||||
->middleware('admin.moderation')
|
||||
->name('usernames.moderation');
|
||||
|
||||
Route::resource('artworks', \App\Http\Controllers\Admin\ArtworkController::class)->except(['show']);
|
||||
Route::get('reports', function () {
|
||||
return view('admin.reports.queue');
|
||||
})->middleware('admin.moderation')->name('reports.queue');
|
||||
|
||||
// ── Early Growth System admin panel (§14) ─────────────────────────────
|
||||
Route::get('reports', fn () => view('admin.reports.queue'))
|
||||
->middleware('admin.moderation')
|
||||
->name('reports.queue');
|
||||
|
||||
Route::middleware('admin.moderation')->prefix('early-growth')->name('early-growth.')->group(function () {
|
||||
Route::get('/', [\App\Http\Controllers\Admin\EarlyGrowthAdminController::class, 'index'])->name('index');
|
||||
Route::get('/', [\App\Http\Controllers\Admin\EarlyGrowthAdminController::class, 'index'])->name('index');
|
||||
Route::delete('/cache', [\App\Http\Controllers\Admin\EarlyGrowthAdminController::class, 'flushCache'])->name('cache.flush');
|
||||
Route::get('/status', [\App\Http\Controllers\Admin\EarlyGrowthAdminController::class, 'status'])->name('status');
|
||||
Route::get('/status', [\App\Http\Controllers\Admin\EarlyGrowthAdminController::class, 'status'])->name('status');
|
||||
});
|
||||
|
||||
Route::middleware('admin.moderation')->prefix('stories')->name('stories.')->group(function () {
|
||||
Route::get('/review', [\App\Http\Controllers\Admin\StoryAdminController::class, 'review'])->name('review');
|
||||
Route::get('/', [\App\Http\Controllers\Admin\StoryAdminController::class, 'index'])->name('index');
|
||||
Route::get('/create', [\App\Http\Controllers\Admin\StoryAdminController::class, 'create'])->name('create');
|
||||
Route::post('/', [\App\Http\Controllers\Admin\StoryAdminController::class, 'store'])->name('store');
|
||||
Route::get('/{story}', [\App\Http\Controllers\Admin\StoryAdminController::class, 'show'])->name('show');
|
||||
Route::post('/{story}/approve', [\App\Http\Controllers\Admin\StoryAdminController::class, 'approve'])->name('approve');
|
||||
Route::post('/{story}/reject', [\App\Http\Controllers\Admin\StoryAdminController::class, 'reject'])->name('reject');
|
||||
Route::get('/{story}/edit', [\App\Http\Controllers\Admin\StoryAdminController::class, 'edit'])->name('edit');
|
||||
Route::put('/{story}', [\App\Http\Controllers\Admin\StoryAdminController::class, 'update'])->name('update');
|
||||
Route::delete('/{story}', [\App\Http\Controllers\Admin\StoryAdminController::class, 'destroy'])->name('destroy');
|
||||
Route::post('/{story}/publish', [\App\Http\Controllers\Admin\StoryAdminController::class, 'publish'])->name('publish');
|
||||
Route::get('/moderation/comments', [\App\Http\Controllers\Admin\StoryAdminController::class, 'moderateComments'])->name('comments.moderation');
|
||||
});
|
||||
});
|
||||
|
||||
// ── MESSAGES ──────────────────────────────────────────────────────────────────
|
||||
Route::middleware(['auth', 'ensure.onboarding.complete'])
|
||||
->get('/messages/attachments/{id}', [\App\Http\Controllers\Api\Messaging\AttachmentController::class, 'show'])
|
||||
->whereNumber('id')
|
||||
->name('messages.attachments.show');
|
||||
|
||||
// ── Messages ──────────────────────────────────────────────────────────────────
|
||||
Route::middleware(['auth', 'ensure.onboarding.complete'])->prefix('messages')->name('messages.')->group(function () {
|
||||
Route::get('/', [\App\Http\Controllers\Messaging\MessagesPageController::class, 'index'])->name('index');
|
||||
Route::get('/', [\App\Http\Controllers\Messaging\MessagesPageController::class, 'index'])->name('index');
|
||||
Route::get('/{id}', [\App\Http\Controllers\Messaging\MessagesPageController::class, 'show'])->whereNumber('id')->name('show');
|
||||
});
|
||||
|
||||
// ── Community Activity Feed ───────────────────────────────────────────────────
|
||||
// ── COMMUNITY ACTIVITY ────────────────────────────────────────────────────────
|
||||
Route::get('/community/activity', [\App\Http\Controllers\Web\CommunityActivityController::class, 'index'])
|
||||
->name('community.activity');
|
||||
|
||||
// ── Posts / Following Feed ────────────────────────────────────────────────────
|
||||
// /feed/following – Inertia page for the ranked, diversified following feed
|
||||
// ── FEEDS ─────────────────────────────────────────────────────────────────────
|
||||
Route::middleware(['auth', 'ensure.onboarding.complete'])
|
||||
->get('/feed/following', [\App\Http\Controllers\Web\Posts\FollowingFeedController::class, 'index'])
|
||||
->name('feed.following');
|
||||
|
||||
// ── Feed 2.0: Trending Feed ───────────────────────────────────────────────────
|
||||
Route::get('/feed/trending', [\App\Http\Controllers\Web\Posts\TrendingFeedController::class, 'index'])
|
||||
->name('feed.trending');
|
||||
|
||||
// ── Feed 2.0: Hashtag Feed ────────────────────────────────────────────────────
|
||||
Route::get('/tags/{tag}', [\App\Http\Controllers\Web\Posts\HashtagFeedController::class, 'index'])
|
||||
->where('tag', '[A-Za-z][A-Za-z0-9_]{1,63}')
|
||||
->name('feed.hashtag');
|
||||
|
||||
// ── Feed 2.0: Saved Posts ─────────────────────────────────────────────────────
|
||||
Route::middleware(['auth'])
|
||||
->get('/feed/saved', [\App\Http\Controllers\Web\Posts\SavedFeedController::class, 'index'])
|
||||
->name('feed.saved');
|
||||
|
||||
// ── Feed 2.0: Post Search ─────────────────────────────────────────────────────
|
||||
Route::get('/feed/search', [\App\Http\Controllers\Web\Posts\SearchFeedController::class, 'index'])
|
||||
->name('feed.search');
|
||||
|
||||
// ── Fallback: Generic 404 ─────────────────────────────────────────────────────
|
||||
// Must be last. Catches any URL not matched by a registered route.
|
||||
// ── CONTENT BROWSER (artwork / category universal router) ─────────────────────
|
||||
// Bind the artwork route parameter to the Artwork model by slug.
|
||||
Route::bind('artwork', function ($value) {
|
||||
return Artwork::where('slug', $value)->firstOrFail();
|
||||
});
|
||||
|
||||
Route::get('/{contentTypeSlug}/{categoryPath}/{artwork}', [BrowseGalleryController::class, 'showArtwork'])
|
||||
->where('contentTypeSlug', 'photography|wallpapers|skins|other')
|
||||
->where('categoryPath', '[^/]+(?:/[^/]+)*')
|
||||
->name('artworks.show');
|
||||
|
||||
Route::get('/{contentTypeSlug}/{path?}', [BrowseGalleryController::class, 'content'])
|
||||
->where('contentTypeSlug', 'photography|wallpapers|skins|other')
|
||||
->where('path', '.*')
|
||||
->name('content.route');
|
||||
|
||||
// ── FALLBACK 404 — must be last ───────────────────────────────────────────────
|
||||
Route::fallback(function (\Illuminate\Http\Request $request) {
|
||||
return app(\App\Http\Controllers\Web\ErrorController::class)->handleNotFound($request);
|
||||
})->name('404.fallback');
|
||||
|
||||
Reference in New Issue
Block a user