name('welcome'); Route::get('/lang', [LanguageController::class, 'switch'])->name('lang.switch'); // Legal documents (public, readable without an account). Route::get('/legal/{type}', [LegalController::class, 'show']) ->whereIn('type', ['terms', 'privacy', 'cookies']) ->name('legal.show'); // --------------------------------------------------------------------------- // Guest authentication // --------------------------------------------------------------------------- Route::middleware('guest')->group(function (): void { Route::get('/login', [AuthController::class, 'showLogin'])->name('login'); Route::post('/login', [AuthController::class, 'login'])->middleware('throttle:10,1'); Route::get('/register', [AuthController::class, 'showRegister'])->name('register'); Route::post('/register', [AuthController::class, 'register'])->middleware('throttle:10,1'); }); // --------------------------------------------------------------------------- // Authenticated area // --------------------------------------------------------------------------- Route::middleware('auth')->group(function (): void { Route::post('/logout', [AuthController::class, 'logout'])->name('logout'); // Pending registration wait screen (reachable before full approval). Route::get('/account/pending', [AccountController::class, 'pending'])->name('account.pending'); // Consent screen is reachable even before terms are accepted (by design). Route::get('/terms/accept', [LegalController::class, 'acceptForm'])->name('terms.accept'); Route::post('/terms/accept', [LegalController::class, 'accept'])->name('terms.accept.store'); Route::get('/terms/history', [LegalController::class, 'history'])->name('terms.history'); // Main platform features (blocked until terms are accepted). Route::middleware(EnsureTermsAccepted::class)->group(function (): void { Route::get('/dashboard', DashboardController::class)->name('dashboard'); // 3D city viewer (Phase 3). Route::get('/city', CityViewerController::class)->name('city.viewer'); Route::get('/city/data', [CityViewerController::class, 'data'])->name('city.data'); // Citizen lifecycle actions inside the world. Route::post('/city/actions/position', [CityActionController::class, 'position'])->name('city.actions.position'); Route::post('/city/actions/{action}', [CityActionController::class, 'handle'])->name('city.actions.handle'); // Character social graph and chat. Route::post('/city/social/{verb}', [CitySocialController::class, 'handle'])->name('city.social.handle'); Route::get('/city/social/inbox', [CitySocialController::class, 'inbox'])->name('city.social.inbox'); Route::post('/city/messages/{character}', [CharacterChatController::class, 'send'])->name('city.messages.send'); Route::get('/city/messages/{character}', [CharacterChatController::class, 'index'])->name('city.messages.index'); // NPC chat (SSE stream + message POST). Route::post('/city/chat/{agent}', [ChatController::class, 'send'])->name('city.chat.send'); Route::get('/city/chat/{agent}/stream', [ChatController::class, 'stream'])->name('city.chat.stream'); }); }); // --------------------------------------------------------------------------- // Admin area (administrator role required, on top of auth + terms) // --------------------------------------------------------------------------- Route::middleware(['auth', EnsureTermsAccepted::class, EnsureUserIsAdmin::class]) ->prefix('admin') ->name('admin.') ->group(function (): void { Route::get('/stores', [StoreAdminController::class, 'index'])->name('stores.index'); Route::get('/stores/create', [StoreAdminController::class, 'create'])->name('stores.create'); Route::post('/stores', [StoreAdminController::class, 'store'])->name('stores.store'); Route::get('/stores/{store}/edit', [StoreAdminController::class, 'edit'])->name('stores.edit'); Route::put('/stores/{store}', [StoreAdminController::class, 'update'])->name('stores.update'); Route::delete('/stores/{store}', [StoreAdminController::class, 'destroy'])->name('stores.destroy'); Route::get('/citizens', [CitizenAdminController::class, 'index'])->name('citizens.index'); Route::post('/citizens/{user}/approve', [CitizenAdminController::class, 'approve'])->name('citizens.approve'); Route::post('/citizens/{user}/ban', [CitizenAdminController::class, 'ban'])->name('citizens.ban'); Route::get('/cities', [CityAdminController::class, 'index'])->name('cities.index'); Route::post('/cities', [CityAdminController::class, 'store'])->name('cities.store'); Route::post('/cities/{city}/expand', [CityAdminController::class, 'expand'])->name('cities.expand'); });