messages implemented
This commit is contained in:
162
routes/api.php
162
routes/api.php
@@ -111,6 +111,9 @@ Route::middleware(['web', 'auth', 'admin.moderation'])->prefix('admin/uploads')-
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'auth', 'admin.moderation'])->prefix('admin/reports')->name('api.admin.reports.')->group(function () {
|
||||
Route::get('queue', [\App\Http\Controllers\Api\Admin\ModerationReportQueueController::class, 'index'])
|
||||
->name('queue');
|
||||
|
||||
Route::get('similar-artworks', [\App\Http\Controllers\Api\Admin\SimilarArtworkReportController::class, 'index'])
|
||||
->name('similar-artworks');
|
||||
|
||||
@@ -166,6 +169,11 @@ Route::middleware(['web', 'throttle:60,1'])->prefix('tags')->name('api.tags.')->
|
||||
Route::get('popular', [\App\Http\Controllers\Api\TagController::class, 'popular'])->name('popular');
|
||||
});
|
||||
|
||||
// User/creator search (public, supports @mention prefix)
|
||||
Route::middleware(['web', 'throttle:60,1'])
|
||||
->get('search/users', \App\Http\Controllers\Api\Search\UserSearchController::class)
|
||||
->name('api.search.users');
|
||||
|
||||
Route::middleware(['web', 'auth', 'normalize.username'])->prefix('artworks')->name('api.artworks.tags.')->group(function () {
|
||||
Route::get('{id}/tags', [\App\Http\Controllers\Api\ArtworkTagController::class, 'index'])->whereNumber('id')->name('index');
|
||||
Route::post('{id}/tags', [\App\Http\Controllers\Api\ArtworkTagController::class, 'store'])->whereNumber('id')->name('store');
|
||||
@@ -183,6 +191,12 @@ Route::middleware(['web', 'auth', 'normalize.username', 'throttle:20,1'])
|
||||
Route::delete('{id}/award', [\App\Http\Controllers\Api\ArtworkAwardController::class, 'destroy']) ->whereNumber('id')->name('destroy');
|
||||
});
|
||||
|
||||
// ── Latest Comments feed ──────────────────────────────────────────────────────
|
||||
// GET /api/comments/latest?type=all|following|mine&page=N
|
||||
Route::middleware(['web', 'throttle:60,1'])
|
||||
->get('comments/latest', [\App\Http\Controllers\Api\LatestCommentsApiController::class, 'index'])
|
||||
->name('api.comments.latest');
|
||||
|
||||
Route::middleware(['web'])
|
||||
->prefix('artworks')
|
||||
->name('api.artworks.awards.show.')
|
||||
@@ -207,3 +221,151 @@ Route::middleware(['web', 'auth', 'normalize.username'])->group(function () {
|
||||
->whereNumber('id')
|
||||
->name('api.users.follow');
|
||||
});
|
||||
|
||||
// ── Comment CRUD ──────────────────────────────────────────────────────────────
|
||||
// GET /api/artworks/{id}/comments list comments (public)
|
||||
// POST /api/artworks/{id}/comments post a comment (auth)
|
||||
// PUT /api/artworks/{id}/comments/{commentId} edit own comment (auth)
|
||||
// DELETE /api/artworks/{id}/comments/{commentId} delete own/admin (auth)
|
||||
|
||||
Route::middleware(['web', 'throttle:60,1'])
|
||||
->get('artworks/{id}/comments', [\App\Http\Controllers\Api\ArtworkCommentController::class, 'index'])
|
||||
->whereNumber('id')
|
||||
->name('api.artworks.comments.index');
|
||||
|
||||
Route::middleware(['web', 'auth', 'normalize.username', 'throttle:30,1'])->group(function () {
|
||||
Route::post('artworks/{id}/comments', [\App\Http\Controllers\Api\ArtworkCommentController::class, 'store'])
|
||||
->whereNumber('id')
|
||||
->name('api.artworks.comments.store');
|
||||
|
||||
Route::put('artworks/{id}/comments/{commentId}', [\App\Http\Controllers\Api\ArtworkCommentController::class, 'update'])
|
||||
->whereNumber(['id', 'commentId'])
|
||||
->name('api.artworks.comments.update');
|
||||
|
||||
Route::delete('artworks/{id}/comments/{commentId}', [\App\Http\Controllers\Api\ArtworkCommentController::class, 'destroy'])
|
||||
->whereNumber(['id', 'commentId'])
|
||||
->name('api.artworks.comments.destroy');
|
||||
});
|
||||
|
||||
// ── Reactions ─────────────────────────────────────────────────────────────────
|
||||
// GET /api/artworks/{id}/reactions list artwork reaction totals (public)
|
||||
// POST /api/artworks/{id}/reactions toggle artwork reaction (auth)
|
||||
// GET /api/comments/{id}/reactions list comment reaction totals (public)
|
||||
// POST /api/comments/{id}/reactions toggle comment reaction (auth)
|
||||
|
||||
Route::middleware(['web', 'throttle:60,1'])->group(function () {
|
||||
Route::get('artworks/{id}/reactions', [\App\Http\Controllers\Api\ReactionController::class, 'artworkReactions'])
|
||||
->whereNumber('id')
|
||||
->name('api.artworks.reactions.index');
|
||||
|
||||
Route::get('comments/{id}/reactions', [\App\Http\Controllers\Api\ReactionController::class, 'commentReactions'])
|
||||
->whereNumber('id')
|
||||
->name('api.comments.reactions.index');
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'auth', 'normalize.username', 'throttle:60,1'])->group(function () {
|
||||
Route::post('artworks/{id}/reactions', [\App\Http\Controllers\Api\ReactionController::class, 'toggleArtworkReaction'])
|
||||
->whereNumber('id')
|
||||
->name('api.artworks.reactions.toggle');
|
||||
|
||||
Route::post('comments/{id}/reactions', [\App\Http\Controllers\Api\ReactionController::class, 'toggleCommentReaction'])
|
||||
->whereNumber('id')
|
||||
->name('api.comments.reactions.toggle');
|
||||
});
|
||||
|
||||
// ── Follow system ─────────────────────────────────────────────────────────────
|
||||
// POST /api/user/{username}/follow → follow a user
|
||||
// DELETE /api/user/{username}/follow → unfollow a user
|
||||
// GET /api/user/{username}/followers → paginated followers (public)
|
||||
// GET /api/user/{username}/following → paginated following (public)
|
||||
Route::middleware(['web', 'throttle:60,1'])
|
||||
->prefix('user')
|
||||
->name('api.user.follow.')
|
||||
->group(function () {
|
||||
// Public: list followers / following
|
||||
Route::get('{username}/followers', [\App\Http\Controllers\Api\FollowController::class, 'followers'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('followers');
|
||||
|
||||
Route::get('{username}/following', [\App\Http\Controllers\Api\FollowController::class, 'following'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('following');
|
||||
|
||||
// Auth-required: follow / unfollow
|
||||
Route::middleware(['auth', 'normalize.username'])->group(function () {
|
||||
Route::post('{username}/follow', [\App\Http\Controllers\Api\FollowController::class, 'follow'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('follow');
|
||||
|
||||
Route::delete('{username}/follow', [\App\Http\Controllers\Api\FollowController::class, 'unfollow'])
|
||||
->where('username', '[A-Za-z0-9_-]{3,20}')
|
||||
->name('unfollow');
|
||||
});
|
||||
});
|
||||
|
||||
// ── Messaging ────────────────────────────────────────────────────────────────
|
||||
// GET /api/messages/conversations → list conversations
|
||||
// POST /api/messages/conversation → create conversation
|
||||
// GET /api/messages/conversation/{id} → show conversation
|
||||
// GET /api/messages/{conversation_id} → paginated messages
|
||||
// POST /api/messages/{conversation_id} → send message
|
||||
// POST /api/messages/{conversation_id}/read → mark as read
|
||||
// POST /api/messages/{conversation_id}/archive → toggle archive
|
||||
// POST /api/messages/{conversation_id}/mute → toggle mute
|
||||
// DELETE /api/messages/{conversation_id}/leave → leave conversation
|
||||
// POST /api/messages/{conversation_id}/add-user → add user (admin)
|
||||
// DELETE /api/messages/{conversation_id}/remove-user → remove user (admin)
|
||||
// POST /api/messages/{conversation_id}/rename → rename group (admin)
|
||||
// POST /api/messages/{conversation_id}/{message_id}/react → add reaction
|
||||
// DELETE /api/messages/{conversation_id}/{message_id}/react → remove reaction
|
||||
// DELETE /api/messages/message/{message_id} → soft-delete message
|
||||
Route::middleware(['web', 'auth', 'normalize.username', 'throttle:60,1'])
|
||||
->prefix('messages')
|
||||
->name('api.messages.')
|
||||
->group(function () {
|
||||
Route::get('settings', [\App\Http\Controllers\Api\Messaging\MessagingSettingsController::class, 'show'])->name('settings.show');
|
||||
Route::patch('settings', [\App\Http\Controllers\Api\Messaging\MessagingSettingsController::class, 'update'])->name('settings.update');
|
||||
|
||||
Route::get('conversations', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'index'])->name('conversations.index');
|
||||
Route::post('conversation', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'store'])->middleware('throttle:messages-send')->name('conversations.store');
|
||||
Route::get('conversation/{id}', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'show'])->whereNumber('id')->name('conversations.show');
|
||||
|
||||
Route::post('{conversation_id}/read', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'markRead'])->whereNumber('conversation_id')->name('read');
|
||||
Route::post('{conversation_id}/archive', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'archive'])->whereNumber('conversation_id')->name('archive');
|
||||
Route::post('{conversation_id}/mute', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'mute'])->whereNumber('conversation_id')->name('mute');
|
||||
Route::post('{conversation_id}/pin', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'pin'])->whereNumber('conversation_id')->name('pin');
|
||||
Route::post('{conversation_id}/unpin', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'unpin'])->whereNumber('conversation_id')->name('unpin');
|
||||
Route::delete('{conversation_id}/leave', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'leave'])->whereNumber('conversation_id')->name('leave');
|
||||
Route::post('{conversation_id}/add-user', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'addUser'])->whereNumber('conversation_id')->name('add-user');
|
||||
Route::delete('{conversation_id}/remove-user', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'removeUser'])->whereNumber('conversation_id')->name('remove-user');
|
||||
Route::post('{conversation_id}/rename', [\App\Http\Controllers\Api\Messaging\ConversationController::class, 'rename'])->whereNumber('conversation_id')->name('rename');
|
||||
|
||||
Route::get('search', [\App\Http\Controllers\Api\Messaging\MessageSearchController::class, 'index'])->name('search.index');
|
||||
Route::post('search/rebuild', [\App\Http\Controllers\Api\Messaging\MessageSearchController::class, 'rebuild'])->name('search.rebuild');
|
||||
|
||||
Route::get('{conversation_id}', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'index'])->whereNumber('conversation_id')->name('messages.index');
|
||||
Route::post('{conversation_id}', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'store'])->middleware('throttle:messages-send')->whereNumber('conversation_id')->name('messages.store');
|
||||
|
||||
Route::post('{conversation_id}/typing', [\App\Http\Controllers\Api\Messaging\TypingController::class, 'start'])->whereNumber('conversation_id')->name('typing.start');
|
||||
Route::post('{conversation_id}/typing/stop', [\App\Http\Controllers\Api\Messaging\TypingController::class, 'stop'])->whereNumber('conversation_id')->name('typing.stop');
|
||||
Route::get('{conversation_id}/typing', [\App\Http\Controllers\Api\Messaging\TypingController::class, 'index'])->whereNumber('conversation_id')->name('typing.index');
|
||||
|
||||
Route::post('{conversation_id}/{message_id}/react', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'react'])->whereNumber(['conversation_id', 'message_id'])->name('react');
|
||||
Route::delete('{conversation_id}/{message_id}/react', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'unreact'])->whereNumber(['conversation_id', 'message_id'])->name('unreact');
|
||||
|
||||
Route::post('{message_id}/reactions', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'reactByMessage'])
|
||||
->middleware('throttle:messages-react')
|
||||
->whereNumber('message_id')
|
||||
->name('messages.reactions.toggle');
|
||||
Route::delete('{message_id}/reactions', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'unreactByMessage'])
|
||||
->middleware('throttle:messages-react')
|
||||
->whereNumber('message_id')
|
||||
->name('messages.reactions.delete');
|
||||
|
||||
Route::patch('message/{message_id}', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'update'])->whereNumber('message_id')->name('messages.update');
|
||||
Route::delete('message/{message_id}', [\App\Http\Controllers\Api\Messaging\MessageController::class, 'destroy'])->whereNumber('message_id')->name('messages.destroy');
|
||||
});
|
||||
|
||||
Route::middleware(['web', 'auth', 'normalize.username', 'throttle:60,1'])
|
||||
->post('reports', [\App\Http\Controllers\Api\ReportController::class, 'store'])
|
||||
->name('api.reports.store');
|
||||
|
||||
@@ -32,8 +32,40 @@ use App\Http\Controllers\User\ReceivedCommentsController;
|
||||
use App\Http\Controllers\Web\BrowseCategoriesController;
|
||||
use App\Http\Controllers\Web\GalleryController;
|
||||
use App\Http\Controllers\Web\BrowseGalleryController;
|
||||
use App\Http\Controllers\Web\DiscoverController;
|
||||
use Inertia\Inertia;
|
||||
|
||||
// ── DISCOVER routes (/discover/*) ─────────────────────────────────────────────
|
||||
Route::prefix('discover')->name('discover.')->group(function () {
|
||||
Route::get('/trending', [DiscoverController::class, 'trending'])->name('trending');
|
||||
Route::get('/fresh', [DiscoverController::class, 'fresh'])->name('fresh');
|
||||
Route::get('/top-rated', [DiscoverController::class, 'topRated'])->name('top-rated');
|
||||
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');
|
||||
});
|
||||
|
||||
// ── CREATORS routes (/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');
|
||||
});
|
||||
|
||||
// Creator Stories → canonical rename of /interviews
|
||||
Route::get('/stories', [\App\Http\Controllers\Community\InterviewController::class, 'index'])->name('stories');
|
||||
|
||||
// Tags listing page
|
||||
Route::get('/tags', [\App\Http\Controllers\Web\TagController::class, 'index'])->name('tags.index');
|
||||
|
||||
// Following redirect (convenience shortcut for authenticated users)
|
||||
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']);
|
||||
@@ -77,6 +109,11 @@ Route::middleware('ensure.onboarding.complete')->get('/forum.php', function (\Il
|
||||
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');
|
||||
@@ -127,7 +164,10 @@ Route::get('/profile/{username}', [ProfileController::class, 'legacyByUsername']
|
||||
->name('legacy.profile');
|
||||
|
||||
Route::get('/top-favourites', [TopFavouritesController::class, 'index'])->name('legacy.top_favourites');
|
||||
Route::get('/top-authors', [TopAuthorsController::class, 'index'])->name('legacy.top_authors');
|
||||
// /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');
|
||||
@@ -160,7 +200,12 @@ Route::get('/monthly-commentators', [MonthlyCommentatorsController::class, 'inde
|
||||
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');
|
||||
Route::get('/interviews', [InterviewController::class, 'index'])->name('legacy.interviews');
|
||||
// /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');
|
||||
@@ -184,6 +229,8 @@ Route::middleware(['auth', \App\Http\Middleware\NoIndexDashboard::class])->prefi
|
||||
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::middleware(['auth', 'normalize.username', 'ensure.onboarding.complete'])->group(function () {
|
||||
@@ -316,4 +363,18 @@ Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function ()
|
||||
})->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');
|
||||
});
|
||||
|
||||
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('/{id}', [\App\Http\Controllers\Messaging\MessagesPageController::class, 'show'])->whereNumber('id')->name('show');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user