Respi

Reserva de pistas · móvil y web

App para reservar pistas deportivas con pago integrado. Proyecto final de DAM en equipo de tres; mi parte, los pagos con Stripe de extremo a extremo.

Autoría
Colaborativo · 3 desarrolladores
Rol
Pagos y flujo de reserva
Contexto
Proyecto final de ciclo · DAM
Periodo
Sep 2025 – Jul 2026
Plataformas
Android · iOS · Web
  • Primer paso de una reserva: selector de día y lista de pistas con su precio por hora y la disponibilidad de la jornada.
  • Pantalla de inicio de Respi con las reservas activas, la próxima reserva y accesos para reservar o ver las pistas.
  • Detalle de una reserva confirmada con fecha, horario, importe y un código QR de verificación.

El proyecto

Reservar una pista de un polideportivo desde el móvil, de principio a fin: ver la disponibilidad, elegir hora, pagar con tarjeta y presentar un código en la instalación. La administración lo gestiona todo desde su propio panel.

Respi conecta a los usuarios de un polideportivo con sus pistas: consultar disponibilidad, reservar, pagar y valorar. La administración tiene su propio panel para gestionar pistas, horarios, precios, reservas, usuarios y pagos.

Es el proyecto final de DAM de un equipo de tres personas. La aplicación está hecha con React Native y Expo, con una sola base de código para Android, iOS y web, y consume una API REST propia en NestJS con MariaDB, desplegada en un VPS.

Funcionalidades principales

  • Disponibilidad de cada pista por franja horaria
  • Reserva en tres pasos: pista, datos y confirmación
  • Pago con tarjeta y reembolso al cancelar
  • Código QR para validar la reserva en la instalación
  • Panel de administración: pistas, horarios, precios, usuarios y pagos
  • Una sola base de código para Android, iOS y web

Mi aportación

El repositorio lo lideró Christopher, autor de la mayor parte de la aplicación, con Javi y conmigo en áreas concretas. La mía fue acotada y de extremo a extremo: todo lo que tiene que ver con cobrar una reserva.

  • Pagos con Stripe en la API

    El módulo de NestJS completo: creación del PaymentIntent, webhook con verificación de firma, confirmación de la reserva, reembolsos al cancelar y sus tests.

  • Pagos en la app

    El hook de pago, con una implementación por plataforma tras la misma interfaz, y la pantalla de gestión de pagos del panel de administración.

  • Flujo de reserva

    La lógica de creación de reservas (tipo de pista, pista, fecha, hora, duración y confirmación) y el historial con estados, cancelación y código de verificación.

  • Arranque de la API

    Primeras entidades y relaciones de TypeORM, DTOs, seeders y documentación Swagger, en la fase inicial del proyecto.

  • Revisión final

    Pasada de corrección antes de la entrega: modales propios en lugar de alertas nativas, etiquetas de accesibilidad y arreglos en autenticación, pagos y rutas de administración.

commits de la app
56 / 493 (11 % del total)
commits de la API
49 / 511 (10 % del total)
tests propios de pagos y reservas
23
personas en el equipo
3

Commits sin fusiones en la rama principal, según el historial de Git.

Decisiones técnicas

  • El importe lo fija el servidor

    El PaymentIntent se crea en la API a partir del precio guardado de la reserva: el cliente nunca envía la cantidad. Y solo si la reserva pertenece al usuario autenticado; en otro caso, 403.

  • Un webhook que desconfía

    La confirmación llega por webhook. El endpoint lee el cuerpo sin procesar, verifica la firma de Stripe con el secreto del webhook y rechaza todo lo que no la supere. Para entornos de demostración sin webhook hay una confirmación manual autenticada.

  • Idempotencia

    Stripe puede reenviar un evento. Antes de tocar nada se comprueba el estado de la reserva: si ya está confirmada, el evento se ignora y el pago no se duplica. La misma regla impide crear un segundo PaymentIntent para una reserva pagada.

  • Un contrato, tres implementaciones

    El hook useStripePayment existe en tres ficheros y Metro elige por plataforma: hoja de pago nativa en móvil, Stripe.js en web y, en Expo Go, donde el módulo nativo no está disponible, una hoja simulada para seguir probando el flujo.

  • Cancelar no depende del reembolso

    Al cancelar una reserva confirmada se lanza el reembolso y se guardan su identificador e importe; si el pago no pasó por Stripe, solo se marca como reembolsado. La cancelación se completa aunque el reembolso falle. 23 tests cubren propiedad, firma inválida, idempotencia y reembolsos.

Evolución

  1. Sep – Nov 2025

    Arranque de la API: entidades, relaciones, DTOs, seeders y Swagger.

  2. Mar – Abr 2026

    Primeras pantallas de reserva y mejoras de la pantalla de inicio.

  3. May 2026

    Integración de Stripe en API y app, reembolsos, tests, pagos del panel de administración y revisión final.

  4. Jul 2026

    Entrega del proyecto final.

Stack

  1. App

    • React Native
    • Expo Router
    • TypeScript
    • Zustand
    • Axios
    • i18next
    • Stripe
  2. API

    • NestJS
    • TypeORM
    • MariaDB
    • JWT
    • Swagger
    • Jest
  3. Infraestructura

    • Docker Compose
    • PM2
    • GitHub Actions
    • VPS

Capturas