feat: initialize Next.js project with Prisma, authentication, and rankings page

This commit is contained in:
2026-03-27 14:50:00 -07:00
parent 96f7cb86d3
commit 66e4baa643
208 changed files with 8522 additions and 9035 deletions
+552
View File
@@ -0,0 +1,552 @@
# EuchreCamp
A comprehensive tournament management and partnership analytics system for the card game Euchre.
## Overview
EuchreCamp is a full-stack Ruby web application built with Hanami 2.1 that provides:
- **Tournament Management**: Create and manage round-robin, single elimination, double elimination, and Swiss-style tournaments
- **Partnership Analytics**: Track partnership performance, win rates, and Elo changes between players
- **Player Profiles**: Display individual player statistics and partnership breakdowns
- **Admin Dashboard**: Centralized management interface for tournaments, players, and matches
- **Authentication & Authorization**: Role-based access control with player, tournament_admin, and club_admin roles
## Quick Start
### Prerequisites
- Ruby 3.3.3 (managed by mise or rbenv)
- Node.js 22+ (for asset compilation)
- SQLite3
- Bundler
### Installation
1. **Clone the repository:**
```bash
git clone <repository-url>
cd euchre_camp
```
2. **Install dependencies:**
```bash
bundle install
npm install
```
3. **Set up the database:**
```bash
bundle exec rake db:migrate
```
4. **Compile assets:**
```bash
./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css
```
5. **Start the server:**
```bash
bundle exec puma -p 3000 -e development
```
### Accessing the Application
- **Main Page**: http://localhost:3000
- **Admin Dashboard**: http://localhost:3000/admin
- **Rankings**: http://localhost:3000/rankings
- **Login**: http://localhost:3000/login
## Development
### Project Structure
```
euchre_camp/
├── app/
│ ├── actions/ # Hanami actions (controllers)
│ ├── assets/ # CSS, JavaScript, images
│ ├── repositories/ # ROM repositories for data access
│ ├── services/ # Business logic (Elo calculator, partnership tracker)
│ ├── templates/ # ERB view templates
│ ├── views/ # Hanami view objects
│ └── action.rb # Base action class with auth helpers
├── config/
│ ├── routes.rb # Application routes
│ ├── app.rb # Hanami app configuration
│ └── assets.js # Asset compilation configuration
├── db/
│ ├── migrate/ # Database migrations
│ └── euchre_camp.db # SQLite database
├── lib/
│ └── euchre_camp/ # Domain models and entities
├── spec/
│ └── acceptance/ # RSpec acceptance tests
└── public/
└── assets/ # Compiled assets
```
### Running the Application
**Development mode (with auto-reload):**
```bash
bundle exec puma -p 3000 -e development
```
**Production mode:**
```bash
bundle exec puma -p 3000 -e production
```
### Database Management
**Run migrations:**
```bash
bundle exec rake db:migrate
```
**Rollback last migration:**
```bash
bundle exec rake db:migrate[<version>]
```
**Reset database:**
```bash
bundle exec rake db:reset
```
### Testing
**Run all acceptance tests:**
```bash
bundle exec rspec spec/acceptance/
```
**Run specific test:**
```bash
bundle exec rspec spec/acceptance/tournament_partnership_spec.rb:280
```
**Run with documentation:**
```bash
bundle exec rspec spec/acceptance/ --format documentation
```
**Run Playwright mobile responsiveness tests:**
```bash
# Start the server
bundle exec hanami server --port 2300 &
# Run Playwright tests
bundle exec rspec spec/playwright/mobile_responsiveness_spec.rb
```
**Test with Playwright MCP (browser automation):**
1. Start the Hanami server: `bundle exec hanami server --port 2300`
2. Use opencode with Playwright MCP tools to:
- Navigate to pages
- Take screenshots
- Test responsive layouts
- Verify mobile UI elements
### Assets
**Compile CSS for development:**
```bash
./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css
```
**Watch for changes (requires separate process):**
```bash
./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css --watch
```
## Features
### Tournament Management
#### Creating a Tournament
1. Navigate to Admin Dashboard (`/admin`)
2. Click "Create Tournament"
3. Enter tournament details:
- Name
- Format (round-robin, single elimination, double elimination, Swiss)
- Number of teams/players
4. Register participants
5. Generate schedule
6. Record match results
#### Tournament Formats
- **Round-Robin**: Each team plays every other team once
- **Single Elimination**: Lose once and you're out
- **Double Elimination**: Must lose twice to be eliminated
- **Swiss**: Pairings based on win-loss records
### Partnership Analytics
#### Tracking Partnerships
The system automatically tracks:
- Games played together
- Win/loss records
- Elo changes per partnership
- Partnership win rates
#### Viewing Partnership Data
1. Visit any player's profile page (`/players/:id/profile`)
2. Scroll to "Partnership Performance" section
3. View statistics for each partner
### Player Profiles
Each player profile displays:
- Current Elo rating
- Total games played
- Win rate
- Partnership statistics
- Recent games timeline
### Admin Dashboard
The admin dashboard provides:
- Quick statistics (total players, active tournaments, recent matches)
- Quick action buttons for common tasks
- Recent matches table
- Links to all admin sections
## Authentication & Authorization
### User Roles
| Role | Permissions |
|------|-------------|
| **Player** | Edit own profile, record own matches within 5 minutes |
| **Tournament Admin** | Create/manage tournaments, edit matches in their tournaments (no time limit) |
| **Club Admin** | Full access to edit/delete any record, manage all players and tournaments |
### Login/Logout
**Login:**
- Navigate to `/login`
- Enter email and password
- Click "Login"
**Logout:**
- Click "Logout" in navigation bar
### Admin User Creation
To create an admin user, use the provided script:
```bash
ruby scripts/create_admin.rb <email> <password>
```
**Example:**
```bash
ruby scripts/create_admin.rb david@dhg.lol admin
```
This will:
1. Create a player profile
2. Create a user account with `club_admin` role
3. Mark the account as confirmed
**Manual SQL Alternative:**
If you prefer to create users manually via SQL:
1. Access the database: `sqlite3 db/euchre_camp.db`
2. Generate a BCrypt password hash:
```bash
ruby -e "require 'bcrypt'; puts BCrypt::Password.create('your_password')"
```
3. Insert a user record:
```sql
INSERT INTO players (name, rating) VALUES ('PlayerName', 1000);
INSERT INTO users (player_id, email, password_digest, role, confirmed, created_at, updated_at)
VALUES (1, 'user@example.com', '$2b$12$...', 'club_admin', 1, datetime('now'), datetime('now'));
```
## API Reference
### Routes
#### Public Routes
- `GET /` - Redirects to rankings
- `GET /rankings` - Player rankings
- `GET /players/:id` - Player profile
- `GET /players/:id/profile` - Player profile with partnerships
- `GET /players/:id/schedule` - Player tournament schedule
#### Authentication Routes
- `GET /login` - Login form
- `POST /auth/login` - Process login
- `GET /logout` - Logout and clear session
#### Admin Routes (Require Authentication)
- `GET /admin` - Admin dashboard
- `GET /admin/players` - List all players
- `GET /admin/players/new` - Add new player form
- `POST /admin/players` - Create new player
- `GET /admin/players/:id/edit` - Edit player form
- `PATCH /admin/players/:id` - Update player
- `DELETE /admin/players/:id` - Delete player
- `GET /admin/matches` - List all matches
- `GET /admin/matches/new` - Record match form
- `POST /admin/matches` - Create match
- `GET /admin/matches/:id/edit` - Edit match form
- `PATCH /admin/matches/:id` - Update match
- `GET /admin/matches/upload` - CSV upload form
- `POST /admin/matches/process_upload` - Process CSV upload
- `GET /admin/tournaments` - List all tournaments
- `GET /admin/tournaments/new` - Create tournament form
- `POST /admin/tournaments` - Create tournament
- `GET /admin/tournaments/:id` - Tournament details
- `GET /admin/tournaments/:id/edit` - Edit tournament form
- `PATCH /admin/tournaments/:id` - Update tournament
- `DELETE /admin/tournaments/:id` - Delete tournament
- `POST /admin/tournaments/:id/participants` - Add participant
- `DELETE /admin/tournaments/:id/participants/:player_id` - Remove participant
- `POST /admin/tournaments/:id/teams` - Create team
- `GET /admin/tournaments/:id/teams/:team_id/edit` - Edit team form
- `PATCH /admin/tournaments/:id/teams/:team_id` - Update team
- `DELETE /admin/tournaments/:id/teams/:team_id` - Delete team
- `POST /admin/tournaments/:id/schedule` - Generate schedule
- `GET /admin/tournaments/:id/rounds/:round_id` - View round matchups
- `GET /admin/tournaments/:id/results` - Tournament results
- `POST /admin/tournaments/:id/results` - Save results
- `POST /admin/tournaments/:id/complete` - Complete tournament
## Database Schema
### Tables
- **players**: Player information and ratings
- **users**: Authentication and authorization
- **events**: Tournaments and events
- **event_participants**: Player participation in tournaments
- **teams**: Teams in tournaments
- **tournament_rounds**: Tournament rounds
- **bracket_matchups**: Matchups per round
- **matches**: Individual match results
- **elo_snapshots**: Elo rating history
- **partnership_games**: Partnership occurrence tracking
- **partnership_stats**: Aggregated partnership statistics
## Common Tasks
### Adding a New Player
1. Navigate to Admin Dashboard
2. Click "Add Player"
3. Enter name and initial rating (default 1000)
4. Click "Create Player"
### Recording a Match
1. Navigate to Admin Dashboard
2. Click "Record Match Result"
3. Select players for Team 1 and Team 2
4. Enter scores
5. Click "Create Match"
### Creating a Tournament
1. Navigate to Admin Dashboard
2. Click "Create Tournament"
3. Enter tournament details
4. Register participants
5. Generate schedule
6. Start recording results
### Editing a Match
**Within 5 minutes (any user):**
1. Navigate to `/admin/matches`
2. Click "Edit" next to the match
3. Update scores
4. Click "Update Match"
**Anytime (tournament admin or club admin):**
- Same process as above, no time restriction
## Troubleshooting
### Common Issues
**Server won't start:**
- Check if port 3000 is already in use: `lsof -i :3000`
- Kill existing process: `kill -9 <PID>`
- Try a different port: `bundle exec puma -p 3001`
**CSS not loading:**
- Recompile assets: `./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css`
- Clear browser cache
**Database errors:**
- Run migrations: `bundle exec rake db:migrate`
- Reset database: `bundle exec rake db:reset`
**Authorization errors:**
- Ensure you're logged in
- Check user role in database
### Debugging
**Check server logs:**
```bash
tail -f /tmp/puma.log
```
**Check database:**
```bash
sqlite3 db/euchre_camp.db
sqlite> .tables
sqlite> SELECT * FROM users;
```
## Development Workflow
### Making Changes
1. Create a feature branch: `git checkout -b feature/your-feature`
2. Make changes to code
3. Run tests: `bundle exec rspec spec/acceptance/`
4. Commit with conventional commit message
5. Push to remote: `git push origin feature/your-feature`
6. Create pull request
### Commit Message Format
```
<type>: <description>
[optional body]
[optional footer]
```
Types:
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation changes
- `style`: Code style changes
- `refactor`: Code refactoring
- `test`: Test changes
- `chore`: Build/dependency changes
### Code Style
- Follow existing code patterns in the project
- Use ROM (Ruby Object Mapper) for database access
- Keep business logic in services
- Use dependency injection in actions
- Write acceptance tests for new features
## Deployment
### Production Environment
1. **Set production environment variables:**
```bash
export HANAMI_ENV=production
export DATABASE_URL=sqlite:///path/to/prod.db
export SESSION_SECRET=<secure-random-string>
```
2. **Compile assets for production:**
```bash
./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css
```
3. **Run migrations:**
```bash
bundle exec rake db:migrate
```
4. **Start server:**
```bash
bundle exec puma -p 3000 -e production
```
### Using a Process Manager
**Using systemd:**
```ini
[Unit]
Description=EuchreCamp
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/var/www/euchre_camp
Environment=HANAMI_ENV=production
ExecStart=/usr/local/bin/bundle exec puma -C config/puma.rb
Restart=always
[Install]
WantedBy=multi-user.target
```
**Using PM2 (Node.js):**
```bash
pm2 start bundle exec -- puma -C config/puma.rb
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Run tests to ensure they pass
5. Submit a pull request
## License
MIT License - see LICENSE file for details
## Credits
Built with:
- Hanami 2.1
- ROM (Ruby Object Mapper)
- SQLite3
- RSpec
- Puma
## Additional Resources
- [Hanami Documentation](https://guides.hanamirb.org/)
- [ROM Documentation](https://rom-rb.org/)
- [RSpec Documentation](https://rspec.info/)
- [Euchre Rules](https://www.pagat.com/euchre/euchre.html)