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:
+107
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"Login": "Log in",
|
||||
"Logout": "Log out",
|
||||
"Register": "Register",
|
||||
"Dashboard": "Dashboard",
|
||||
"Email": "Email",
|
||||
"Password": "Password",
|
||||
"Password Confirmation": "Confirm Password",
|
||||
"Remember Me": "Remember me",
|
||||
"Name": "Name",
|
||||
"Save": "Save",
|
||||
"Cancel": "Cancel",
|
||||
"Delete": "Delete",
|
||||
"Edit": "Edit",
|
||||
"Create": "Create",
|
||||
"Search": "Search",
|
||||
"Back": "Back",
|
||||
"Welcome": "Welcome to City10",
|
||||
"auth.failed": "These credentials do not match our records.",
|
||||
"auth.disabled": "This account has been disabled. Please contact an administrator.",
|
||||
"auth.forbidden": "You do not have permission to access this resource.",
|
||||
"auth.logged_out": "You have been logged out successfully.",
|
||||
"auth.throttle": "Too many attempts. Please try again in :seconds seconds.",
|
||||
"legal.accept_required": "You must accept the Terms of Use and Privacy Policy before continuing.",
|
||||
"legal.accepted": "Terms accepted successfully.",
|
||||
"legal.must_accept_terms": "You must accept the Terms of Use.",
|
||||
"legal.must_accept_privacy": "You must accept the Privacy Policy.",
|
||||
"legal.must_accept_cookies": "You must accept the Cookie Policy.",
|
||||
"validation.captcha_required": "Please solve the math verification.",
|
||||
"validation.captcha_failed": "The math verification answer is incorrect.",
|
||||
"validation.model_not_allowed": "The selected AI model is not in the allowed list.",
|
||||
"users.cannot_deactivate_self": "You cannot deactivate your own account.",
|
||||
"users.deactivated": "Account deactivated successfully.",
|
||||
"stores.deleted": "Store deleted successfully.",
|
||||
"agents.deleted": "Agent deleted successfully.",
|
||||
"welcome.tagline": "A living 3D city in your browser, with autonomous AI agents — Mayor, pedestrians, shopkeepers and vehicles — deciding in real time through OpenRouter.ai.",
|
||||
"welcome.card1.title": "🌐 Real-Time 3D City",
|
||||
"welcome.card1.desc": "Explore streets, avenues, bridges, rivers, squares and buildings rendered with Three.js right in your browser.",
|
||||
"welcome.card2.title": "🤖 AI Agents",
|
||||
"welcome.card2.desc": "The mayor, pedestrians and shopkeepers make strategic decisions using free OpenRouter.ai models.",
|
||||
"welcome.card3.title": "🔒 Secure & LGPD",
|
||||
"welcome.card3.desc": "Differentiated authentication (Admin/User), math CAPTCHA and auditable terms consent compliant with Brazilian law.",
|
||||
"welcome.city.title": "🗺️ City Elements (Phase 1)",
|
||||
"welcome.city.desc": "The database already models houses, buildings, schools, parks, squares, traffic lights, streets, avenues, bridges, airports, rivers, industries, stores and shopkeepers — all with 3D coordinates (X, Y, Z) ready for the rendering engine.",
|
||||
"welcome.no_account": "Don't have an account?",
|
||||
"welcome.has_account": "Already have an account?",
|
||||
"nav.city": "3D City",
|
||||
"nav.admin": "Admin",
|
||||
"dashboard.open_viewer": "Open 3D viewer",
|
||||
"dashboard.viewer_desc": "Explore the city ground, stores and agents with a controllable camera.",
|
||||
"dashboard.stores_title": "Stores",
|
||||
"dashboard.stores_desc": "Stores registered in the 3D city.",
|
||||
"dashboard.legal_title": "Consents",
|
||||
"dashboard.consent_history": "View acceptance history",
|
||||
"legal.terms_label": "Terms",
|
||||
"legal.privacy_label": "Privacy",
|
||||
"legal.cookies_label": "Cookies",
|
||||
"admin.stores.title": "Manage Stores",
|
||||
"admin.stores.manage": "Manage stores",
|
||||
"admin.stores.admin_desc": "Create stores and define their 3D position in the city.",
|
||||
"admin.stores.new": "New store",
|
||||
"admin.stores.created": "Store created successfully.",
|
||||
"admin.stores.updated": "Store updated successfully.",
|
||||
"admin.stores.edit_title": "Edit store",
|
||||
"admin.stores.create_title": "New store",
|
||||
"admin.stores.empty": "No stores registered yet.",
|
||||
"admin.stores.position": "3D position in the city",
|
||||
"admin.stores.position_hint": "Click the ground to set X/Z, or type the coordinates. Use controls to rotate/zoom.",
|
||||
"admin.stores.pos_x": "Position X",
|
||||
"admin.stores.pos_y": "Height Y (ground = 0)",
|
||||
"admin.stores.pos_z": "Position Z",
|
||||
"admin.stores.dimensions": "Building dimensions",
|
||||
"admin.stores.width": "Width",
|
||||
"admin.stores.height": "Height",
|
||||
"admin.stores.depth": "Depth",
|
||||
"admin.stores.type": "Store type",
|
||||
"admin.stores.description": "Description",
|
||||
"admin.stores.owner": "Owner (user)",
|
||||
"admin.stores.agent": "AI agent (shopkeeper)",
|
||||
"admin.stores.is_open": "Store open",
|
||||
"admin.stores.no_owner": "No owner",
|
||||
"admin.stores.no_agent": "No agent",
|
||||
"admin.stores.actions": "Actions",
|
||||
"admin.stores.coords": "Coordinates",
|
||||
"admin.stores.confirm_delete": "Delete this store from the city?",
|
||||
"city.title": "3D City Viewer",
|
||||
"city.loading": "Loading city…",
|
||||
"city.error": "Failed to load city data.",
|
||||
"city.stores_count": "stores",
|
||||
"city.agents_count": "agents",
|
||||
"city.hint": "Click the scene to control · WASD to walk · Mouse to look · Esc to exit",
|
||||
"city.refresh": "Reload",
|
||||
"city.selected": "Selected",
|
||||
"city.open": "Open",
|
||||
"city.closed": "Closed",
|
||||
"city.hint_fps": "WASD to walk · Mouse to look · Esc to exit · Click an NPC to chat",
|
||||
"city.position": "POSITION",
|
||||
"city.on_ground": "on ground",
|
||||
"city.triangles": "collision tris",
|
||||
"city.chat_placeholder": "Type your message…",
|
||||
"city.chat_thinking": "thinking…",
|
||||
"city.chat_responding": "responding…",
|
||||
"city.chat_accepted": "Message sent to agent.",
|
||||
"city.chat_error": "Sorry, I can't reply right now. Please try again.",
|
||||
"city.chat_send": "Send",
|
||||
"city.chat_with": "Chatting with"
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"Login": "Iniciar sesión",
|
||||
"Logout": "Cerrar sesión",
|
||||
"Register": "Registrarse",
|
||||
"Dashboard": "Panel",
|
||||
"Email": "Correo electrónico",
|
||||
"Password": "Contraseña",
|
||||
"Password Confirmation": "Confirmar contraseña",
|
||||
"Remember Me": "Recuérdame",
|
||||
"Name": "Nombre",
|
||||
"Save": "Guardar",
|
||||
"Cancel": "Cancelar",
|
||||
"Delete": "Eliminar",
|
||||
"Edit": "Editar",
|
||||
"Create": "Crear",
|
||||
"Search": "Buscar",
|
||||
"Back": "Volver",
|
||||
"Welcome": "Bienvenido a City10",
|
||||
"auth.failed": "Las credenciales proporcionadas no coinciden con nuestros registros.",
|
||||
"auth.disabled": "Esta cuenta ha sido desactivada. Contacte al administrador.",
|
||||
"auth.forbidden": "No tiene permiso para acceder a este recurso.",
|
||||
"auth.logged_out": "Sesión cerrada exitosamente.",
|
||||
"auth.throttle": "Demasiados intentos. Intente de nuevo en :seconds segundos.",
|
||||
"legal.accept_required": "Debe aceptar los Términos de Uso y la Política de Privacidad antes de continuar.",
|
||||
"legal.accepted": "Términos aceptados exitosamente.",
|
||||
"legal.must_accept_terms": "Debe aceptar los Términos de Uso.",
|
||||
"legal.must_accept_privacy": "Debe aceptar la Política de Privacidad.",
|
||||
"legal.must_accept_cookies": "Debe aceptar la Política de Cookies.",
|
||||
"validation.captcha_required": "Resuelva la verificación matemática.",
|
||||
"validation.captcha_failed": "La respuesta de la verificación matemática es incorrecta.",
|
||||
"validation.model_not_allowed": "El modelo de IA seleccionado no está en la lista de permitidos.",
|
||||
"users.cannot_deactivate_self": "No puede desactivar su propia cuenta.",
|
||||
"users.deactivated": "Cuenta desactivada exitosamente.",
|
||||
"stores.deleted": "Tienda eliminada exitosamente.",
|
||||
"agents.deleted": "Agente eliminado exitosamente.",
|
||||
"welcome.tagline": "Una ciudad 3D viva en tu navegador, con agentes de IA autónomos — Alcalde, peatones, comerciantes y vehículos — decidiendo en tiempo real a través de OpenRouter.ai.",
|
||||
"welcome.card1.title": "🌐 Ciudad 3D en Tiempo Real",
|
||||
"welcome.card1.desc": "Explora calles, avenidas, puentes, ríos, plazas y edificios renderizados con Three.js directamente en tu navegador.",
|
||||
"welcome.card2.title": "🤖 Agentes de IA",
|
||||
"welcome.card2.desc": "El alcalde, los peatones y los comerciantes toman decisiones estratégicas usando modelos gratuitos de OpenRouter.ai.",
|
||||
"welcome.card3.title": "🔒 Seguro y LGPD",
|
||||
"welcome.card3.desc": "Autenticación diferenciada (Admin/User), CAPTCHA matemático y consentimiento auditado de términos conforme la legislación brasileña.",
|
||||
"welcome.city.title": "🗺️ Elementos de la Ciudad (Fase 1)",
|
||||
"welcome.city.desc": "La base de datos ya modela casas, edificios, escuelas, parques, plazas, semáforos, calles, avenidas, puentes, aeropuertos, ríos, industrias, tiendas y comerciantes — todos con coordenadas 3D (X, Y, Z) listas para el motor de renderizado.",
|
||||
"welcome.no_account": "¿No tienes cuenta?",
|
||||
"welcome.has_account": "¿Ya tienes cuenta?",
|
||||
"nav.city": "Ciudad 3D",
|
||||
"nav.admin": "Administración",
|
||||
"dashboard.open_viewer": "Abrir visor 3D",
|
||||
"dashboard.viewer_desc": "Explora el suelo de la ciudad, tiendas y agentes con cámara controlable.",
|
||||
"dashboard.stores_title": "Tiendas",
|
||||
"dashboard.stores_desc": "Tiendas registradas en la ciudad 3D.",
|
||||
"dashboard.legal_title": "Consentimientos",
|
||||
"dashboard.consent_history": "Ver historial de aceptaciones",
|
||||
"legal.terms_label": "Términos",
|
||||
"legal.privacy_label": "Privacidad",
|
||||
"legal.cookies_label": "Cookies",
|
||||
"admin.stores.title": "Gestionar Tiendas",
|
||||
"admin.stores.manage": "Gestionar tiendas",
|
||||
"admin.stores.admin_desc": "Crea tiendas y define su posición 3D en la ciudad.",
|
||||
"admin.stores.new": "Nueva tienda",
|
||||
"admin.stores.created": "Tienda creada exitosamente.",
|
||||
"admin.stores.updated": "Tienda actualizada exitosamente.",
|
||||
"admin.stores.edit_title": "Editar tienda",
|
||||
"admin.stores.create_title": "Nueva tienda",
|
||||
"admin.stores.empty": "Aún no hay tiendas registradas.",
|
||||
"admin.stores.position": "Posición 3D en la ciudad",
|
||||
"admin.stores.position_hint": "Haz clic en el suelo para fijar X/Z o escribe las coordenadas. Usa los controles para rotar/zoom.",
|
||||
"admin.stores.pos_x": "Posición X",
|
||||
"admin.stores.pos_y": "Altura Y (suelo = 0)",
|
||||
"admin.stores.pos_z": "Posición Z",
|
||||
"admin.stores.dimensions": "Dimensiones del edificio",
|
||||
"admin.stores.width": "Ancho",
|
||||
"admin.stores.height": "Alto",
|
||||
"admin.stores.depth": "Profundidad",
|
||||
"admin.stores.type": "Tipo de tienda",
|
||||
"admin.stores.description": "Descripción",
|
||||
"admin.stores.owner": "Dueño (usuario)",
|
||||
"admin.stores.agent": "Agente de IA (comerciante)",
|
||||
"admin.stores.is_open": "Tienda abierta",
|
||||
"admin.stores.no_owner": "Sin dueño",
|
||||
"admin.stores.no_agent": "Sin agente",
|
||||
"admin.stores.actions": "Acciones",
|
||||
"admin.stores.coords": "Coordenadas",
|
||||
"admin.stores.confirm_delete": "¿Eliminar esta tienda de la ciudad?",
|
||||
"city.title": "Visor 3D de la Ciudad",
|
||||
"city.loading": "Cargando ciudad…",
|
||||
"city.error": "Error al cargar los datos de la ciudad.",
|
||||
"city.stores_count": "tiendas",
|
||||
"city.agents_count": "agentes",
|
||||
"city.hint": "Haz clic en la escena para controlar · WASD para caminar · Ratón para mirar · Esc para salir",
|
||||
"city.refresh": "Recargar",
|
||||
"city.selected": "Seleccionada",
|
||||
"city.open": "Abierta",
|
||||
"city.closed": "Cerrada",
|
||||
"city.hint_fps": "WASD para caminar · Ratón para mirar · Esc para salir · Clic en un NPC para chatear",
|
||||
"city.position": "POSICIÓN",
|
||||
"city.on_ground": "en el suelo",
|
||||
"city.triangles": "tris de colisión",
|
||||
"city.chat_placeholder": "Escribe tu mensaje…",
|
||||
"city.chat_thinking": "pensando…",
|
||||
"city.chat_responding": "respondiendo…",
|
||||
"city.chat_accepted": "Mensaje enviado al agente.",
|
||||
"city.chat_error": "Lo siento, no puedo responder ahora. Inténtalo de nuevo.",
|
||||
"city.chat_send": "Enviar",
|
||||
"city.chat_with": "Chateando con"
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"Login": "Entrar",
|
||||
"Logout": "Sair",
|
||||
"Register": "Cadastrar",
|
||||
"Dashboard": "Painel",
|
||||
"Email": "E-mail",
|
||||
"Password": "Senha",
|
||||
"Password Confirmation": "Confirmar Senha",
|
||||
"Remember Me": "Lembrar de mim",
|
||||
"Name": "Nome",
|
||||
"Save": "Salvar",
|
||||
"Cancel": "Cancelar",
|
||||
"Delete": "Excluir",
|
||||
"Edit": "Editar",
|
||||
"Create": "Criar",
|
||||
"Search": "Buscar",
|
||||
"Back": "Voltar",
|
||||
"Welcome": "Bem-vindo ao City10",
|
||||
"auth.failed": "As credenciais fornecidas não correspondem aos nossos registros.",
|
||||
"auth.disabled": "Esta conta foi desativada. Contate o administrador.",
|
||||
"auth.forbidden": "Você não tem permissão para acessar este recurso.",
|
||||
"auth.logged_out": "Sessão encerrada com sucesso.",
|
||||
"auth.throttle": "Muitas tentativas. Tente novamente em :seconds segundos.",
|
||||
"legal.accept_required": "Você precisa aceitar os Termos de Uso e a Política de Privacidade antes de continuar.",
|
||||
"legal.accepted": "Termos aceitos com sucesso.",
|
||||
"legal.must_accept_terms": "Você precisa aceitar os Termos de Uso.",
|
||||
"legal.must_accept_privacy": "Você precisa aceitar a Política de Privacidade.",
|
||||
"legal.must_accept_cookies": "Você precisa aceitar a Política de Cookies.",
|
||||
"validation.captcha_required": "Resolva a verificação matemática.",
|
||||
"validation.captcha_failed": "Resposta da verificação matemática incorreta.",
|
||||
"validation.model_not_allowed": "O modelo de IA selecionado não está na lista de permitidos.",
|
||||
"users.cannot_deactivate_self": "Você não pode desativar sua própria conta.",
|
||||
"users.deactivated": "Conta desativada com sucesso.",
|
||||
"stores.deleted": "Loja excluída com sucesso.",
|
||||
"agents.deleted": "Agente excluído com sucesso.",
|
||||
"welcome.tagline": "Uma cidade 3D viva no navegador, com agentes de IA autônomos — Prefeito, pedestres, lojistas e veículos — decidindo em tempo real através do OpenRouter.ai.",
|
||||
"welcome.card1.title": "🌐 Cidade 3D em Tempo Real",
|
||||
"welcome.card1.desc": "Explore ruas, avenidas, pontes, rios, praças e edifícios renderizados com Three.js direto no navegador.",
|
||||
"welcome.card2.title": "🤖 Agentes de IA",
|
||||
"welcome.card2.desc": "Prefeito, pedestres e lojistas tomam decisões estratégicas através de modelos gratuitos do OpenRouter.ai.",
|
||||
"welcome.card3.title": "🔒 Seguro & LGPD",
|
||||
"welcome.card3.desc": "Autenticação diferenciada (Admin/User), CAPTCHA matemático e consentimento auditável de termos conforme a legislação brasileira.",
|
||||
"welcome.city.title": "🗺️ Elementos da Cidade (Fase 1)",
|
||||
"welcome.city.desc": "A base de dados já modela casas, edifícios, escolas, parques, praças, semáforos, ruas, avenidas, pontes, aeroportos, rios, indústrias, lojas e lojistas — todos com coordenadas 3D (X, Y, Z) prontas para o motor de renderização.",
|
||||
"welcome.no_account": "Não tem conta?",
|
||||
"welcome.has_account": "Já tem conta?",
|
||||
"nav.city": "Cidade 3D",
|
||||
"nav.admin": "Administração",
|
||||
"dashboard.open_viewer": "Abrir visualizador 3D",
|
||||
"dashboard.viewer_desc": "Explore o chão da cidade, lojas e agentes com câmera controlável.",
|
||||
"dashboard.stores_title": "Lojas",
|
||||
"dashboard.stores_desc": "Lojas cadastradas na cidade 3D.",
|
||||
"dashboard.legal_title": "Consentimentos",
|
||||
"dashboard.consent_history": "Ver histórico de aceites",
|
||||
"legal.terms_label": "Termos",
|
||||
"legal.privacy_label": "Privacidade",
|
||||
"legal.cookies_label": "Cookies",
|
||||
"admin.stores.title": "Gerenciar Lojas",
|
||||
"admin.stores.manage": "Gerenciar lojas",
|
||||
"admin.stores.admin_desc": "Cadastre lojas e defina a posição 3D delas na cidade.",
|
||||
"admin.stores.new": "Nova loja",
|
||||
"admin.stores.created": "Loja criada com sucesso.",
|
||||
"admin.stores.updated": "Loja atualizada com sucesso.",
|
||||
"admin.stores.edit_title": "Editar loja",
|
||||
"admin.stores.create_title": "Nova loja",
|
||||
"admin.stores.empty": "Nenhuma loja cadastrada ainda.",
|
||||
"admin.stores.position": "Posição 3D na cidade",
|
||||
"admin.stores.position_hint": "Clique no chão para definir X/Z, ou digite as coordenadas. Use os controles para girar/zoom.",
|
||||
"admin.stores.pos_x": "Posição X",
|
||||
"admin.stores.pos_y": "Altura Y (chão = 0)",
|
||||
"admin.stores.pos_z": "Posição Z",
|
||||
"admin.stores.dimensions": "Dimensões do prédio",
|
||||
"admin.stores.width": "Largura",
|
||||
"admin.stores.height": "Altura",
|
||||
"admin.stores.depth": "Profundidade",
|
||||
"admin.stores.type": "Tipo de loja",
|
||||
"admin.stores.description": "Descrição",
|
||||
"admin.stores.owner": "Dono (usuário)",
|
||||
"admin.stores.agent": "Agente de IA (lojista)",
|
||||
"admin.stores.is_open": "Loja aberta",
|
||||
"admin.stores.no_owner": "Sem dono",
|
||||
"admin.stores.no_agent": "Sem agente",
|
||||
"admin.stores.actions": "Ações",
|
||||
"admin.stores.coords": "Coordenadas",
|
||||
"admin.stores.confirm_delete": "Excluir esta loja da cidade?",
|
||||
"city.title": "Visualizador 3D da Cidade",
|
||||
"city.loading": "Carregando cidade…",
|
||||
"city.error": "Falha ao carregar os dados da cidade.",
|
||||
"city.stores_count": "lojas",
|
||||
"city.agents_count": "agentes",
|
||||
"city.hint": "Clique na tela para controlar · WASD para andar · Mouse para olhar · Esc para sair",
|
||||
"city.refresh": "Recarregar",
|
||||
"city.selected": "Selecionada",
|
||||
"city.open": "Aberta",
|
||||
"city.closed": "Fechada",
|
||||
"city.hint_fps": "WASD para andar · Mouse para olhar · Esc para sair · Clique no NPC para conversar",
|
||||
"city.position": "POSIÇÃO",
|
||||
"city.on_ground": "no chão",
|
||||
"city.triangles": "tris de colisão",
|
||||
"city.chat_placeholder": "Digite sua mensagem…",
|
||||
"city.chat_thinking": "pensando…",
|
||||
"city.chat_responding": "respondendo…",
|
||||
"city.chat_accepted": "Mensagem enviada ao agente.",
|
||||
"city.chat_error": "Desculpe, não consegui responder agora. Tente novamente.",
|
||||
"city.chat_send": "Enviar",
|
||||
"city.chat_with": "Conversando com"
|
||||
}
|
||||
Reference in New Issue
Block a user