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:
2026-10-17 20:46:15 -03:00
commit 79d12fa2f4
128 changed files with 17053 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\AiAgent;
use App\Models\Store;
use Illuminate\Http\JsonResponse;
/**
* Aggregated city snapshot consumed by the Three.js frontend.
*
* Provides a single lightweight payload describing the static and dynamic
* elements of the virtual city (stores and AI agents with coordinates).
*/
class CityController extends Controller
{
/**
* Return the current world state used to bootstrap the 3D scene.
*/
public function world(): JsonResponse
{
$stores = Store::query()
->get(['id', 'name', 'type', 'pos_x', 'pos_y', 'pos_z', 'width', 'height', 'depth', 'is_open'])
->map(fn (Store $store): array => [
'id' => $store->id,
'name' => $store->name,
'type' => $store->type,
'position' => [(float) $store->pos_x, (float) $store->pos_y, (float) $store->pos_z],
'size' => [(float) $store->width, (float) $store->height, (float) $store->depth],
'is_open' => $store->is_open,
]);
$agents = AiAgent::query()
->where('status', '!=', 'paused')
->get(['id', 'name', 'type', 'status', 'pos_x', 'pos_y', 'pos_z', 'rotation_y'])
->map(fn (AiAgent $agent): array => [
'id' => $agent->id,
'name' => $agent->name,
'type' => $agent->type,
'status' => $agent->status,
'position' => [(float) $agent->pos_x, (float) $agent->pos_y, (float) $agent->pos_z],
'rotation_y' => (float) $agent->rotation_y,
]);
return response()->json([
'generated_at' => now()->toIso8601String(),
'stores' => $stores,
'agents' => $agents,
]);
}
}