Documento técnico principal del proyecto móvil y su API backend.
| Campo | Valor |
|---|---|
| Aplicación | Kancha |
| Tipo de solución | Aplicación móvil híbrida y web para gestión deportiva |
| Frontend | Ionic 8, Angular 20, Capacitor 8, TypeScript |
| Backend | Node.js, Express, TypeScript, Socket.IO |
| Persistencia y servicios cloud | Firebase Authentication, Firestore, Cloud Storage y Firebase Cloud Messaging |
| Documentación API ejecutable | Swagger UI en /api-docs |
| Última revisión documental | 24 de mayo de 2026 |
Kancha permite conectar usuarios alrededor de actividades deportivas. La plataforma soporta autenticación, perfiles, amistades, mensajería privada y grupal, comunidades, publicación y reserva de canchas, administración de deportes y servicios, notificaciones push y recomendación de canchas asistida por inteligencia artificial.
Este README.md es la fuente recomendada para la documentación técnica porque:
- Permanece versionado junto al código y puede actualizarse en cada cambio.
- Se visualiza directamente en GitHub, GitLab o el entorno de desarrollo.
- Permite registrar comandos, estructuras, rutas y decisiones arquitectónicas sin depender de software externo.
- Puede exportarse posteriormente a PDF o Word cuando se necesite una entrega académica o administrativa.
| Módulo | Capacidades principales |
|---|---|
| Autenticación y perfil | Registro, inicio de sesión por correo, Google Sign-In, cierre de sesión, consulta de sesión, imagen de perfil y preferencias del deportista. |
| Presencia y amistades | Usuarios en línea, búsqueda, solicitudes de amistad, aceptación, rechazo y eliminación. |
| Chat privado | Conversaciones, listado de chats activos, envío, lectura, entrega y estado de escritura en tiempo real. |
| Canchas | Creación y edición con imágenes, ubicación, deportes, servicios, precio, descubrimiento y detalle. |
| Reservas | Disponibilidad semanal, solicitud de reserva, aceptación, rechazo, cancelación, reseñas y métricas de uso. |
| Recomendaciones | Búsqueda personalizada y chat de recomendaciones con proveedor de IA configurable. |
| Grupos deportivos | Creación de grupos, miembros, asistencia, asociación a reserva y chat grupal. |
| Comunidades | Comunidades públicas o privadas, miembros, publicaciones, comentarios, reacciones e imágenes. |
| Catálogos | Administración de deportes y servicios disponibles para canchas. |
| Notificaciones | Registro de tokens móviles y envío push ante eventos del dominio. |
programacion_mobile/
|-- backend/
| |-- src/
| | |-- application/ Casos de uso, DTO, esquemas, puertos y servicios
| | |-- domain/ Entidades, eventos, errores y contratos de repositorios
| | |-- infrastructure/ Firebase, HTTP, Socket.IO, IA, storage y notificaciones
| | |-- interfaces/ Controladores HTTP y controladores de WebSocket
| | |-- shared/ Configuración de entorno, logger y tipos comunes
| | `-- main.ts Punto de entrada del servidor
| |-- Dockerfile
| |-- docker-compose.yml
| |-- jest.config.js
| `-- package.json
|-- frontend/
| |-- src/
| | |-- app/
| | | |-- core/ Servicios globales, interceptor y manejo de errores
| | | |-- features/ Módulos funcionales
| | | `-- shared/ Componentes, páginas, pipes y directivas compartidas
| | |-- environments/ URL de API, Socket.IO, mapas, Firebase y push
| | `-- theme/ Variables y estilos globales
| |-- android/ Proyecto nativo Android de Capacitor
| |-- ios/ Proyecto nativo iOS de Capacitor
| |-- angular.json
| |-- capacitor.config.ts
| `-- package.json
|-- .gitignore
`-- README.md
flowchart LR
subgraph Cliente["Cliente Kancha"]
UI["Ionic / Angular"]
CAP["Capacitor Android / iOS"]
STATE["Estados y casos de uso frontend"]
UI --> STATE
CAP --> UI
end
subgraph Servidor["Backend Node.js"]
REST["Express REST API /api"]
WS["Socket.IO"]
APP["Casos de uso"]
REST --> APP
WS --> APP
end
subgraph Firebase["Servicios Firebase"]
AUTH["Authentication"]
DB[("Firestore")]
STORAGE["Cloud Storage"]
FCM["Cloud Messaging"]
end
subgraph Externos["Servicios externos"]
MAPS["Mapbox"]
AI["OpenRouter o Gemini"]
end
STATE -- "HTTP + Bearer token" --> REST
STATE -- "Eventos realtime + token" --> WS
UI -- "Google Sign-In" --> AUTH
APP -- "Verificar token" --> AUTH
APP --> DB
APP --> STORAGE
APP --> FCM
APP --> AI
UI --> MAPS
La API REST gestiona operaciones transaccionales y consultas; Socket.IO mantiene presencia y mensajería inmediata. Firebase concentra identidad, persistencia, archivos y notificaciones, mientras que los proveedores de IA y mapas son integraciones externas especializadas.
El backend y varios módulos del frontend siguen una separación inspirada en Clean Architecture y DDD:
| Capa | Responsabilidad |
|---|---|
| Dominio | Entidades, invariantes, roles, estados y contratos abstractos. No depende de Firebase ni de HTTP. |
| Aplicación | Casos de uso, validaciones Zod, DTO, servicios de aplicación y puertos externos. |
| Infraestructura | Implementaciones Firestore/Firebase, HTTP Express, Socket.IO, proveedores IA y almacenamiento. |
| Presentación o interfaces | Controladores que reciben solicitudes y delegan a los casos de uso. |
En el backend, src/infrastructure/config/container.ts es el composition root: registra implementaciones concretas en tsyringe y selecciona el proveedor de recomendaciones. En el frontend, Angular enlaza repositorios HTTP con casos de uso y estados desde CoreModule, AppModule y los módulos funcionales.
flowchart LR
CLIENT["Vista Ionic"] --> STATE["Estado o caso de uso frontend"]
STATE --> ADAPTER["Repositorio HTTP frontend"]
ADAPTER --> ROUTE["Ruta Express"]
ROUTE --> MIDDLEWARE["Autenticación y validación Zod"]
MIDDLEWARE --> CONTROLLER["Controlador"]
CONTROLLER --> USECASE["Caso de uso backend"]
USECASE --> DOMAIN["Entidad y reglas de dominio"]
USECASE --> PORT["Puerto de repositorio"]
PORT --> FIRESTORE["Adaptador Firestore"]
FIRESTORE --> DATA[("Datos persistidos")]
USECASE -. "evento" .-> PUSH["Push o Socket.IO"]
El cliente no accede directamente a datos administrativos. La solicitud cruza validación y autenticación del backend, donde el caso de uso aplica autorización y reglas de dominio antes de persistir o emitir eventos.
| Tecnología | Uso |
|---|---|
| Node.js y TypeScript | Runtime y tipado del servidor. La imagen Docker usa Node 22 Alpine. |
| Express | API HTTP, middleware, CORS y manejo global de errores. |
| Socket.IO | Presencia, chats y actualizaciones en tiempo real. |
| Firebase Admin SDK | Autenticación de tokens, Firestore, Storage y Messaging. |
| tsyringe | Inyección de dependencias. |
| Zod | Validación de cuerpos, parámetros y consultas HTTP. |
| Multer | Carga de imágenes en memoria para perfiles, canchas y publicaciones. |
| Swagger | Especificación y UI de documentación REST. |
| Jest y ts-jest | Pruebas unitarias de casos de uso. |
| Directorio | Contenido técnico |
|---|---|
domain/entities |
User, Court, CourtReservation, CourtAvailability, Group, GroupMember, Message, Friend, Community, Sports y CourtService. |
domain/repositories |
Puertos de persistencia y almacenamiento que consumen los casos de uso. |
application/use-cases |
Operaciones de usuarios, amistades, mensajes, canchas, reservas, grupos, comunidades, push, deportes y servicios. |
application/schemas |
Contratos de entrada HTTP validados con Zod. |
infrastructure/repositories |
Adaptadores concretos de Firestore. |
infrastructure/http/routes |
Exposición de endpoints REST. |
infrastructure/websocket |
Servidor Socket.IO, gateway de emisiones y eventos en tiempo real. |
interfaces/http |
Controladores HTTP. |
interfaces/websocket |
Controladores de eventos de usuario, mensajes y chat grupal. |
El archivo backend/src/main.ts ejecuta la secuencia:
- Carga configuración de entorno.
- Configura dependencias y conecta Firebase.
- Inicializa Express y registra rutas bajo
/api. - Registra suscriptores para notificaciones y eventos en tiempo real.
- Publica Swagger en
/api-docsy JSON en/api-docs.json. - Configura el manejador global de errores.
- Crea el servidor HTTP y monta Socket.IO sobre el mismo puerto.
- Atiende
SIGINTySIGTERMpara cerrar el servidor correctamente.
El endpoint de disponibilidad operativa es:
GET /healthsequenceDiagram
participant N as Node.js
participant E as envConfig
participant DI as Container tsyringe
participant F as Firebase Admin
participant X as Express
participant S as Socket.IO
N->>E: Cargar variables de entorno
N->>DI: configureDependencies()
DI->>F: Inicializar credenciales y servicios
F-->>DI: Firestore, Auth, Storage y Messaging
N->>X: Crear servidor y middleware
N->>X: Registrar rutas /api y Swagger
N->>DI: Registrar suscriptores de eventos
N->>S: Montar Socket.IO sobre HTTP
N->>N: Escuchar puerto configurado
| Rol de usuario | Uso funcional |
|---|---|
athlete |
Descubre canchas, configura preferencias, reserva, reseña y participa en interacciones sociales. |
court_landlord |
Registra canchas, administra disponibilidad, atiende reservas y consulta métricas. |
admin |
Gestiona catálogos de deportes y servicios desde las pantallas administrativas. |
user |
Rol soportado por la entidad como valor general o de compatibilidad. |
Reglas relevantes implementadas en casos de uso:
- El registro público admite los roles
athleteycourt_landlord. - La creación de cancha exige un usuario
court_landlord. - Las preferencias deportivas pertenecen a usuarios
athlete. - Una reserva inicia con estado
pendingy puede pasar aconfirmed,cancelled,rejectedoexpired. - El arrendador propietario puede aceptar o rechazar reservas de su cancha.
- La cancelación se autoriza para el deportista dueño de la reserva o el arrendador propietario de la cancha.
- La creación de deportes y servicios se restringe al rol
adminen los casos de uso correspondientes. - Los permisos internos de grupos usan roles
ADMINyMEMBER. - Los permisos internos de comunidades usan roles
adminymember.
| Colección Firestore | Propósito |
|---|---|
users |
Perfil, rol, presencia y preferencias del usuario. |
sports |
Catálogo de deportes. |
court_services |
Catálogo de servicios disponibles. |
courts |
Canchas registradas y sus datos operativos. |
courts/{courtId}/reviews |
Reseñas de reservas completadas por cancha. |
court_availability |
Configuración semanal de horarios de cancha. |
court_reservations |
Reservas y estado actual. |
court_reservation_events |
Eventos históricos de reservas. |
friendships |
Solicitudes y relaciones de amistad. |
messages/{conversationId}/messages |
Conversaciones privadas y mensajes. |
groups |
Grupos deportivos y último mensaje. |
groupMembers |
Membresía, rol y asistencia en grupos. |
groupMessages |
Mensajes de grupos. |
communities |
Comunidades creadas. |
communityMembers |
Membresía y solicitudes en comunidades. |
communityPosts |
Publicaciones de comunidades. |
communityPostLikes |
Reacciones a publicaciones. |
communityPostComments |
Comentarios de publicaciones. |
push_tokens |
Tokens de dispositivos para notificaciones. |
Firebase Cloud Storage almacena imágenes de perfil, imágenes de canchas e imágenes cargadas para publicaciones.
erDiagram
USER ||--o{ FRIENDSHIP : participa
USER ||--o{ MESSAGE : envia_o_recibe
USER ||--o{ PUSH_TOKEN : registra
USER ||--o{ COURT : administra
USER ||--o{ COURT_RESERVATION : solicita
COURT ||--|| COURT_AVAILABILITY : configura
COURT ||--o{ COURT_RESERVATION : recibe
COURT ||--o{ REVIEW : obtiene
COURT }o--o{ SPORT : ofrece
COURT }o--o{ COURT_SERVICE : incluye
USER ||--o{ GROUP_MEMBER : integra
GROUP ||--o{ GROUP_MEMBER : contiene
GROUP ||--o{ GROUP_MESSAGE : registra
COURT_RESERVATION o|--o| GROUP : vincula
USER ||--o{ COMMUNITY_MEMBER : integra
COMMUNITY ||--o{ COMMUNITY_MEMBER : contiene
COMMUNITY ||--o{ COMMUNITY_POST : publica
COMMUNITY_POST ||--o{ COMMUNITY_COMMENT : recibe
COMMUNITY_POST ||--o{ COMMUNITY_LIKE : recibe
El diagrama representa relaciones conceptuales. Firestore implementa parte de ellas como colecciones independientes y parte como subcolecciones, por ejemplo las reseñas en courts/{courtId}/reviews y los mensajes privados en messages/{conversationId}/messages.
Crear backend/.env localmente. No se deben versionar archivos de cuentas de servicio ni claves privadas.
# Servidor
PORT=3000
NODE_ENV=development
HTTP_CORS_ORIGIN=http://localhost:8100,http://localhost:4200
WS_CORS_ORIGIN=http://localhost:8100,http://localhost:4200
# Firebase: opción A para desarrollo
FIREBASE_SERVICE_ACCOUNT_PATH=./firebase-service-account.json
FIREBASE_STORAGE_BUCKET=nombre-del-bucket
FIREBASE_API_KEY=api-key-web-firebase
# Firebase: opción B para despliegue, en lugar del archivo JSON
# FIREBASE_PROJECT_ID=proyecto
# FIREBASE_CLIENT_EMAIL=cuenta-servicio@proyecto.iam.gserviceaccount.com
# FIREBASE_PRIVATE_KEY_BASE64=clave-privada-codificada-en-base64
# Recomendaciones por IA
AI_PROVIDER=openrouter
OPENROUTER_API_KEY=
OPENROUTER_MODEL=openai/gpt-4o-mini
OPENROUTER_SITE_URL=
OPENROUTER_APP_NAME=mobile-courts-recommender
# Alternativa de IA
# AI_PROVIDER=gemini
# GEMINI_API_KEY=
# GEMINI_MODEL=gemini-1.5-flash
# GEMINI_BASE_URL=https://generativelanguage.googleapis.comNotas de configuración:
- El backend no inicia sin credenciales válidas de Firebase Admin.
- Si no existe una clave válida para el proveedor IA elegido, se utiliza un servicio sin recomendaciones generativas (
NoopCourtRecommendationAIService). HTTP_CORS_ORIGINyWS_CORS_ORIGINaceptan orígenes separados por comas.- Las cargas de imágenes aceptan JPG, PNG o WEBP, con máximo de 5 MB por imagen; una cancha acepta hasta cinco imágenes.
Todas las rutas funcionales se montan con prefijo /api. Las marcadas como autenticadas requieren:
Authorization: Bearer <firebase-id-token>La documentación interactiva del backend está disponible durante la ejecución en:
http://localhost:3000/api-docs
http://localhost:3000/api-docs.json
| Método | Ruta | Autenticación | Descripción |
|---|---|---|---|
POST |
/api/users/register |
No | Registra un usuario. |
POST |
/api/auth/login |
No | Autenticación por correo y contraseña. |
POST |
/api/auth/google |
No | Autenticación con token de Google. |
POST |
/api/auth/refresh |
No | Renueva token de acceso. |
POST |
/api/auth/logout |
Sí | Cierra la sesión autenticada. |
GET |
/api/auth/me |
Sí | Retorna el usuario actual. |
GET |
/api/users/:id |
No | Consulta un usuario por identificador. |
GET |
/api/users/search |
Sí | Busca usuarios por texto. |
GET |
/api/users/online/list |
No | Lista usuarios en línea. |
POST |
/api/users/connect |
No | Marca presencia conectada. |
POST |
/api/users/:id/disconnect |
No | Marca desconexión. |
PATCH |
/api/users/profile-image |
Sí | Actualiza imagen, usando multipart/form-data con campo image. |
PATCH |
/api/users/me/athlete-preferences |
Sí | Actualiza deportes favoritos, ubicación base y radio preferido. |
| Método | Ruta | Autenticación | Descripción |
|---|---|---|---|
GET |
/api/friends |
Sí | Lista amistades. |
GET |
/api/friends/pending |
Sí | Lista solicitudes recibidas pendientes. |
GET |
/api/friends/sent |
Sí | Lista solicitudes enviadas. |
POST |
/api/friends/send-request |
Sí | Envía solicitud de amistad. |
POST |
/api/friends/accept-request |
Sí | Acepta solicitud. |
POST |
/api/friends/reject-request |
Sí | Rechaza solicitud. |
DELETE |
/api/friends/remove/:id |
Sí | Elimina una amistad. |
POST |
/api/messages |
Sí | Envía mensaje privado por HTTP. |
GET |
/api/messages/active |
Sí | Obtiene conversaciones activas. |
GET |
/api/messages/:userId |
Sí | Obtiene mensajes con un usuario. |
POST |
/api/push/tokens |
Sí | Registra token push de un dispositivo. |
DELETE |
/api/push/tokens/:token |
Sí | Elimina un token push. |
| Método | Ruta | Autenticación | Descripción |
|---|---|---|---|
GET |
/api/sports/icons |
No | Obtiene catálogo de iconos deportivos. |
GET |
/api/sports |
No | Lista deportes. |
POST |
/api/sports/create |
Sí | Crea deporte; operación administrativa. |
GET |
/api/sports/:id |
Sí | Consulta deporte. |
PUT |
/api/sports/update/:id |
Sí | Modifica deporte. |
DELETE |
/api/sports/delete/:id |
Sí | Elimina deporte. |
GET |
/api/services |
No | Lista servicios de canchas. |
POST |
/api/services/create |
Sí | Crea servicio; operación administrativa. |
GET |
/api/services/:id |
Sí | Consulta servicio. |
PUT |
/api/services/update/:id |
Sí | Modifica servicio. |
DELETE |
/api/services/delete/:id |
Sí | Elimina servicio. |
POST |
/api/courts/create |
Sí | Crea cancha con multipart/form-data y campo images. |
GET |
/api/courts/recent |
No | Lista canchas recientes. |
GET |
/api/courts/discover |
Sí | Descubre canchas con filtros y personalización. |
POST |
/api/courts/recommendations/chat |
Sí | Consulta recomendación conversacional. |
GET |
/api/courts/me |
Sí | Lista canchas del arrendador actual. |
GET |
/api/courts/:id |
Sí | Obtiene detalle de cancha. |
PUT |
/api/courts/update/:id |
Sí | Actualiza una cancha y opcionalmente imágenes. |
| Método | Ruta | Autenticación | Descripción |
|---|---|---|---|
PUT |
/api/courts/:id/availability |
Sí | Configura reglas semanales de disponibilidad. |
GET |
/api/courts/:id/availability |
Sí | Consulta espacios disponibles para una fecha. |
GET |
/api/courts/:id/availability-config |
Sí | Consulta configuración horaria. |
POST |
/api/courts/:id/reservations |
Sí | Crea reserva. |
GET |
/api/reservations/me |
Sí | Lista reservas del deportista. |
GET |
/api/courts/landlord/reservations |
Sí | Lista reservas recibidas por arrendador. |
POST |
/api/reservations/:reservationId/accept |
Sí | Confirma reserva. |
POST |
/api/reservations/:reservationId/reject |
Sí | Rechaza reserva. |
POST |
/api/reservations/:reservationId/cancel |
Sí | Cancela reserva. |
POST |
/api/reservations/:reservationId/review |
Sí | Registra reseña asociada a reserva. |
GET |
/api/courts/:id/reviews |
Sí | Lista reseñas de la cancha. |
GET |
/api/courts/:id/metrics |
Sí | Calcula métricas por periodo para la cancha. |
| Método | Ruta | Autenticación | Descripción |
|---|---|---|---|
POST |
/api/groups |
Sí | Crea grupo deportivo. |
GET |
/api/groups/me |
Sí | Lista grupos del usuario. |
GET |
/api/groups/my-chats |
Sí | Lista conversaciones grupales activas. |
GET |
/api/groups/:id |
Sí | Obtiene grupo y miembros. |
PATCH |
/api/groups/:id |
Sí | Modifica información de grupo. |
POST |
/api/groups/:id/members |
Sí | Agrega miembro. |
DELETE |
/api/groups/:id/members/:userId |
Sí | Retira miembro. |
PATCH |
/api/groups/:id/reservation |
Sí | Vincula o desvincula reserva. |
PATCH |
/api/groups/:id/attendance |
Sí | Actualiza asistencia personal. |
POST |
/api/groups/:id/messages |
Sí | Envía mensaje de grupo. |
GET |
/api/groups/:id/messages |
Sí | Obtiene mensajes de grupo. |
GET |
/api/communities/feed |
Sí | Obtiene publicaciones del feed. |
POST |
/api/communities/upload-image |
Sí | Sube imagen para publicación. |
GET / POST |
/api/communities |
Sí | Lista o crea comunidades. |
GET / PATCH |
/api/communities/:id |
Sí | Consulta o actualiza comunidad. |
POST |
/api/communities/:id/join |
Sí | Solicita o ejecuta ingreso. |
DELETE |
/api/communities/:id/leave |
Sí | Sale de comunidad. |
GET |
/api/communities/:id/members |
Sí | Lista miembros. |
GET |
/api/communities/:id/members/pending |
Sí | Lista solicitudes pendientes. |
POST |
/api/communities/:id/members/:memberId/approve |
Sí | Aprueba miembro. |
GET / POST |
/api/communities/:id/posts |
Sí | Lista o crea publicaciones. |
DELETE |
/api/communities/:id/posts/:postId |
Sí | Elimina publicación. |
POST |
/api/communities/:id/posts/:postId/like |
Sí | Alterna reacción. |
GET / POST |
/api/communities/:id/posts/:postId/comments |
Sí | Lista o crea comentarios. |
Socket.IO usa la misma URL base del backend y acepta el token Firebase en handshake.auth.token o en el encabezado Authorization: Bearer <token>. Si el token es válido, el socket ingresa a la sala user:<uid>.
sequenceDiagram
actor A as Usuario A
participant FA as Frontend A
participant IO as Socket.IO Backend
participant DB as Firestore
participant FB as Frontend B
actor B as Usuario B
A->>FA: Abre sesión y chat
FA->>IO: connect(token Firebase)
IO->>IO: Verifica token y une a user:A
FA->>IO: conversation:join(peerId B)
B->>FB: Abre aplicación
FB->>IO: connect(token Firebase)
IO->>IO: Verifica token y une a user:B
A->>FA: Escribe mensaje
FA->>IO: typing:start
IO-->>FB: typing:start
FA->>IO: message:send
IO->>DB: Persistir mensaje
DB-->>IO: Mensaje creado
IO-->>FA: message:created
IO-->>FB: message:created
FB->>IO: message:mark-read
IO->>DB: Actualizar lectura
IO-->>FA: message:read
flowchart TD
AUTH["Socket autenticado"] --> USERROOM["Sala privada user:uid"]
USERROOM --> PRIVATE["Notificaciones privadas y mensajes"]
AUTH --> CONV["Sala conversation:userA_userB"]
CONV --> TYPING["Escritura y actividad de conversación"]
AUTH --> GROUP["Sala group:groupId"]
GROUP --> GROUPMSG["Mensajes grupales"]
EVENTS["Eventos de amistad"] --> USERROOM
| Evento | Dirección principal | Propósito |
|---|---|---|
user:connect |
Cliente a servidor | Registra presencia del usuario. |
user:disconnect |
Cliente a servidor | Actualiza salida del usuario. |
users:get-online |
Cliente a servidor | Solicita usuarios conectados. |
users:online |
Servidor a clientes | Difunde listado actualizado de presencia. |
conversation:join |
Cliente a servidor | Entra a una conversación privada. |
conversation:leave |
Cliente a servidor | Sale de una conversación privada. |
message:send |
Cliente a servidor | Envía mensaje privado con confirmación. |
message:created |
Servidor a cliente | Notifica mensaje creado. |
message:delivered |
Servidor a cliente | Notifica entrega de mensaje. |
message:mark-read |
Cliente a servidor | Marca mensajes leídos. |
message:read |
Servidor a cliente | Notifica lectura. |
typing:start / typing:stop |
Bidireccional | Estado de escritura. |
friend:request:sent |
Servidor a cliente | Solicitud de amistad en tiempo real. |
friend:request:accepted |
Servidor a cliente | Aceptación de amistad. |
group:chat:join / group:chat:leave |
Cliente a servidor | Suscripción a sala group:<id>. |
group:message:send |
Cliente a servidor | Envía mensaje grupal. |
group:message:created |
Servidor a sala | Difunde nuevo mensaje de grupo. |
| Tecnología | Uso |
|---|---|
| Angular 20 | Componentes, routing, inyección, formularios y cliente HTTP. |
| Ionic 8 | Interfaz móvil, navegación y componentes visuales. |
| Capacitor 8 | Empaquetado y acceso a Android/iOS. |
| Firebase Web SDK | Inicio de sesión con Google. |
| Socket.IO Client | Mensajería, amistad y presencia en tiempo real. |
| RxJS | Estado reactivo y flujos asincrónicos. |
| Mapbox | Selección y presentación geográfica de canchas. |
| SCSS | Estilos, tema y accesibilidad. |
flowchart TB
APP["AppModule"] --> CORE["CoreModule"]
APP --> ROUTER["AppRoutingModule"]
ROUTER --> AUTH["AuthModule"]
ROUTER --> HOME["HomePageModule"]
HOME --> TABS["MainTabsComponent"]
TABS --> CHATS["Chats"]
TABS --> FRIENDS["Friends"]
TABS --> PUB["Publications"]
TABS --> GROUPS["Groups"]
TABS --> COMM["Communities y Feed"]
TABS --> PROFILE["Profile"]
CORE --> HTTP["ApiService + AuthInterceptor"]
CORE --> SOCKET["SocketService"]
CORE --> SESSION["AuthState + Guards"]
PUB --> ROLES["Guards Athlete, Landlord y Admin"]
Carpeta de src/app/features |
Responsabilidad |
|---|---|
auth |
Login, registro, Google Sign-In, sesión, perfil, token service y guards. |
friends |
Solicitudes, amigos, búsqueda de usuarios y eventos Socket.IO asociados. |
chats |
Lista de chats, conversación privada y estado reactivo del chat. |
publications |
Canchas, reservas, disponibilidad, reseñas, recomendaciones, deportes y servicios. |
groups |
Grupos deportivos, miembros, asistencia, reservas vinculadas y chat grupal. |
communities |
Feed, comunidades, miembros, posts, likes y comentarios. |
profile |
Visualización y modificación de datos del usuario. |
home |
Contenedor de navegación autenticada y pestañas principales. |
flowchart TD
START["Inicio"] --> LOGIN["/auth/login"]
LOGIN -->|Sesión válida| HOME["/home"]
LOGIN --> REGISTER["/auth/register"]
HOME --> CHATS["chats"]
HOME --> FRIENDS["friends"]
HOME --> PUBLICATIONS["publications"]
HOME --> GROUPS["groups"]
HOME --> COMMUNITIES["communities / feed"]
HOME --> PROFILE["profile"]
PUBLICATIONS -->|athlete| RESERVATIONS["reservations/mine"]
PUBLICATIONS -->|admin| ADMIN["sports/admin y services/admin"]
HOME -->|court_landlord| LANDLORD["my-courts, create-court y landlord-reservations"]
START -->|Ruta inválida| OOPS["/oops"]
| Ruta frontend | Acceso | Vista o módulo |
|---|---|---|
/auth/login |
Sin sesión | Inicio de sesión. |
/auth/register |
Sin sesión | Registro. |
/home/chats |
Sesión | Conversaciones privadas y grupales. |
/home/friends |
Sesión | Amistades y solicitudes. |
/home/publications |
Sesión | Descubrimiento y gestión según rol. |
/home/publications/reservations/mine |
athlete |
Reservas personales. |
/home/publications/sports/admin |
admin |
Administración de deportes. |
/home/publications/services/admin |
admin |
Administración de servicios. |
/home/landlord-reservations |
court_landlord |
Reservas recibidas. |
/home/my-courts |
court_landlord |
Canchas propias. |
/home/create-court |
court_landlord |
Registro de cancha. |
/home/groups |
Sesión y rol habilitado | Gestión de grupos. |
/home/communities |
Sesión | Listado y detalle de comunidades. |
/home/feed |
Sesión | Feed global. |
/home/profile |
Sesión | Perfil. |
| Servicio | Función |
|---|---|
ApiService |
Construye solicitudes contra environment.apiUrl. |
AuthInterceptor |
Agrega el token Bearer a solicitudes HTTP autenticadas. |
SocketService |
Conecta a environment.wsUrl, autentica y gestiona eventos. |
PushNotificationsService |
Solicita permisos, registra token de plataforma y sincroniza con API. |
GoogleAuthService |
Ejecuta autenticación Google con configuración Firebase web. |
GeolocationService |
Apoya funcionalidades de ubicación. |
RolePermissionService |
Controla pestañas y accesos visibles según rol. |
ThemeService |
Persiste preferencia visual local. |
NotificationCenterService |
Persiste y presenta notificaciones recibidas. |
GlobalErrorHandler |
Centraliza tratamiento de fallos de interfaz. |
Los archivos frontend/src/environments/environment.ts y environment.prod.ts definen:
| Propiedad | Uso |
|---|---|
apiUrl |
URL del backend con sufijo /api. |
wsUrl |
URL base para Socket.IO. |
mapboxToken y mapboxStyleUrl |
Visualización y selección de ubicación. |
pushNotificationsEnabled |
Habilitación funcional de push. |
iosPushPresentationEnabled y opciones |
Comportamiento de notificaciones en primer plano iOS. |
firebase |
Configuración pública del cliente Firebase para autenticación. |
capacitor.config.ts utiliza la configuración elegida por CAPACITOR_ENV o NODE_ENV, define el identificador app.mobile.starter, el nombre Kancha, la salida web www y los plugins de teclado y notificaciones.
- Node.js 22 recomendado, consistente con la imagen Docker del backend.
- npm.
- Proyecto Firebase configurado con Authentication, Firestore, Storage y Messaging.
- Archivo de cuenta de servicio Firebase local o credenciales equivalentes por variables de entorno.
- Android Studio o Xcode únicamente si se generará la aplicación nativa.
cd backend
npm install
# Crear .env y disponer la credencial Firebase configurada en ese archivo
npm run devServicios disponibles por defecto:
API: http://localhost:3000/api
Health: http://localhost:3000/health
Swagger: http://localhost:3000/api-docs
Socket.IO: http://localhost:3000
cd frontend
npm install
npm startAngular/Ionic sirve el frontend para desarrollo y utiliza environment.ts, cuya API local debe apuntar al backend en ejecución.
cd frontend
npm run cap:android:dev
npm run cap:ios:devPara construir sincronizando la configuración productiva:
npm run cap:android:prod
npm run cap:ios:prodDespués de la sincronización, el proyecto nativo se opera desde Android Studio o Xcode.
cd backend
npm run build
npm test
npm run lint| Comando | Resultado |
|---|---|
npm run build |
Compila TypeScript a dist/ y resuelve aliases del resultado compilado. |
npm test |
Ejecuta Jest sobre archivos *.spec.ts. |
npm run lint |
Valida los archivos TypeScript de src/. |
Las pruebas actuales se concentran principalmente en casos de uso de usuarios, amistades, mensajes, deportes, canchas, reservas, grupos y tokens push.
cd frontend
npm run build
npm test
npm run lint| Comando | Resultado |
|---|---|
npm run build |
Genera aplicación web en www/, por defecto con configuración productiva. |
npm test |
Ejecuta pruebas Angular/Karma. |
npm run lint |
Ejecuta reglas Angular ESLint. |
El archivo backend/docker-compose.yml construye el Dockerfile, publica 3000:3000, carga .env y monta una cuenta de servicio Firebase como archivo de solo lectura.
cd backend
docker compose up -d --buildEl Dockerfile utiliza compilación multi-etapa:
- Instala dependencias de compilación.
- Construye TypeScript.
- Instala solo dependencias de producción.
- Ejecuta
node dist/main.jssobre Node 22 Alpine.
backend/vercel.json enruta todas las solicitudes al artefacto compilado dist/main.js. Antes de publicar deben configurarse las variables de Firebase, CORS y, si aplica, el proveedor IA en el entorno de despliegue.
La aplicación utiliza conexiones Socket.IO persistentes para presencia y chat. Un runtime serverless de ejecución corta no sustituye un servidor WebSocket persistente; para operar todas las funciones en tiempo real debe desplegarse el backend en un entorno Node de larga ejecución, por ejemplo mediante la imagen Docker, o separar el servicio realtime en infraestructura compatible.
environment.prod.ts contiene la URL productiva de API y WebSocket. La compilación productiva reemplaza automáticamente environment.ts y deja la salida web en frontend/www/, que también es consumida por Capacitor.
flowchart LR
subgraph Dispositivos
WEB["Navegador"]
ANDROID["Aplicación Android"]
IOS["Aplicación iOS"]
end
subgraph Aplicacion
STATIC["Frontend compilado www"]
API["Backend Node persistente<br/>Express + Socket.IO"]
end
subgraph Servicios
FIREBASE["Firebase"]
AI["Proveedor IA"]
MAPBOX["Mapbox"]
end
WEB --> STATIC
ANDROID --> API
IOS --> API
STATIC --> API
API --> FIREBASE
API --> AI
WEB --> MAPBOX
ANDROID --> MAPBOX
IOS --> MAPBOX
Para soportar chat y presencia, la instancia que aloja Socket.IO debe aceptar conexiones persistentes y compartir el mismo entorno de datos Firebase que procesa la API REST.
- Firebase ID Token protege la mayoría de endpoints funcionales mediante
firebaseAuthMiddleware. - Socket.IO valida opcionalmente token Firebase; los clientes autenticados reciben su sala privada.
- El backend restringe orígenes CORS HTTP y WebSocket a listas configurables.
- Las claves de servicio Firebase, claves de IA y otros secretos del backend deben mantenerse en variables del entorno o gestores de secretos.
- La configuración web de Firebase y el token público de mapas del frontend deben limitarse con reglas y restricciones del proveedor; nunca deben otorgar privilegios administrativos.
- Storage debe operar con reglas adecuadas y validación de tipos/tamaños; el servidor ya valida tipo MIME y tamaño antes de subir imágenes.
- Las reglas de rol importantes deben mantenerse en backend, aunque el frontend oculte rutas o botones por rol.
- Se recomienda mantener Swagger actualizado cuando se agreguen o modifiquen endpoints.
- El frontend registra o inicia sesión mediante los repositorios HTTP de
features/auth. - Google Sign-In obtiene un token Firebase desde el cliente y lo envía a
/api/auth/google. - Los tokens de sesión se guardan en
localStorageosessionStoragesegún la opción de recordar sesión. AuthInterceptoradjunta el token a las llamadas posteriores.- El backend verifica el token con Firebase Admin y agrega la identidad a la solicitud.
sequenceDiagram
actor U as Usuario
participant UI as Ionic Angular
participant FW as Firebase Web Auth
participant API as Backend API
participant FI as Firebase Identity Toolkit
participant FA as Firebase Admin
participant FS as Firestore
alt Correo y contraseña
U->>UI: Ingresa credenciales
UI->>API: POST /api/auth/login
API->>FI: signInWithPassword
FI-->>API: ID token y refresh token
else Google Sign-In
U->>UI: Selecciona Google
UI->>FW: Abrir autenticación
FW-->>UI: ID token
UI->>API: POST /api/auth/google
API->>FA: Verificar ID token
API->>FA: Crear custom token
API->>FI: Intercambiar custom token
end
API->>FS: Consultar o crear perfil
API-->>UI: Sesión y usuario
UI->>UI: Persistir tokens
UI->>API: Solicitudes con Bearer token
API->>FA: verifyIdToken()
FA-->>API: uid autenticado
- Un usuario
court_landlordregistra una cancha con ubicación, deportes, servicios, precio e imágenes. - Las imágenes se validan y almacenan en Firebase Storage; la cancha se persiste en Firestore.
- El arrendador establece disponibilidad semanal.
- Un usuario habilitado consulta disponibilidad y crea una reserva.
- El arrendador acepta o rechaza; el propietario de la reserva o de la cancha puede cancelarla según las reglas de negocio.
- Una reserva habilita reseña y alimenta métricas de uso.
sequenceDiagram
actor L as Arrendador
actor D as Deportista
participant FL as Frontend arrendador
participant FD as Frontend deportista
participant API as Backend
participant STORE as Firebase Storage
participant DB as Firestore
L->>FL: Registra cancha e imágenes
FL->>API: POST /api/courts/create
API->>STORE: Subir imágenes validadas
API->>DB: Guardar cancha
L->>FL: Define horarios
FL->>API: PUT /api/courts/:id/availability
API->>DB: Guardar disponibilidad
D->>FD: Explora y elige cancha
FD->>API: GET /api/courts/:id/availability
API-->>FD: Slots disponibles
D->>FD: Solicita horario
FD->>API: POST /api/courts/:id/reservations
API->>DB: Reserva pending
L->>FL: Revisa solicitud
FL->>API: POST /api/reservations/:id/accept
API->>DB: Reserva confirmed
D->>FD: Consulta reservas personales
FD->>API: GET /api/reservations/me
API-->>FD: Reserva confirmed
D->>FD: Califica experiencia
FD->>API: POST /api/reservations/:id/review
API->>DB: Guardar reseña
- Tras autenticarse, el frontend conecta
SocketServiceusando el token vigente. - Para chat privado se usan salas de conversación y eventos de envío, entrega, lectura y escritura.
- Para chat grupal el usuario entra a
group:<groupId>y los mensajes nuevos se publican a la sala. - Los eventos registrados para solicitudes de amistad, aceptación de amistad, mensajes y notificaciones de sistema pueden originar notificaciones push mediante tokens asociados al usuario.
flowchart LR
USER["Usuario autenticado"] --> COMM["Crear o unirse a comunidad"]
COMM --> MEMBER["Membresía aprobada"]
MEMBER --> POST["Crear publicación"]
POST --> LIKE["Reacciones"]
POST --> COMMENT["Comentarios"]
USER --> GROUP["Crear o integrar grupo deportivo"]
GROUP --> ATT["Confirmar asistencia"]
GROUP --> CHAT["Chat grupal"]
GROUP --> BOOKING["Asociar reserva de cancha"]
Las comunidades agrupan interacción social y moderación interna; los grupos representan la coordinación de una actividad concreta y pueden enlazarse con una reserva válida.
flowchart LR
ATHLETE["Deportista"] --> FILTERS["Preferencias, deporte, radio y precio"]
FILTERS --> API["Discover / recommendations chat"]
API --> DB[("Canchas en Firestore")]
API --> PROVIDER{"Proveedor configurado"}
PROVIDER -->|Credencial OpenRouter| OPEN["OpenRouter"]
PROVIDER -->|Credencial Gemini| GEM["Gemini"]
PROVIDER -->|Sin credencial| NOOP["Respuesta sin IA generativa"]
DB --> RESULT["Canchas candidatas"]
OPEN --> RESULT
GEM --> RESULT
NOOP --> RESULT
RESULT --> ATHLETE
| Área | Archivo principal |
|---|---|
| Arranque backend | backend/src/main.ts |
| Configuración backend | backend/src/shared/env/envConfig.ts |
| Inyección de dependencias | backend/src/infrastructure/config/container.ts |
| Firebase Admin | backend/src/infrastructure/config/firebase.ts |
| REST API | backend/src/infrastructure/http/routes/ |
| Socket.IO | backend/src/infrastructure/websocket/SocketServer.ts |
| Eventos de socket | backend/src/interfaces/websocket/events.ts |
| Aplicación Angular | frontend/src/app/app.module.ts |
| Rutas Angular | frontend/src/app/app-routing.module.ts |
| Servicios globales | frontend/src/app/core/ |
| Configuración frontend | frontend/src/environments/ |
| Configuración móvil | frontend/capacitor.config.ts |
Actualizar este documento cuando ocurra alguno de los siguientes cambios:
- Nueva ruta HTTP o evento Socket.IO.
- Nueva variable de entorno o proveedor externo.
- Cambio en roles, autorización o reglas de reserva.
- Nueva colección Firestore o cambio de estructura persistida.
- Cambio de comandos de construcción, pruebas o despliegue.
- Cambio en configuración móvil, API productiva o estrategia de autenticación.