feat: rebrand application from Padel Pro to SmashPoint

Complete rename across all layers: UI branding, package names
(@smashpoint/web, @smashpoint/shared), infrastructure (Docker,
DB config), seed data, documentation, and logo/favicon.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ivan
2026-02-08 02:46:29 +00:00
parent 242b8bad3d
commit 45ceeba9e3
27 changed files with 152 additions and 147 deletions

View File

@@ -1,4 +1,4 @@
# Dockerfile para Padel Pro # Dockerfile para SmashPoint
# Multi-stage build para optimizar el tamano de la imagen # Multi-stage build para optimizar el tamano de la imagen
# ============================================ # ============================================

View File

@@ -1,4 +1,4 @@
# Padel Pro # SmashPoint
Sistema integral de gestion para clubes de padel. Una solucion moderna y completa para administrar reservas, ventas, torneos, membresias y multiples sedes. Sistema integral de gestion para clubes de padel. Una solucion moderna y completa para administrar reservas, ventas, torneos, membresias y multiples sedes.
@@ -69,8 +69,8 @@ Sistema integral de gestion para clubes de padel. Una solucion moderna y complet
```bash ```bash
# Clonar el repositorio # Clonar el repositorio
git clone https://github.com/tu-organizacion/padel-pro.git git clone https://github.com/tu-organizacion/smashpoint.git
cd padel-pro cd smashpoint
# Instalar dependencias # Instalar dependencias
pnpm install pnpm install
@@ -99,7 +99,7 @@ La aplicacion estara disponible en `http://localhost:3000`
## Estructura del Proyecto ## Estructura del Proyecto
``` ```
padel-pro/ smashpoint/
├── apps/ ├── apps/
│ └── web/ # Aplicacion Next.js principal │ └── web/ # Aplicacion Next.js principal
│ ├── app/ │ ├── app/
@@ -137,7 +137,7 @@ Crear un archivo `.env` en `apps/web/` con las siguientes variables:
```env ```env
# Base de datos # Base de datos
DATABASE_URL="postgresql://usuario:password@localhost:5432/padel_pro?schema=public" DATABASE_URL="postgresql://usuario:password@localhost:5432/smashpoint_db?schema=public"
# NextAuth # NextAuth
NEXTAUTH_SECRET="tu-clave-secreta-aqui" NEXTAUTH_SECRET="tu-clave-secreta-aqui"
@@ -211,8 +211,8 @@ Despues de ejecutar el seed, puedes acceder con:
| Usuario | Password | Rol | | Usuario | Password | Rol |
|---------|----------|-----| |---------|----------|-----|
| `admin@padelpro.com` | `admin123` | Super Admin | | `admin@smashpoint.com` | `admin123` | Super Admin |
| `recepcion@padelpro.com` | `recepcion123` | Recepcionista | | `recepcion@smashpoint.com` | `recepcion123` | Recepcionista |
> **IMPORTANTE:** Cambiar estas credenciales inmediatamente en entornos de produccion. > **IMPORTANTE:** Cambiar estas credenciales inmediatamente en entornos de produccion.
@@ -254,7 +254,7 @@ Este proyecto esta bajo la Licencia MIT. Ver el archivo [LICENSE](LICENSE) para
``` ```
MIT License MIT License
Copyright (c) 2024 Padel Pro Copyright (c) 2024 SmashPoint
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,4 +1,4 @@
DATABASE_URL="postgresql://user:password@localhost:5432/padel_pro?schema=public" DATABASE_URL="postgresql://user:password@localhost:5432/smashpoint_db?schema=public"
NEXTAUTH_SECRET="your-secret-key-here" NEXTAUTH_SECRET="your-secret-key-here"
NEXTAUTH_URL="http://localhost:3000" NEXTAUTH_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000" NEXT_PUBLIC_APP_URL="http://localhost:3000"

View File

@@ -55,8 +55,8 @@ export default function SettingsPage() {
const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null); const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);
// Organization state // Organization state
const [orgName, setOrgName] = useState("Padel Pro Demo"); const [orgName, setOrgName] = useState("SmashPoint Demo");
const [orgEmail, setOrgEmail] = useState("info@padelpro.com"); const [orgEmail, setOrgEmail] = useState("info@smashpoint.com");
const [orgPhone, setOrgPhone] = useState("+52 555 123 4567"); const [orgPhone, setOrgPhone] = useState("+52 555 123 4567");
const [currency, setCurrency] = useState("MXN"); const [currency, setCurrency] = useState("MXN");
const [timezone, setTimezone] = useState("America/Mexico_City"); const [timezone, setTimezone] = useState("America/Mexico_City");

View File

