Futbol Veritabanı
8대 리그 클럽·선수·통계—Transfermarkt 데이터
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Trabajo Practico: Desarrollo de una Aplicacion SaaS con Next.js y Firebase Este repositorio proporciona una base tecnica para el desarrollo de una aplicacion web de tipo SaaS utilizando Next.js, Firebase Authentication, Firebase Admin SDK, Firestore y Tailwind CSS. El trabajo practico debera realizarse en grupos de 2 integrantes. Cada grupo debera definir una propuesta propia de aplicacion, disenar su modelo de datos, implementar las rutas y componentes necesarios, y desarrollar una funcionalidad principal que permita a los usuarios autenticados gestionar informacion persistente.README 전문 보기 ↗
SiezaGym es una plataforma integral de entrenamiento de fuerza, hipertrofia y acondicionamiento físico diseñada para atletas, entrenadores y administradores. Combina una aplicación web moderna (Next.js 16) con una aplicación nativa de iPhone (SwiftUI / iOS 18+), ambas conectadas en tiempo real a la misma base de datos Firebase Firestore.
Toda la lógica de entrenamiento, cálculo de marcas (1RM), registro de series, distribución de grupos musculares y seguimiento de progreso es compartida y coherente entre plataformas: lo que registrás en el gimnasio desde el iPhone impacta inmediatamente en la web y viceversa.
SiezaGym opera con un modelo de tres roles con permisos granulares y vistas adaptadas a cada necesidad:
La aplicación web está desarrollada sobre las últimas especificaciones del ecosistema React y Node:
@dnd-kit/sortable para la reordenación fluida de ejercicios en el creador de rutinas.firestore.rules) basadas en identidad y relaciones coach-alumno.HTTP-only seguras (__session).scripts/seedExercises.mjs)./api/session/login que genera una Cookie de Sesión HTTP-only de Firebase (__session).getCurrentUser() en lib/firebase/session.js, permitiendo renderizado en el servidor sin destellos de carga ni redirecciones cliente innecesarias./dashboard/coach o /admin).lib/)La lógica de negocio está completamente separada de las vistas:
lib/routines/: Creación, edición, duplicación, prescripciones parecidas vs rampa por serie, y ordenamiento de rutinas.lib/workout/: Estado activo del entrenamiento, temporizadores, sonido y cálculo de volumen.lib/sessions/: Registro de entrenamientos finalizados, cálculo de rachas continuas y estadísticas semanales.lib/coach/: Gestión de invitaciones, desvinculación y lectura de perfiles de alumnos.lib/epley.js: Algoritmo matemático unificado para la estimación de 1RM.lib/home/metrics.js: Ponderación de esfuerzo, cálculo de calorías (fórmula MET) y balance empuje/tracción./)/rutinas y /rutinas/nueva)RoutineComposer):
customExercises) especificando nombre, músculos implicados, patrón motor y equipamiento.4 × 10).12 reps @ 60kg, 10 reps @ 70kg, 8 reps @ 80kg).@dnd-kit)./rutinas/[id])RoutineScreen): El detalle de la rutina y la sesión en vivo conviven en la misma interfaz:
localStorage (activeWorkout); si se cierra la pestaña accidentalmente, el entrenamiento no se pierde./sessions./historial y /progreso)/historial/[id]), se detalla cada serie, peso, reps y el 1RM estimado alcanzado./progreso):
/progreso/[exerciseId]):
/perfil)Ubicado en /dashboard/coach, optimizado para escritorio y accesible para usuarios con isCoach: true:
/dashboard/coach/alumnos/[studentId]):
Semana 3) y notas específicas.Ubicado en /admin, accesible únicamente para los correos configurados como administradores:
La carpeta /ios contiene la aplicación nativa en SwiftUI para el alumno. Habla directamente con el mismo Firebase Firestore que la web, sin capas intermedias ni bases de datos duplicadas.
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
│ SiezaGym Web (Next.js) │ │ SiezaGym iOS (SwiftUI) │
│ - App Router │ │ - Swift 6 / iOS 18+ │
│ - React 19 │ │ - ActivityKit & WidgetKit │
│ - Firebase Client & Admin SDK │ │ - HealthKit (Apple Salud) │
└────────────────┬────────────────┘ └────────────────┬────────────────┘
│ │
│ Firebase Firestore │
└──────────────► & Auth ◄───────────────┘
SWIFT_DEFAULT_ACTOR_ISOLATION = YES, Main Actor por defecto).firebase-ios-sdk (v12) y GoogleSignIn-iOS (v9).project.yml. Toda la configuración de compilación, targets, bundles y capacidades se gestiona desde el archivo YAML para evitar conflictos de merge en .pbxproj.Models/: Modelos de datos inmutables y conformes a Sendable (Exercise, Routine, WorkoutSession, UserProfile).Domain/: Funciones matemáticas y reglas de negocio puras, sin dependencias de Firestore ni SwiftUI (port idéntico de lib/ de la web: HomeMetrics, Epley, TrainingCalendar, RoutineSummary, RestTimer).Services/: Repositorio de Firestore (GymRepository), servicio de autenticación y estado reactivo global (GymStore).DesignSystem/: Paleta SIEZA sincronizada con el CSS de la web mediante ios/scripts/sync-theme.mjs.Features/: Pantallas modulares (Inicio, Rutinas, Entrenamiento, Historial, Progreso, Perfil).SiezaGymWidgets/: Extensión de widgets y actividades en vivo.UserDefaults (sieza.onboarding.completed.v1).Actividad de hoy se conecta a HealthKit para leer:
activeEnergyBurned).stepCount).distanceWalkingRunning).Activity<WorkoutActivityAttributes> de ActivityKit:
Text(timerInterval:)), lo que garantiza cero consumo excesivo de batería.Serie 2 de 4), el peso y las repeticiones.TerminarSerieIntent): El usuario puede pulsar el botón de "Terminar serie" directamente desde la Dynamic Island o la pantalla de bloqueo para registrar la serie sin desbloquear el teléfono.App Groups.SnapshotStore) con atributo kSecAttrAccessibleAfterFirstUnlock. La app principal deposita un snapshot ligero de datos y el widget lo consume instantáneamente sin requerir sesión de Firebase ni exceder los límites de memoria de WidgetKit.RestTimer.swift): Se inicia en 90 segundos entre series y se sincroniza con el estado de la rutina.AsyncImage no anima GIFs remotos en iOS. La app utiliza ImageIO nativo para extraer los frames y renderizarlos mediante UIImageView con caché en memoria.img.youtube.com/vi/<id>/mqdefault.jpg).| Colección / Ruta | Descripción | Acceso / Reglas de Seguridad |
|---|---|---|
/users/{uid} | Perfil de usuario, peso corporal, rol, referencias al coach. | Lectura: propio usuario o coach vinculado. Escritura: propio usuario (protegiendo campos de rol). |
/users/{uid}/customExercises | Ejercicios propios creados por el usuario. | Lectura: propio usuario o su coach. Escritura: propio usuario (validando estructura muscular). |
/exercises/{exerciseId} | Catálogo maestro de 94 ejercicios (nombre, músculos, GIFs, equipamiento). | Lectura: todos los usuarios autenticados. Escritura: restringida (solo Admin SDK). |
/routines/{routineId} | Rutinas creadas por atletas o entrenadores. | Lectura y escritura: únicamente el propietario (ownerId == auth.uid). |
/assignments/{assignmentId} | Rutinas congeladas asignadas de un entrenador a un alumno. | Lectura: entrenador o alumno asignado. Escritura: únicamente el entrenador vinculado. |
/sessions/{sessionId} | Registro inmutable de entrenamientos completados con detalle serie por serie. | Lectura: atleta propietario o su entrenador. Creación: atleta autenticado (máx 40 ejercicios). |
/coaches/{coachId}/students/{studentId} | Registro de relación formal entre profesor y alumno. | Lectura: entrenador propietario. Escritura: sólo transacciones seguras del servidor. |
/invites/{code} | Códigos temporales de 6 caracteres para vinculación. | Lectura: autenticados. Creación: entrenador autenticado. Canje: Server Action seguro. |
/mfaChallenges/{challengeId} | Desafíos OTP de 6 dígitos para autenticación por correo. | Acceso totalmente bloqueado a clientes. Solo gestionado por Firebase Admin SDK. |
La plataforma implementa algoritmos idénticos en JavaScript (lib/) y Swift (Domain/):
Estimación de 1RM (Fórmula de Epley): $$\text{1RM} = \text{Peso} \times \left(1 + \frac{\text{Reps}}{30}\right)$$ (Si $\text{Reps} = 1$, $\text{1RM} = \text{Peso}$. Las series marcadas como falladas se excluyen).
Gasto Calórico Estimado (MET): $$\text{Calorías (kcal)} = \text{MET (5.0)} \times \text{Peso (kg)} \times \text{Horas de entrenamiento}$$ (Si el perfil no registra peso, se utiliza un estándar de 75 kg con advertencia visible en UI).
Reparto y Distribución Muscular:
Cada ejercicio almacena un diccionario muscleWeights que suma 1.0. El impacto de una sesión en cada grupo muscular se calcula multiplicando el tonelaje levantado ($\text{Peso} \times \text{Reps}$) por el coeficiente de participación de cada músculo.
Cálculo de Racha (Streak):
Basado en días locales consecutivos con al menos una sesión terminada. Los cálculos normalizan la fecha a la zona horaria de Argentina (America/Argentina/Buenos_Aires).
SiezaGym/
├── app/ # Next.js 16 App Router
│ ├── (app)/ # Rutas privadas de la aplicación
│ │ ├── page.js # Portada / Home del atleta
│ │ ├── rutinas/ # Listado, nueva rutina y [id] detalle/entrenamiento
│ │ ├── historial/ # Listado de entrenamientos y [id] detalle de sesión
│ │ ├── progreso/ # Dashboard de progreso y [exerciseId] evolución 1RM
│ │ ├── perfil/ # Perfil, ajustes de tema y vinculación con coach
│ │ └── layout.js # Layout base con temas y estilos
│ ├── admin/ # Panel de operaciones del Administrador
│ ├── dashboard/coach/ # Panel del Entrenador (Roster, alumnos, invitaciones)
│ ├── api/ # Endpoints HTTP (MFA, sesión con cookies)
│ ├── globals.css # Estilos globales y tokens base
│ └── design2.css # Sistema de diseño SIEZA / Design2
├── components/ # Componentes modulares de React
│ ├── design2/ # Componentes visuales del sistema SIEZA (Header, TabBar, etc.)
│ ├── coach/ # Vistas y componentes del entrenador
│ ├── progress/ # Gráficos Recharts y tablas de marcas
│ └── routines/ # Creadores de rutinas y formularios de ejercicios
├── lib/ # Lógica de dominio pura y servicios backend
│ ├── admin/ # Métricas y control de acceso de admin
│ ├── assignments/ # Lógica de asignación de rutinas coach-alumno
│ ├── coach/ # Invitaciones y vinculación
│ ├── exercises/ # Catálogo global y categorización de ejercicios
│ ├── firebase/ # Configuración de Firebase Client y Firebase Admin SDK
│ ├── home/ # Métricas de la portada y volumen semanal
│ ├── routines/ # Prescripciones, cálculo de duración y armado
│ ├── sessions/ # Gestión de sesiones y algoritmo de racha
│ └── epley.js # Algoritmo de 1RM
├── ios/ # Aplicación Nativa para iPhone (SwiftUI)
│ ├── project.yml # Especificación declarativa del proyecto (XcodeGen)
│ ├── SiezaGym/ # Código fuente de la app nativa
│ │ ├── Models/ # Entidades Sendable de Swift
│ │ ├── Domain/ # Lógica de negocio pura (HomeMetrics, Epley, etc.)
│ │ ├── Services/ # GymRepository, GymStore, Firebase iOS SDK
│ │ ├── DesignSystem/ # Tokens SIEZA sincronizados
│ │ └── Features/ # Vistas SwiftUI por pestaña y pantalla
│ ├── SiezaGymCompartido/ # Código compartido entre App y Extensión de Widgets
│ ├── SiezaGymWidgets/ # WidgetKit y Live Activities (Dynamic Island)
│ ├── SiezaGymTests/ # Tests unitarios en Swift
│ └── scripts/ # Scripts de sincronización de temas, configs y build
├── firestore.rules # Reglas de seguridad para Firestore
├── scripts/seedExercises.mjs # Script de migración y siembra de catálogo de ejercicios
├── tests/ # Suites de pruebas con Vitest
└── package.json # Dependencias y scripts de Node
Crear un archivo .env.local en la raíz del proyecto con la siguiente configuración:
# Firebase Client SDK
NEXT_PUBLIC_FIREBASE_API_KEY=tu_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=tu_proyecto.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=tu_proyecto_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=tu_proyecto.firebasestorage.app
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=tu_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=tu_app_id
# Firebase Admin SDK (Server-Side)
FIREBASE_PROJECT_ID=tu_proyecto_id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxx@tu_proyecto.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\ntu_clave_privada\n-----END PRIVATE KEY-----"
# Proveedor de Correo para MFA (Opcional en desarrollo local)
RESEND_API_KEY=re_tu_clave_resend
RESEND_FROM="SiezaGym <[email protected]>"
# Instalar dependencias
npm install
# Sembrar el catálogo de 94 ejercicios en Firestore (solo la primera vez)
npm run seed:exercises
# Iniciar el servidor de desarrollo
npm run dev
La aplicación web estará disponible en http://localhost:3000.
brew install xcodegen).Para evitar exponer claves privadas en repositorios públicos, el archivo GoogleService-Info.plist se descarga dinámicamente usando las credenciales del Admin SDK ya configuradas en el entorno:
# Desde la raíz del repositorio:
node --env-file=.env --env-file=.env.local ios/scripts/fetch-google-service-info.mjs
cd ios
xcodegen generate
open SiezaGym.xcodeproj
Para desplegar en un dispositivo real con cuenta de desarrollador gratuita:
cp Local.example.xcconfig Local.xcconfig
# Editar Local.xcconfig e ingresar tu Apple Development Team ID
./scripts/run-on-device.sh
(En el iPhone, aprobar el certificado de desarrollador en: Ajustes › General › VPN y gestión de dispositivos › Confiar en el desarrollador).
Se cuenta con 47 archivos de test que validan flujos completos, seguridad y cálculos:
# Correr todas las suites de prueba
npm run test
# Verificar linter de código
npm run lint
# Validar compilación de producción
npm run build
Pruebas unitarias de las funciones puras de Domain/, cálculo de 1RM, sincronización de temas y widgets:
xcodebuild test -project ios/SiezaGym.xcodeproj -scheme SiezaGym \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro'
Proyecto desarrollado en el marco de la carrera de Programación (UMAI) para la materia Programación 3.
Diseñado y construido por Tobías Arraiza y Valentín Sierra. Todos los derechos reservados.