Skip to content

Repository files navigation

🏸 Majadu App

React TypeScript Vite Tailwind CSS Supabase PWA

The operational app for running badminton sessions end to end — planning, scheduling, live scoring, tournaments, and social export.


✨ Features

🎯 Session Planning

  • Configure courts, time slots, player count, and game duration
  • Define fixed-match constraints with time & court pinning
  • Generate balanced doubles schedules with quality analysis
  • Retry generation for optimal partner/opponent distribution

🔴 Live Session Control

  • Publish sessions and share via URL
  • Mark games played, enter/revise scores
  • Swap players, teams, and game slots
  • Change individual players in specific games
  • Mark players absent (excluded from leaderboard)
  • Lock session to prevent further edits

📊 Player Stats & History

  • Browse historical sessions
  • Per-player career stats (W/L, points, partners, opponents)
  • Real-time leaderboard with on-the-fly computation

🏆 Tournament

  • 16 pairs → 4 groups → round-robin → knockout bracket
  • Automatic bracket propagation
  • Match PIC assignment
  • Scoreboard overlay

📸 Social Export

  • Instagram-style post & story graphics (1080×1350 / 1080×1920)
  • Leaderboard export (absent players filtered)
  • Tournament bracket & standings visuals

🛠️ Tech Stack

Layer Technology
Framework React 19 + TypeScript 6
Build Vite 8
Styling Tailwind CSS v4
State Zustand (local) + TanStack React Query (server)
Routing React Router v7
Backend Supabase (PostgreSQL + PostgREST RPC)
PWA vite-plugin-pwa
DnD @dnd-kit/core

🚀 Quick Start

1. Install

npm ci

2. Configure

cp .env.local.example .env.local
# Fill in VITE_SUPABASE_URL and VITE_SUPABASE_KEY

3. Apply Migrations

Apply the SQL migrations from supabase/migrations/ to your Supabase project.

4. Run

npm run dev

🧪 Verification

# Static checks (types + lint + tailwind + regression)
npm run check

# Supabase smoke tests
source .env.local && npm run check:smoke

📁 Project Structure

src/
├── components/     # Shared UI components (SummaryModal, ShareButton, etc.)
├── config/         # Instagram template configs
├── generator/      # Schedule generation algorithm (pure TS)
├── hooks/          # Custom React hooks
├── pages/          # Route pages (Setup, Players, Generate, etc.)
├── queries/        # React Query hooks + Supabase RPC endpoints
├── store/          # Zustand stores (session, tournament)
└── utils/          # Utility functions (swap, standings, canvas, etc.)

🔐 Security Model

RPC Access Notes
publish_session anon Rejects writes when status ≠ 'draft'
get_session anon Read-only
list_sessions anon Returns lock status
delete_session anon Rejects deletion of locked sessions
unlock_session service_role Admin-only, not in UI
register_player anon Idempotent with TOCTOU fix

📖 Documentation


🏗️ Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Local State   │ ←→  │  Domain Logic   │ ←→  │  Remote State   │
│    (Zustand)    │     │ (Generator/Utils)│     │   (Supabase)    │
└─────────────────┘     └─────────────────┘     └─────────────────┘
        ↓                       ↓                       ↓
   localStorage           Pure Functions          PostgREST RPC

🤝 Relationship to MDEF

App Role
Majadu App Operations — session planning, live control, tournaments
MDEF Analytics — canonical players, match history, ratings

📄 License

Private project.

About

A badminton session scheduler web app. Built with React + TypeScript + Zustand + Tailwind (Vite)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages