Files
City10/app/Http/Controllers/Api/StoreController.php
T
marcocosta10000 79d12fa2f4 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
2026-10-17 20:46:15 -03:00

113 lines
3.4 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreRequest as StoreFormRequest;
use App\Models\Store;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* Store management endpoints.
*
* Regular users may list stores and manage the ones they own; admins may
* manage the entire registry. Coordinates follow the 3D city grid.
*/
class StoreController extends Controller
{
/**
* Paginated listing of stores with geographic filtering.
*/
public function index(Request $request): JsonResponse
{
$query = Store::query()->with(['owner:id,name', 'agent:id,name,status'])->orderBy('name');
if ($search = $request->query('search')) {
$query->where('name', 'like', "%{$search}%");
}
if ($type = $request->query('type')) {
$query->where('type', $type);
}
if ($request->boolean('only_open')) {
$query->where('is_open', true);
}
return response()->json($query->paginate((int) $request->query('per_page', 15)));
}
/**
* Return a compact snapshot of all stores for the 3D renderer.
*/
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,
]);
return response()->json(['stores' => $stores]);
}
/**
* Persist a new store.
*/
public function store(StoreFormRequest $request): JsonResponse
{
$data = $request->validated();
// Regular users always own the stores they create.
if (! $request->user()->isAdmin()) {
$data['owner_id'] = $request->user()->id;
}
$store = Store::create($data);
return response()->json($store->load(['owner:id,name', 'agent:id,name']), 201);
}
/**
* Return a single store.
*/
public function show(Store $store): JsonResponse
{
return response()->json($store->load(['owner:id,name,email', 'agent:id,name,type,status']));
}
/**
* Update a store (owner or admin only).
*/
public function update(StoreFormRequest $request, Store $store): JsonResponse
{
if (! $request->user()->isAdmin() && $store->owner_id !== $request->user()->id) {
return response()->json(['message' => __('auth.forbidden')], 403);
}
$store->update($request->validated());
return response()->json($store->fresh()->load(['owner:id,name', 'agent:id,name']));
}
/**
* Delete a store (owner or admin only).
*/
public function destroy(Request $request, Store $store): JsonResponse
{
if (! $request->user()->isAdmin() && $store->owner_id !== $request->user()->id) {
return response()->json(['message' => __('auth.forbidden')], 403);
}
$store->delete();
return response()->json(['message' => __('stores.deleted')]);
}
}