| Server IP : 35.80.110.71 / Your IP : 216.73.216.221 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64 User : ubuntu ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/client-portal-laravel/backup/routes/ |
Upload File : |
<?php
use App\Http\Controllers\Api\ChunkedUploadController;
use App\Http\Controllers\Api\DocumentationController;
use App\Http\Controllers\Api\PresenceController;
use App\Http\Controllers\Api\SyncController;
use App\Http\Controllers\Api\V1;
use App\Http\Controllers\Marketing\ChatbotController;
use App\Http\Controllers\Marketing\FaqController;
use App\Services\RealtimeNotificationService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| API routes for the client portal. All routes are prefixed with /api.
| Version 1 routes are prefixed with /api/v1.
|
*/
// Real-time notification endpoints (used by JavaScript)
// Uses 'web' middleware for session-based auth from browser
Route::middleware(['web', 'auth'])->group(function () {
Route::get('notifications', function (Request $request) {
$service = app(RealtimeNotificationService::class);
return response()->json([
'notifications' => $service->getRecent($request->user()),
'unread_count' => $service->getUnreadCount($request->user()),
]);
});
Route::post('notifications/{id}/read', function (Request $request, string $id) {
$service = app(RealtimeNotificationService::class);
$service->markAsRead($request->user(), $id);
return response()->json(['success' => true]);
});
Route::post('notifications/read-all', function (Request $request) {
$service = app(RealtimeNotificationService::class);
$service->markAllAsRead($request->user());
return response()->json(['success' => true]);
});
// Real-time sync endpoints
Route::prefix('sync')->group(function () {
Route::post('check', [SyncController::class, 'check']);
Route::post('heartbeat', [SyncController::class, 'heartbeat']);
Route::get('online-users', [SyncController::class, 'onlineUsers']);
Route::get('activities', [SyncController::class, 'activities']);
Route::get('user/{userId}/presence', [SyncController::class, 'userPresence']);
Route::get('viewers', [SyncController::class, 'resourceViewers']);
Route::post('start-viewing', [SyncController::class, 'startViewing']);
Route::post('stop-viewing', [SyncController::class, 'stopViewing']);
});
// Presence API endpoints (Plan 100)
Route::prefix('presence')->group(function () {
Route::get('online', [PresenceController::class, 'onlineUsers']);
Route::get('count', [PresenceController::class, 'onlineCount']);
Route::get('{userId}/status', [PresenceController::class, 'userStatus']);
Route::post('heartbeat', [PresenceController::class, 'heartbeat']);
Route::get('viewers/{resourceType}/{resourceId}', [PresenceController::class, 'resourceViewers']);
Route::post('viewing/{resourceType}/{resourceId}/start', [PresenceController::class, 'startViewing']);
Route::post('viewing/{resourceType}/{resourceId}/stop', [PresenceController::class, 'stopViewing']);
});
// Typing indicator endpoints (Plan 100)
Route::prefix('typing')->group(function () {
Route::get('{channelType}/{channelId}', [PresenceController::class, 'getTypingUsers']);
Route::post('{channelType}/{channelId}/start', [PresenceController::class, 'startTyping']);
Route::post('{channelType}/{channelId}/stop', [PresenceController::class, 'stopTyping']);
});
});
// API Documentation
Route::get('docs/spec', [DocumentationController::class, 'spec'])->name('api.docs.spec');
Route::prefix('v1')->name('api.v1.')->middleware(['api.version', 'api.log'])->group(function () {
// Protected routes (Sanctum token auth)
Route::middleware('auth:sanctum')->group(function () {
// Profile
Route::get('me', [V1\ProfileController::class, 'show'])->name('profile');
// Projects
Route::get('projects', [V1\ProjectController::class, 'index'])->name('projects.index');
Route::get('projects/{project}', [V1\ProjectController::class, 'show'])->name('projects.show');
// Project Files
Route::get('projects/{project}/files', [V1\FileController::class, 'index'])->name('projects.files.index');
Route::get('files/{file}/download', [V1\FileController::class, 'download'])->name('files.download');
// Invoices
Route::get('invoices', [V1\InvoiceController::class, 'index'])->name('invoices.index');
Route::get('invoices/{invoice}', [V1\InvoiceController::class, 'show'])->name('invoices.show');
// Tokens (manage own tokens)
Route::post('tokens', [V1\TokenController::class, 'store'])->name('tokens.store');
Route::delete('tokens/{token}', [V1\TokenController::class, 'destroy'])->name('tokens.destroy');
});
});
// Chunked Upload Routes (requires web auth for session)
Route::middleware(['web', 'auth'])->prefix('uploads')->name('api.uploads.')->group(function () {
Route::post('initiate', [ChunkedUploadController::class, 'initiate'])->name('initiate');
Route::post('{uploadId}/chunk', [ChunkedUploadController::class, 'uploadChunk'])->name('chunk');
Route::post('{uploadId}/complete', [ChunkedUploadController::class, 'complete'])->name('complete');
Route::delete('{uploadId}', [ChunkedUploadController::class, 'cancel'])->name('cancel');
Route::get('{uploadId}/status', [ChunkedUploadController::class, 'status'])->name('status');
Route::get('{uploadId}/missing', [ChunkedUploadController::class, 'missingChunks'])->name('missing');
});
// Chatbot API Routes (public, session-based)
Route::middleware('web')->prefix('chatbot')->name('api.chatbot.')->group(function () {
Route::post('start', [ChatbotController::class, 'startConversation'])->name('start');
Route::post('message', [ChatbotController::class, 'sendMessage'])->name('message');
Route::post('faq', [ChatbotController::class, 'selectFaq'])->name('faq');
Route::post('feedback', [ChatbotController::class, 'recordFeedback'])->name('feedback');
Route::get('faqs', [ChatbotController::class, 'getFaqs'])->name('faqs');
Route::post('escalate', [ChatbotController::class, 'escalate'])->name('escalate');
Route::get('status', [ChatbotController::class, 'status'])->name('status');
});
// FAQ API Routes (public)
Route::middleware('web')->prefix('faq')->name('api.faq.')->group(function () {
Route::get('search', [FaqController::class, 'search'])->name('search');
Route::post('feedback', [FaqController::class, 'feedback'])->name('feedback');
});