@@ -11,29 +11,20 @@ function LoginContent() {
<div className="max-w-md text-center"> <div className="max-w-md text-center">
{/* Logo */} {/* Logo */}
<div className="mb-8 flex justify-center"> <div className="mb-8 flex justify-center">
<div className="w-24 h-24 bg-white/10 backdrop-blur-sm rounded-2xl flex items-center justify-center border border-white/20"> <div className="w-24 h-24 bg-amber-500/20 backdrop-blur-sm rounded-2xl flex items-center justify-center border border-amber-400/30">
<svg <svg viewBox="0 0 100 100" className="w-16 h-16" fill="none">
viewBox="0 0 100 100" {/* Lightning bolt / smash icon */}
className="w-16 h-16 text-white" <path d="M55 10L20 55h25l-10 35L70 45H45l10-35z" fill="#FBBF24" />
fill="currentColor" {/* Impact sparks */}
> <circle cx="78" cy="18" r="4" fill="#FBBF24" opacity="0.8" />
{/* Padel racket stylized icon */} <circle cx="85" cy="28" r="2.5" fill="#FBBF24" opacity="0.6" />
<ellipse cx="50" cy="40" rx="28" ry="35" fill="none" stroke="currentColor" strokeWidth="4" /> <circle cx="72" cy="10" r="2" fill="#FBBF24" opacity="0.5" />
<line x1="50" y1="75" x2="50" y2="95" stroke="currentColor" strokeWidth="6" strokeLinecap="round" />
<circle cx="35" cy="30" r="3" />
<circle cx="50" cy="25" r="3" />
<circle cx="65" cy="30" r="3" />
<circle cx="35" cy="45" r="3" />
<circle cx="50" cy="40" r="3" />
<circle cx="65" cy="45" r="3" />
<circle cx="42" cy="55" r="3" />
<circle cx="58" cy="55" r="3" />
</svg> </svg>
</div> </div>
</div> </div>
{/* Title */} {/* Title */}
<h1 className="text-4xl font-bold mb-4">Padel Pro</h1> <h1 className="text-4xl font-bold mb-4">SmashPoint</h1>
{/* Tagline */} {/* Tagline */}
<p className="text-xl text-primary-200 mb-8"> <p className="text-xl text-primary-200 mb-8">
@@ -104,25 +95,15 @@ function LoginContent() {
<div className="w-full lg:w-1/2 flex flex-col justify-center items-center p-6 lg:p-12"> <div className="w-full lg:w-1/2 flex flex-col justify-center items-center p-6 lg:p-12">
{/* Mobile Logo */} {/* Mobile Logo */}
<div className="lg:hidden mb-8 text-center text-white"> <div className="lg:hidden mb-8 text-center text-white">
<div className="w-16 h-16 mx-auto mb-4 bg-white/10 backdrop-blur-sm rounded-xl flex items-center justify-center border border-white/20"> <div className="w-16 h-16 mx-auto mb-4 bg-amber-500/20 backdrop-blur-sm rounded-xl flex items-center justify-center border border-amber-400/30">
<svg <svg viewBox="0 0 100 100" className="w-10 h-10" fill="none">
viewBox="0 0 100 100" <path d="M55 10L20 55h25l-10 35L70 45H45l10-35z" fill="#FBBF24" />
className="w-10 h-10 text-white" <circle cx="78" cy="18" r="4" fill="#FBBF24" opacity="0.8" />
fill="currentColor" <circle cx="85" cy="28" r="2.5" fill="#FBBF24" opacity="0.6" />
> <circle cx="72" cy="10" r="2" fill="#FBBF24" opacity="0.5" />
<ellipse cx="50" cy="40" rx="28" ry="35" fill="none" stroke="currentColor" strokeWidth="4" />
<line x1="50" y1="75" x2="50" y2="95" stroke="currentColor" strokeWidth="6" strokeLinecap="round" />
<circle cx="35" cy="30" r="3" />
<circle cx="50" cy="25" r="3" />
<circle cx="65" cy="30" r="3" />
<circle cx="35" cy="45" r="3" />
<circle cx="50" cy="40" r="3" />
<circle cx="65" cy="45" r="3" />
<circle cx="42" cy="55" r="3" />
<circle cx="58" cy="55" r="3" />
</svg> </svg>
</div> </div>
<h1 className="text-2xl font-bold">Padel Pro</h1> <h1 className="text-2xl font-bold">SmashPoint</h1>
<p className="text-sm text-primary-200 mt-1">Sistema de Gestion para Clubes de Padel</p> <p className="text-sm text-primary-200 mt-1">Sistema de Gestion para Clubes de Padel</p>
</div> </div>
@@ -130,7 +111,7 @@ function LoginContent() {
{/* Footer */} {/* Footer */}
<p className="mt-8 text-center text-sm text-primary-300"> <p className="mt-8 text-center text-sm text-primary-300">
&copy; {new Date().getFullYear()} Padel Pro. Todos los derechos reservados. &copy; {new Date().getFullYear()} SmashPoint. Todos los derechos reservados.
</p> </p>
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth'; import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth'; import { authOptions } from '@/lib/auth';
import { db } from '@/lib/db'; import { db } from '@/lib/db';
import { createBookingSchema } from '@padel-pro/shared'; import { createBookingSchema } from '@smashpoint/shared';
import { Decimal } from '@prisma/client/runtime/library'; import { Decimal } from '@prisma/client/runtime/library';
// Helper function to check if a time is premium (after 18:00 or weekend) // Helper function to check if a time is premium (after 18:00 or weekend)

View File

@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth'; import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth'; import { authOptions } from '@/lib/auth';
import { db } from '@/lib/db'; import { db } from '@/lib/db';
import { createClientSchema } from '@padel-pro/shared'; import { createClientSchema } from '@smashpoint/shared';
// GET /api/clients - List/search clients // GET /api/clients - List/search clients
export async function GET(request: NextRequest) { export async function GET(request: NextRequest) {

6
apps/web/app/icon.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
<rect width="32" height="32" rx="8" fill="#F59E0B"/>
<path d="M17.5 3L6.5 17h8l-3 12L22.5 15H14.5l3-12z" fill="white"/>
<circle cx="25" cy="6" r="1.5" fill="white" opacity="0.8"/>
<circle cx="27" cy="9" r="1" fill="white" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 326 B

View File

@@ -5,10 +5,10 @@ import "./globals.css";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Padel Pro", title: "SmashPoint",
description: "Sistema de Gestión para Clubes de Pádel", description: "Sistema de Gestión para Clubes de Pádel",
keywords: ["padel", "club", "reservas", "gestión", "deportes"], keywords: ["padel", "club", "reservas", "gestión", "deportes"],
authors: [{ name: "Padel Pro Team" }], authors: [{ name: "SmashPoint Team" }],
}; };
export default function RootLayout({ export default function RootLayout({

View File

@@ -4,8 +4,19 @@ export default function Home() {
return ( return (
<main className="min-h-screen flex flex-col items-center justify-center bg-gradient-to-br from-primary-50 to-primary-100"> <main className="min-h-screen flex flex-col items-center justify-center bg-gradient-to-br from-primary-50 to-primary-100">
<div className="text-center space-y-8 px-4"> <div className="text-center space-y-8 px-4">
{/* Logo */}
<div className="flex justify-center">
<div className="w-20 h-20 bg-amber-500 rounded-2xl flex items-center justify-center shadow-lg">
<svg viewBox="0 0 40 40" className="w-12 h-12 text-white" fill="none">
<path d="M22 4L8 22h10l-4 14L28 18H18l4-14z" fill="currentColor" />
<circle cx="32" cy="8" r="2" fill="currentColor" opacity="0.8" />
<circle cx="35" cy="12" r="1.2" fill="currentColor" opacity="0.6" />
<circle cx="30" cy="4" r="1" fill="currentColor" opacity="0.5" />
</svg>
</div>
</div>
<h1 className="text-5xl md:text-6xl font-bold text-primary-800"> <h1 className="text-5xl md:text-6xl font-bold text-primary-800">
Padel Pro SmashPoint
</h1> </h1>
<p className="text-xl md:text-2xl text-primary-600 max-w-2xl mx-auto"> <p className="text-xl md:text-2xl text-primary-600 max-w-2xl mx-auto">
Sistema de Gestion para Clubes de Padel Sistema de Gestion para Clubes de Padel

View File

@@ -38,10 +38,17 @@ export function Sidebar() {
<aside className="fixed left-0 top-0 z-40 h-screen w-64 border-r border-primary-200 bg-white"> <aside className="fixed left-0 top-0 z-40 h-screen w-64 border-r border-primary-200 bg-white">
{/* Logo Section */} {/* Logo Section */}
<div className="flex h-16 items-center gap-3 border-b border-primary-200 px-6"> <div className="flex h-16 items-center gap-3 border-b border-primary-200 px-6">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary text-white font-bold text-lg"> <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-500">
P <svg viewBox="0 0 40 40" className="w-7 h-7 text-white" fill="none">
{/* Lightning bolt / smash icon */}
<path d="M22 4L8 22h10l-4 14L28 18H18l4-14z" fill="currentColor" />
{/* Impact spark */}
<circle cx="32" cy="8" r="2" fill="currentColor" opacity="0.8" />
<circle cx="35" cy="12" r="1.2" fill="currentColor" opacity="0.6" />
<circle cx="30" cy="4" r="1" fill="currentColor" opacity="0.5" />
</svg>
</div> </div>
<span className="text-xl font-semibold text-primary-800">Padel Pro</span> <span className="text-xl font-semibold text-primary-800">SmashPoint</span>
</div> </div>
{/* Navigation */} {/* Navigation */}

View File

@@ -1,7 +1,7 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
output: "standalone", output: "standalone",
transpilePackages: ["@padel-pro/shared"], transpilePackages: ["@smashpoint/shared"],
images: { images: {
remotePatterns: [ remotePatterns: [
{ protocol: "https", hostname: "res.cloudinary.com" }, { protocol: "https", hostname: "res.cloudinary.com" },

View File

@@ -1,11 +1,11 @@
{ {
"name": "@padel-pro/web", "name": "@smashpoint/web",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@padel-pro/web", "name": "@smashpoint/web",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@prisma/client": "^5.10.0", "@prisma/client": "^5.10.0",

View File

@@ -1,5 +1,5 @@
{ {
"name": "@padel-pro/web", "name": "@smashpoint/web",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
@@ -14,7 +14,7 @@
"db:seed": "tsx prisma/seed.ts" "db:seed": "tsx prisma/seed.ts"
}, },
"dependencies": { "dependencies": {
"@padel-pro/shared": "*", "@smashpoint/shared": "*",
"@prisma/client": "^5.10.0", "@prisma/client": "^5.10.0",
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-dropdown-menu": "^2.0.6",

View File

@@ -40,8 +40,8 @@ async function main() {
const organization = await prisma.organization.create({ const organization = await prisma.organization.create({
data: { data: {
name: 'Padel Pro Demo', name: 'SmashPoint Demo',
slug: 'padel-pro-demo', slug: 'smashpoint-demo',
settings: { settings: {
currency: 'MXN', currency: 'MXN',
timezone: 'America/Mexico_City', timezone: 'America/Mexico_City',
@@ -64,7 +64,7 @@ async function main() {
slug: 'sede-norte', slug: 'sede-norte',
address: 'Av. Universidad 1000, Col. Del Valle', address: 'Av. Universidad 1000, Col. Del Valle',
phone: '+52 55 1234 5678', phone: '+52 55 1234 5678',
email: 'norte@padelpro.com', email: 'norte@smashpoint.com',
timezone: 'America/Mexico_City', timezone: 'America/Mexico_City',
openTime: '07:00', openTime: '07:00',
closeTime: '23:00', closeTime: '23:00',
@@ -74,7 +74,7 @@ async function main() {
slug: 'sede-sur', slug: 'sede-sur',
address: 'Av. Insurgentes 2000, Col. Roma', address: 'Av. Insurgentes 2000, Col. Roma',
phone: '+52 55 2345 6789', phone: '+52 55 2345 6789',
email: 'sur@padelpro.com', email: 'sur@smashpoint.com',
timezone: 'America/Mexico_City', timezone: 'America/Mexico_City',
openTime: '08:00', openTime: '08:00',
closeTime: '22:00', closeTime: '22:00',
@@ -84,7 +84,7 @@ async function main() {
slug: 'sede-centro', slug: 'sede-centro',
address: 'Calle Reforma 500, Centro Historico', address: 'Calle Reforma 500, Centro Historico',
phone: '+52 55 3456 7890', phone: '+52 55 3456 7890',
email: 'centro@padelpro.com', email: 'centro@smashpoint.com',
timezone: 'America/Mexico_City', timezone: 'America/Mexico_City',
openTime: '06:00', openTime: '06:00',
closeTime: '24:00', closeTime: '24:00',
@@ -159,7 +159,7 @@ async function main() {
const adminUser = await prisma.user.create({ const adminUser = await prisma.user.create({
data: { data: {
organizationId: organization.id, organizationId: organization.id,
email: 'admin@padelpro.com', email: 'admin@smashpoint.com',
password: hashedPassword, password: hashedPassword,
firstName: 'Administrador', firstName: 'Administrador',
lastName: 'Sistema', lastName: 'Sistema',
@@ -175,9 +175,9 @@ async function main() {
// SITE ADMINS (one per site) // SITE ADMINS (one per site)
// ============================================================================= // =============================================================================
const siteAdminsData = [ const siteAdminsData = [
{ email: 'norte@padelpro.com', firstName: 'Carlos', lastName: 'Rodriguez', site: sites[0] }, { email: 'norte@smashpoint.com', firstName: 'Carlos', lastName: 'Rodriguez', site: sites[0] },
{ email: 'sur@padelpro.com', firstName: 'Maria', lastName: 'Gonzalez', site: sites[1] }, { email: 'sur@smashpoint.com', firstName: 'Maria', lastName: 'Gonzalez', site: sites[1] },
{ email: 'centro@padelpro.com', firstName: 'Luis', lastName: 'Hernandez', site: sites[2] }, { email: 'centro@smashpoint.com', firstName: 'Luis', lastName: 'Hernandez', site: sites[2] },
]; ];
for (const adminData of siteAdminsData) { for (const adminData of siteAdminsData) {
@@ -434,8 +434,8 @@ async function main() {
console.log(` - 1 Active Membership`); console.log(` - 1 Active Membership`);
console.log(''); console.log('');
console.log('Login credentials:'); console.log('Login credentials:');
console.log(' Super Admin: admin@padelpro.com / admin123'); console.log(' Super Admin: admin@smashpoint.com / admin123');
console.log(' Site Admins: norte@padelpro.com, sur@padelpro.com, centro@padelpro.com / admin123'); console.log(' Site Admins: norte@smashpoint.com, sur@smashpoint.com, centro@smashpoint.com / admin123');
console.log(''); console.log('');
} }

BIN
apps/web/public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -4,38 +4,38 @@ services:
# Base de datos PostgreSQL # Base de datos PostgreSQL
db: db:
image: postgres:16-alpine image: postgres:16-alpine
container_name: padel-pro-db container_name: smashpoint-db
restart: unless-stopped restart: unless-stopped
environment: environment:
POSTGRES_USER: ${POSTGRES_USER:-padel_user} POSTGRES_USER: ${POSTGRES_USER:-padel_user}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-padel_password} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-padel_password}
POSTGRES_DB: ${POSTGRES_DB:-padel_pro} POSTGRES_DB: ${POSTGRES_DB:-smashpoint_db}
volumes: volumes:
- postgres_data:/var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
ports: ports:
- "5432:5432" - "5432:5432"
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-padel_user} -d ${POSTGRES_DB:-padel_pro}"] test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-padel_user} -d ${POSTGRES_DB:-smashpoint_db}"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
networks: networks:
- padel-network - smashpoint-network
# Aplicacion Web Next.js # Aplicacion Web Next.js
web: web:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: padel-pro-web container_name: smashpoint-web
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy
environment: environment:
NODE_ENV: production NODE_ENV: production
DATABASE_URL: postgresql://${POSTGRES_USER:-padel_user}:${POSTGRES_PASSWORD:-padel_password}@db:5432/${POSTGRES_DB:-padel_pro}?schema=public DATABASE_URL: postgresql://${POSTGRES_USER:-padel_user}:${POSTGRES_PASSWORD:-padel_password}@db:5432/${POSTGRES_DB:-smashpoint_db}?schema=public
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET} NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000}
NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL:-http://localhost:3000} NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL:-http://localhost:3000}
@@ -50,10 +50,10 @@ services:
retries: 3 retries: 3
start_period: 40s start_period: 40s
networks: networks:
- padel-network - smashpoint-network
networks: networks:
padel-network: smashpoint-network:
driver: bridge driver: bridge
volumes: volumes:

View File

@@ -1,6 +1,6 @@
# API Reference - Padel Pro # API Reference - SmashPoint
Documentacion completa de los endpoints REST de la API de Padel Pro. Documentacion completa de los endpoints REST de la API de SmashPoint.
## Informacion General ## Informacion General

View File

@@ -1,6 +1,6 @@
# Guia de Despliegue - Padel Pro # Guia de Despliegue - SmashPoint
Esta guia cubre el proceso completo para desplegar Padel Pro en un entorno de produccion. Esta guia cubre el proceso completo para desplegar SmashPoint en un entorno de produccion.
## Tabla de Contenidos ## Tabla de Contenidos
@@ -70,8 +70,8 @@ pnpm --version # 8.x.x
```bash ```bash
cd /var/www cd /var/www
git clone https://github.com/tu-organizacion/padel-pro.git git clone https://github.com/tu-organizacion/smashpoint.git
cd padel-pro cd smashpoint
``` ```
### 4. Configurar Variables de Entorno ### 4. Configurar Variables de Entorno
@@ -84,7 +84,7 @@ Editar el archivo `.env`:
```env ```env
# Base de datos - Produccion # Base de datos - Produccion
DATABASE_URL="postgresql://padel_user:PASSWORD_SEGURO@localhost:5432/padel_pro?schema=public" DATABASE_URL="postgresql://smashpoint_user:PASSWORD_SEGURO@localhost:5432/smashpoint_db?schema=public"
# NextAuth - IMPORTANTE: Generar clave unica # NextAuth - IMPORTANTE: Generar clave unica
NEXTAUTH_SECRET="$(openssl rand -base64 32)" NEXTAUTH_SECRET="$(openssl rand -base64 32)"
@@ -135,13 +135,13 @@ sudo -u postgres psql
```sql ```sql
-- Crear usuario -- Crear usuario
CREATE USER padel_user WITH PASSWORD 'PASSWORD_SEGURO'; CREATE USER smashpoint_user WITH PASSWORD 'PASSWORD_SEGURO';
-- Crear base de datos -- Crear base de datos
CREATE DATABASE padel_pro OWNER padel_user; CREATE DATABASE smashpoint_db OWNER smashpoint_user;
-- Otorgar permisos -- Otorgar permisos
GRANT ALL PRIVILEGES ON DATABASE padel_pro TO padel_user; GRANT ALL PRIVILEGES ON DATABASE smashpoint_db TO smashpoint_user;
-- Salir -- Salir
\q \q
@@ -159,10 +159,10 @@ Editar `/etc/postgresql/16/main/pg_hba.conf`:
```conf ```conf
# Conexion local # Conexion local
local all padel_user md5 local all smashpoint_user md5
# Conexion remota (si es necesario) # Conexion remota (si es necesario)
host padel_pro padel_user 192.168.1.0/24 md5 host smashpoint_db smashpoint_user 192.168.1.0/24 md5
``` ```
Reiniciar PostgreSQL: Reiniciar PostgreSQL:
@@ -174,7 +174,7 @@ sudo systemctl restart postgresql
### 4. Ejecutar Migraciones ### 4. Ejecutar Migraciones
```bash ```bash
cd /var/www/padel-pro cd /var/www/smashpoint
pnpm db:generate pnpm db:generate
pnpm db:push pnpm db:push
``` ```
@@ -204,8 +204,8 @@ Crear `ecosystem.config.js` en la raiz del proyecto:
module.exports = { module.exports = {
apps: [ apps: [
{ {
name: 'padel-pro', name: 'smashpoint',
cwd: '/var/www/padel-pro/apps/web', cwd: '/var/www/smashpoint/apps/web',
script: 'node_modules/next/dist/bin/next', script: 'node_modules/next/dist/bin/next',
args: 'start', args: 'start',
instances: 'max', instances: 'max',
@@ -220,8 +220,8 @@ module.exports = {
}, },
// Configuracion de logs // Configuracion de logs
log_date_format: 'YYYY-MM-DD HH:mm:ss Z', log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
error_file: '/var/log/padel-pro/error.log', error_file: '/var/log/smashpoint/error.log',
out_file: '/var/log/padel-pro/out.log', out_file: '/var/log/smashpoint/out.log',
merge_logs: true, merge_logs: true,
// Reinicio automatico // Reinicio automatico
max_memory_restart: '1G', max_memory_restart: '1G',
@@ -234,8 +234,8 @@ module.exports = {
### 3. Crear Directorio de Logs ### 3. Crear Directorio de Logs
```bash ```bash
sudo mkdir -p /var/log/padel-pro sudo mkdir -p /var/log/smashpoint
sudo chown $USER:$USER /var/log/padel-pro sudo chown $USER:$USER /var/log/smashpoint
``` ```
### 4. Iniciar la Aplicacion ### 4. Iniciar la Aplicacion
@@ -258,16 +258,16 @@ pm2 save
pm2 status pm2 status
# Ver logs # Ver logs
pm2 logs padel-pro pm2 logs smashpoint
# Reiniciar # Reiniciar
pm2 restart padel-pro pm2 restart smashpoint
# Recargar sin downtime # Recargar sin downtime
pm2 reload padel-pro pm2 reload smashpoint
# Detener # Detener
pm2 stop padel-pro pm2 stop smashpoint
# Monitoreo # Monitoreo
pm2 monit pm2 monit
@@ -285,7 +285,7 @@ sudo apt install nginx
### 2. Crear Configuracion del Sitio ### 2. Crear Configuracion del Sitio
Crear `/etc/nginx/sites-available/padel-pro`: Crear `/etc/nginx/sites-available/smashpoint`:
```nginx ```nginx
# Redirigir HTTP a HTTPS # Redirigir HTTP a HTTPS
@@ -326,8 +326,8 @@ server {
add_header Strict-Transport-Security "max-age=63072000" always; add_header Strict-Transport-Security "max-age=63072000" always;
# Logs # Logs
access_log /var/log/nginx/padel-pro.access.log; access_log /var/log/nginx/smashpoint.access.log;
error_log /var/log/nginx/padel-pro.error.log; error_log /var/log/nginx/smashpoint.error.log;
# Tamano maximo de subida # Tamano maximo de subida
client_max_body_size 10M; client_max_body_size 10M;
@@ -362,7 +362,7 @@ server {
# Archivos estaticos # Archivos estaticos
location /static { location /static {
alias /var/www/padel-pro/apps/web/public; alias /var/www/smashpoint/apps/web/public;
expires 30d; expires 30d;
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
} }
@@ -372,7 +372,7 @@ server {
### 3. Habilitar el Sitio ### 3. Habilitar el Sitio
```bash ```bash
sudo ln -s /etc/nginx/sites-available/padel-pro /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/smashpoint /etc/nginx/sites-enabled/
# Verificar configuracion # Verificar configuracion
sudo nginx -t sudo nginx -t
@@ -430,10 +430,10 @@ El archivo `docker-compose.yml` ya esta incluido en el proyecto. Ubicado en `/ro
Crear `.env` en la raiz del proyecto: Crear `.env` en la raiz del proyecto:
```env ```env
POSTGRES_USER=padel_user POSTGRES_USER=smashpoint_user
POSTGRES_PASSWORD=PASSWORD_SEGURO POSTGRES_PASSWORD=PASSWORD_SEGURO
POSTGRES_DB=padel_pro POSTGRES_DB=smashpoint_db
DATABASE_URL=postgresql://padel_user:PASSWORD_SEGURO@db:5432/padel_pro?schema=public DATABASE_URL=postgresql://smashpoint_user:PASSWORD_SEGURO@db:5432/smashpoint_db?schema=public
NEXTAUTH_SECRET=tu-clave-secreta-generada NEXTAUTH_SECRET=tu-clave-secreta-generada
NEXTAUTH_URL=https://tudominio.com NEXTAUTH_URL=https://tudominio.com
NEXT_PUBLIC_APP_URL=https://tudominio.com NEXT_PUBLIC_APP_URL=https://tudominio.com
@@ -474,7 +474,7 @@ docker compose ps
docker compose exec web sh docker compose exec web sh
# Backup de base de datos # Backup de base de datos
docker compose exec db pg_dump -U padel_user padel_pro > backup.sql docker compose exec db pg_dump -U smashpoint_user smashpoint_db > backup.sql
``` ```
--- ---
@@ -497,14 +497,14 @@ Crear script `/opt/scripts/backup-padel.sh`:
```bash ```bash
#!/bin/bash #!/bin/bash
BACKUP_DIR="/var/backups/padel-pro" BACKUP_DIR="/var/backups/smashpoint"
DATE=$(date +%Y%m%d_%H%M%S) DATE=$(date +%Y%m%d_%H%M%S)
FILENAME="padel_pro_$DATE.sql.gz" FILENAME="smashpoint_db_$DATE.sql.gz"
mkdir -p $BACKUP_DIR mkdir -p $BACKUP_DIR
# Crear backup # Crear backup
pg_dump -U padel_user padel_pro | gzip > "$BACKUP_DIR/$FILENAME" pg_dump -U smashpoint_user smashpoint_db | gzip > "$BACKUP_DIR/$FILENAME"
# Eliminar backups antiguos (mantener 7 dias) # Eliminar backups antiguos (mantener 7 dias)
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
@@ -526,7 +526,7 @@ crontab -e
### Actualizaciones ### Actualizaciones
```bash ```bash
cd /var/www/padel-pro cd /var/www/smashpoint
# Obtener cambios # Obtener cambios
git pull origin main git pull origin main
@@ -541,17 +541,17 @@ pnpm build
pnpm db:push pnpm db:push
# Reiniciar aplicacion # Reiniciar aplicacion
pm2 reload padel-pro pm2 reload smashpoint
``` ```
### Logs ### Logs
```bash ```bash
# Logs de la aplicacion # Logs de la aplicacion
pm2 logs padel-pro --lines 100 pm2 logs smashpoint --lines 100
# Logs de Nginx # Logs de Nginx
tail -f /var/log/nginx/padel-pro.error.log tail -f /var/log/nginx/smashpoint.error.log
# Logs de PostgreSQL # Logs de PostgreSQL
tail -f /var/log/postgresql/postgresql-16-main.log tail -f /var/log/postgresql/postgresql-16-main.log
@@ -569,7 +569,7 @@ RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL)
if [ $RESPONSE != "200" ]; then if [ $RESPONSE != "200" ]; then
echo "ERROR: Health check failed with status $RESPONSE" echo "ERROR: Health check failed with status $RESPONSE"
# Enviar alerta (email, Slack, etc.) # Enviar alerta (email, Slack, etc.)
pm2 restart padel-pro pm2 restart smashpoint
fi fi
``` ```
@@ -611,13 +611,13 @@ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
```bash ```bash
# Verificar logs # Verificar logs
pm2 logs padel-pro --err pm2 logs smashpoint --err
# Verificar puertos # Verificar puertos
netstat -tlnp | grep 3000 netstat -tlnp | grep 3000
# Verificar conexion a DB # Verificar conexion a DB
psql -U padel_user -h localhost padel_pro -c "SELECT 1" psql -U smashpoint_user -h localhost smashpoint_db -c "SELECT 1"
``` ```
### Error de conexion a base de datos ### Error de conexion a base de datos
@@ -630,7 +630,7 @@ sudo systemctl status postgresql
tail -f /var/log/postgresql/postgresql-16-main.log tail -f /var/log/postgresql/postgresql-16-main.log
# Probar conexion # Probar conexion
psql "postgresql://padel_user:PASSWORD@localhost:5432/padel_pro" psql "postgresql://smashpoint_user:PASSWORD@localhost:5432/smashpoint_db"
``` ```
### Nginx devuelve 502 ### Nginx devuelve 502
@@ -643,7 +643,7 @@ pm2 status
sudo nginx -t sudo nginx -t
# Ver logs # Ver logs
tail -f /var/log/nginx/padel-pro.error.log tail -f /var/log/nginx/smashpoint.error.log
``` ```
--- ---

View File

@@ -1,4 +1,4 @@
# Padel Pro - Documento de Diseño # SmashPoint - Documento de Diseño
**Fecha:** 2026-02-01 **Fecha:** 2026-02-01
**Estado:** Aprobado **Estado:** Aprobado
@@ -59,7 +59,7 @@ Sistema integral de gestión para cadena de clubes de pádel con múltiples sede
``` ```
┌────────────────────────────────────────────────────────────┐ ┌────────────────────────────────────────────────────────────┐
PADEL PRO - MÓDULOS │ SMASHPOINT - MÓDULOS │
├──────────────┬──────────────┬──────────────┬───────────────┤ ├──────────────┬──────────────┬──────────────┬───────────────┤
│ RESERVAS │ TORNEOS │ POS │ MEMBRESÍAS │ │ RESERVAS │ TORNEOS │ POS │ MEMBRESÍAS │
│ │ │ │ │ │ │ │ │ │
@@ -465,7 +465,7 @@ enum MatchStatus {
## Estructura del Proyecto ## Estructura del Proyecto
``` ```
padel-pro/ smashpoint/
├── apps/ ├── apps/
│ ├── web/ # Next.js (Admin + API) │ ├── web/ # Next.js (Admin + API)
│ │ ├── app/ │ │ ├── app/

View File

@@ -1,4 +1,4 @@
# Padel Pro - Plan de Implementación # SmashPoint - Plan de Implementación
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
@@ -71,7 +71,7 @@ Create `turbo.json`:
```json ```json
{ {
"name": "padel-pro", "name": "smashpoint",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "turbo dev", "dev": "turbo dev",
@@ -165,7 +165,7 @@ git commit -m "chore: initialize monorepo with Turborepo and pnpm"
Create `apps/web/package.json`: Create `apps/web/package.json`:
```json ```json
{ {
"name": "@padel-pro/web", "name": "@smashpoint/web",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
@@ -179,7 +179,7 @@ Create `apps/web/package.json`:
"next": "14.2.0", "next": "14.2.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"@padel-pro/shared": "workspace:*" "@smashpoint/shared": "workspace:*"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.11.0", "@types/node": "^20.11.0",
@@ -199,7 +199,7 @@ Create `apps/web/next.config.js`:
```javascript ```javascript
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
transpilePackages: ["@padel-pro/shared"], transpilePackages: ["@smashpoint/shared"],
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
@@ -363,7 +363,7 @@ import "./globals.css";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Padel Pro - Sistema de Gestión", title: "SmashPoint - Sistema de Gestión",
description: "Sistema integral de gestión para clubes de pádel", description: "Sistema integral de gestión para clubes de pádel",
}; };
@@ -389,7 +389,7 @@ export default function Home() {
<main className="flex min-h-screen flex-col items-center justify-center p-24"> <main className="flex min-h-screen flex-col items-center justify-center p-24">
<div className="text-center"> <div className="text-center">
<h1 className="text-4xl font-bold text-primary mb-4"> <h1 className="text-4xl font-bold text-primary mb-4">
Padel Pro SmashPoint
</h1> </h1>
<p className="text-xl text-slate-600"> <p className="text-xl text-slate-600">
Sistema de Gestión para Clubes de Pádel Sistema de Gestión para Clubes de Pádel
@@ -431,7 +431,7 @@ git commit -m "feat(web): add Next.js 14 app with Tailwind CSS"
Create `packages/shared/package.json`: Create `packages/shared/package.json`:
```json ```json
{ {
"name": "@padel-pro/shared", "name": "@smashpoint/shared",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"main": "./src/index.ts", "main": "./src/index.ts",
@@ -1154,7 +1154,7 @@ enum MatchStatus {
Create `apps/web/.env.example`: Create `apps/web/.env.example`:
```env ```env
# Database # Database
DATABASE_URL="postgresql://user:password@localhost:5432/padel_pro?schema=public" DATABASE_URL="postgresql://user:password@localhost:5432/smashpoint_db?schema=public"
# Auth # Auth
NEXTAUTH_SECRET="your-secret-key-here" NEXTAUTH_SECRET="your-secret-key-here"
@@ -1737,7 +1737,7 @@ export function Sidebar() {
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary text-white font-bold"> <div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary text-white font-bold">
P P
</div> </div>
<span className="text-xl font-bold text-primary">Padel Pro</span> <span className="text-xl font-bold text-primary">SmashPoint</span>
</Link> </Link>
</div> </div>
@@ -2116,7 +2116,7 @@ import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth"; import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth"; import { authOptions } from "@/lib/auth";
import { db } from "@/lib/db"; import { db } from "@/lib/db";
import { createBookingSchema } from "@padel-pro/shared"; import { createBookingSchema } from "@smashpoint/shared";
export async function GET(req: NextRequest) { export async function GET(req: NextRequest) {
const session = await getServerSession(authOptions); const session = await getServerSession(authOptions);

4
package-lock.json generated
View File

@@ -1,10 +1,10 @@
{ {
"name": "padel-pro", "name": "smashpoint",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "padel-pro", "name": "smashpoint",
"devDependencies": { "devDependencies": {
"turbo": "^2.0.0" "turbo": "^2.0.0"
} }

View File

@@ -1,5 +1,5 @@
{ {
"name": "padel-pro", "name": "smashpoint",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "turbo dev", "dev": "turbo dev",

View File

@@ -1,11 +1,11 @@
{ {
"name": "@padel-pro/shared", "name": "@smashpoint/shared",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@padel-pro/shared", "name": "@smashpoint/shared",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"zod": "^3.22.4" "zod": "^3.22.4"

View File

@@ -1,5 +1,5 @@
{ {
"name": "@padel-pro/shared", "name": "@smashpoint/shared",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"main": "./src/index.ts", "main": "./src/index.ts",

2
pnpm-lock.yaml generated
View File

@@ -14,7 +14,7 @@ importers:
apps/web: apps/web:
dependencies: dependencies:
'@padel-pro/shared': '@smashpoint/shared':
specifier: '*' specifier: '*'
version: link:../../packages/shared version: link:../../packages/shared
'@prisma/client': '@prisma/client':

View File

@@ -1,8 +1,8 @@
-- Padel Pro Database Initialization -- SmashPoint Database Initialization
-- This script runs when PostgreSQL container starts for the first time -- This script runs when PostgreSQL container starts for the first time
-- Enable UUID extension if needed -- Enable UUID extension if needed
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Grant privileges -- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE padel_pro TO padel; GRANT ALL PRIVILEGES ON DATABASE smashpoint_db TO padel;