Skip to content

Repository files navigation

🏋️ RyStarGym

Full-stack gym management system: marketing landing page + member portal + admin portal, backed by a JWT-secured Node/Express API and MySQL.

Node React Vite TailwindCSS MySQL JWT License

Preview

App Preview

📖 About

RyStarGym is a single-page web app for a fictional gym, built to practice end-to-end product development: a public landing page, a member-facing portal, and an admin back-office, all sharing one MySQL database and a role-based JWT auth system (separate secrets for admin and user sessions).

It covers real business logic beyond basic CRUD — membership expiry enforcement, prorated upgrades/downgrades, weekly class-capacity resets, daily check-ins, and PDF receipt generation — rather than just a static demo.

✨ Features

Landing Page

  • Hero, programs, pricing, testimonials, and call-to-action sections.

Member Portal

  • Register/login with JWT auth (password hashed with bcrypt).
  • Purchase or extend membership (multi-month, extends from existing expiry if still active).
  • Upgrade/downgrade plans with automatic proration (pay the difference, or switch free if downgrading).
  • Book classes with weekly limit + per-class weekly capacity enforcement.
  • Daily check-in (max once per day, requires active membership).
  • Download payment receipts as PDF.
  • Update profile.

Admin Portal

  • Dashboard overview: stats widgets, recent check-ins, class utilization.
  • Member database management.
  • Membership plans & class schedule CRUD.
  • Testimonials CRUD.
  • Transaction history with search + in-browser receipt viewer.
  • Per-class booking roster.

Backend Logic

  • Membership expiry enforced on every booking/check-in request; expired memberships auto-cleared.
  • Weekly scheduler resets class_bookings every Sunday to free up capacity.
  • Dummy payment flow generates a row in payments + a PDF receipt on disk.

🛠️ Tech Stack

Layer Stack
Frontend React 19, React Router 6, Tailwind CSS 4, Vite 7
Backend Node.js, Express 4, JWT (jsonwebtoken), bcryptjs
Database MySQL (mysql2)
File handling multer (uploads), pdfkit (receipt PDFs)
Tooling ESLint, dotenv, morgan

📂 Project Structure

GymMembership/
├── backend/
│   ├── config/         # db, env, server bootstrap
│   ├── controllers/     # request handlers (admin, member, booking, payment, ...)
│   ├── middleware/       # JWT auth (admin + user)
│   ├── models/           # data access layer (one per entity)
│   ├── routes/           # Express routers
│   ├── sql/               # schema + seed + migrations
│   ├── receipts/           # generated PDF receipts
│   └── uploads/             # user-uploaded files
├── server/
│   └── index.js              # backend entrypoint
├── src/
│   ├── components/
│   │   ├── home/                # landing page sections
│   │   ├── user/                # member portal
│   │   ├── admin/                # admin portal
│   │   └── layout/                # header/footer
│   ├── config/api.js              # frontend API client config
│   └── App.jsx
└── vite.config.js

🗄️ Data Model

[users] ──current membership──▶ [memberships] ──payments/history──▶ [payments]
   │  id, name, email, password,                 id, name,
   │  membership_id (FK), expires_at,            weekly_class_limit,
   │  streak                                     monthly_price
   │
   ├──▶ [user_membership_history]   (user_id, membership_id, selected_at)
   │
   └──▶ [class_bookings] ──▶ [class_sessions]
          (user_id, class_session_id,         (class_name, day_of_week,
           status, booked_at)                  start/end_time, coach,
                                                capacity, location)

Other supporting tables: dashboard_* (admin overview widgets), testimonials, homepage_content.

🚀 Getting Started

Prerequisites

  • Node.js 18+
  • MySQL 8+

1. Install dependencies

npm install

2. Configure environment

cp .env.example .env.local
Variable Description
VITE_API_BASE_URL Frontend → backend API base URL
PORT Backend port (default 4000)
CLIENT_ORIGIN Allowed CORS origin (frontend dev URL)
ADMIN_USERNAME / ADMIN_PASSWORD Seeded admin login
ADMIN_JWT_SECRET / USER_JWT_SECRET Separate JWT signing secrets per role
DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_NAME MySQL connection
UPLOAD_DIR Where uploaded files are stored

3. Provision database schema + sample data

mysql -u root -p data_rystargym < backend/sql/schema.sql
mysql -u root -p data_rystargym < backend/sql/migrations/001_add_admin_username.sql
mysql -u root -p data_rystargym < backend/sql/seed_members.sql
mysql -u root -p data_rystargym < backend/sql/seed_dashboard.sql
mysql -u root -p data_rystargym < backend/sql/seed_home.sql
mysql -u root -p data_rystargym < backend/sql/seed_admin.sql

seed_members.sql adds 5 sample active members. seed_dashboard.sql fills admin overview widgets, seed_home.sql seeds landing page content, and seed_admin.sql creates the demo admin account below.

4. Run the backend

npm run server

API base: http://localhost:4000/api

5. Run the frontend

npm run dev

🔑 Key Business Rules

Flow Behavior
Activate/extend membership POST /users/membership (no payment) or POST /payments/dummy (dummy pay + receipt). Supports multi-month; extends from current expiry if still active.
Upgrade/downgrade Cheaper/equal plan → switches immediately, expiry unchanged. Pricier plan → charges the difference for the remaining period, expiry unchanged.
Expiry enforcement Booking/check-in rejected once membership_expires_at has passed; membership auto-cleared on next profile/booking/check-in access.
Class booking Checked against weekly_class_limit (0 = unlimited) and the class's weekly capacity. class_bookings is wiped every Sunday to reset capacity.
Check-in One check-in per user per day, requires an active membership.
Payments Dummy payment creates a payments row + PDF receipt in backend/receipts; admin can view it via GET /admin/payments/:id/receipt.

🔐 Demo Admin Login

Field Value
Username admin@rystar.id
Password admin123

JWT is stored in sessionStorage; sessions persist across refresh until the token expires or the user logs out.

📄 License

Licensed under the MIT License.

Author

Ryan Aric Ardhani

About

Full-stack gym membership management system — user accounts, membership tracking, and transaction/receipt records. Built with React (Vite), Tailwind CSS, Express.js, and MySQL.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages