feat: add City10 platform with Laravel 13, AI agents, 3D viewer, and LGPD compliance
Initial commit of the complete City10 virtual city simulation platform. Backend (Laravel 13): - REST API with Sanctum tokens and session-based web authentication - Role-based access control (admin/user) with middleware protection - AI agent CRUD with OpenRouter.ai integration restricted to free models - Store management with 3D coordinates and AI shopkeeper assignment - Versioned legal documents (Terms, Privacy, Cookies) with LGPD audit trail - Math CAPTCHA on public forms and multi-language support (pt_BR, en, es) Frontend: - Responsive Blade templates with Tailwind CSS v4 - Three.js 3D city viewer with SSE chat streaming to AI agents - Admin panel for store and user administration Infrastructure: - MariaDB/MySQL database with comprehensive migrations - Database seeders for demo content and test accounts - PHPUnit test suite and Laravel Pint code styling - Vite build configuration with hot reload
This commit is contained in:
Executable
+91
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Web\Admin\StoreAdminController;
|
||||
use App\Http\Controllers\Web\AuthController;
|
||||
use App\Http\Controllers\Web\ChatController;
|
||||
use App\Http\Controllers\Web\CityViewerController;
|
||||
use App\Http\Controllers\Web\DashboardController;
|
||||
use App\Http\Controllers\Web\LanguageController;
|
||||
use App\Http\Controllers\Web\LegalController;
|
||||
use App\Http\Middleware\EnsureTermsAccepted;
|
||||
use App\Http\Middleware\EnsureUserIsAdmin;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| City10 Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Public pages (welcome, legal documents, language switch) are open to
|
||||
| guests. The dashboard and consent screen require an authenticated web
|
||||
| session and are blocked until the current legal documents are accepted.
|
||||
|
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public pages
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
})->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');
|
||||
|
||||
// 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');
|
||||
|
||||
// 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');
|
||||
});
|
||||
Reference in New Issue
Block a user