Skip to content

A poker tournament publishing system with real-time updating clocks.Frontend using React + Redux + Thunk + Web Socket + axios + Material-UI. Backend using express + express-ws + PostgreSQL.

Notifications You must be signed in to change notification settings

yb7984/tour-for-all-express

Repository files navigation

Tour For All

I have been working as a poker dealer for over 10 years. Every day I work I need to deal with poker tournaments and looking at the tournament clocks all the time. An idea came up to me I want to make my tournament clock one day and share it with everyone.

Here is the project. Everyone can find tournaments and see the real-time updated clocks online. Tournament hosts can run the same tournament in different rooms even in different cities, everyone would see the same clock with the same information no matter where you are.

Authors

Sunbao Wu@yb7984
Email: bobowu@outlook.com
Linkedin: https://www.linkedin.com/in/sunbao-wu/

Tech Stack

Node.js React express.js PostgreSQL

create-react-app React Testing Library React Router React-Redux Redux-Persist Redux-thunk

Material-UI jsonwebtoken axios moment

Amazon S3 bcrypt jsonschema express-ws heroku surge

Demo

Github

Screen shot & Video

  • Running Clock

    [Running Clock]

  • Copy Tournament

    [Copy Tournament]

Components

Please check it out at tour-for-all-react.

Database schema

Database schema

API Reference

  • Authorization

    • Login

Returns JWT token which can be used to authenticate further requests.

  POST /auth/token
Request JSON Body
{
  "username": "your username",
  "password": "your password" 
}
Response

if successfully login, return status 201

{
    "token": "Your token"
}

else

{
    "error": {
        "message": "Invalid username/password",
        "status": 401
    }
}
  • Register

Returns JWT token which can be used to authenticate further requests.

  POST /auth/register
Request JSON Body
{
  "username": "your username",
  "password": "your password",
  "firstName": "first name", 
  "lastName": "last name", 
  "email": "email"
}
Response

if successfully, return status 201

{
    "token": "Your token"
}

else

{
    "error": {
        "message": "Duplicate username:<your username>",
        "status": 400
    }
}
  • Users

    • List

Returns list of all users.

Authorization required: login as admin
  GET /users
Request JSON Body
{}
Response
{
  users: [user1, user2]
}
  • Get

Returns User.

Authorization required: none
  GET /users/:username
Request JSON Body
{}
Response
{
  user: User
}
  • Insert

Adds a new user.This returns the newly created user and an authentication token for them.

Authorization required: login as admin
  POST /users
Request JSON Body
{
  "username": "your username",
  "password": "your password",
  "firstName": "first name", 
  "lastName": "last name", 
  "email": "email",
  "role": 0 or 1
}
Response

if successfully, return status 201

{
    "user": User
    "token": "Your token"
}

else

{
    "error": {
        "message": "Bad Request",
        "status": 400
    }
}
{
    "error": {
        "message": "Duplicate username:",
        "status": 400
    }
}
  • Update

Update a user.This returns the updated user.

Authorization required: login as admin or current user
  PATCH /users/:username
Request JSON Body
{
  "password": "your password",
  "firstName": "first name", 
  "lastName": "last name", 
  "email": "email",
  "phone":"XXXXXXXXXX",
  "image":"image",
  "role": 0 or 1
}
Response

if successfully, return status 200

{
    "user": User
}

else

{
    "error": {
        "message": "Bad Request",
        "status": 400
    }
}
  • Delete

Delete a User

Authorization required: login as admin or current user
  DELETE /users/:username
Request JSON Body
{
}

##### **Response**

```json
{
  "deleted": username
}

OR

if this user has joined or created some tournaments

{
  "deactivated": username
}
  • Tours

    • List

Returns list of tours.

Authorization required: none
  GET /tours
Request Query String
param value
listType any of private,joined,upcoming,all,running,past,cancel,favorite
username current username
term search term
creator username of tournament creator
isActive true or false
status any of 0,1,9,10
minPrice minimum price, must be 0 or greater
maxPrice maxmum price, must be 0 or greater
minGuaranteed minimum guaranteed, must be 0 or greater
maxGuaranteed minimum guaranteed, must be 0 or greater
page current page, must be 1 or greater
perPage record per page, must be 1 or greater
Response
{
  tours: [tour1, tour2 , ....],
  page,
  total,
  perPage
}
  • Get

Returns Tour.

Authorization required: none
  GET /tours/:handle

handle can be id or slug

Request JSON Body
{}
Response
{
  tour: Tour
}
  • Insert

Adds a new tour.This returns the newly created tour.

Authorization required: login
  POST /tours
Request JSON Body
{
  "slug": "tour slug",
  "title": "title",   // required
  "image": "image", 
  "guaranteed": "guaranteed prize pool, integer of 0 or greater", 
  "stack": "chip stack, integer of 1 or greater",
  "description": "description",
  "price": "purchase price, integer of 0 or greater",
  "entryFee": "entry fee, integer of 0 or greater",
  "start": "start time of tour, string of datetime",  //required
  "setting": "stringified json object",
}
Response

if successfully, return status 201

{
    "tour": Tour
}

else

{
    "error": {
        "message": "Bad Request",
        "status": 400
    }
}
  • Update

Update a tour. This return a updated Tour.

Authorization required: login as admin or creator
  PATCH /tours/:handle
Request JSON Body
{
  "slug": "tour slug",
  "title": "title",   
  "image": "image", 
  "guaranteed": "guaranteed prize pool, integer of 0 or greater", 
  "stack": "chip stack, integer of 1 or greater",
  "description": "description",
  "price": "purchase price, integer of 0 or greater",
  "entryFee": "entry fee, integer of 0 or greater",
  "start": "start time of tour, string of datetime",  
  "setting": "stringified json object",
  "clockSetting": "stringified json object",
  "status": "tour status, integer",
  "isActive": true or false
}
Response

if successfully, return status 200

{
    "tour": Tour
}

else

{
    "error": {
        "message": "Bad Request",
        "status": 400
    }
}
  • Delete

Delete a Tour.

Authorization required: login as admin or creator
  DELETE /tours/:handle
Request JSON Body
{
}

##### **Response**

```json
{
  "deleted": tourId
}

OR

if this tour has started

{
  "deactivated": tourId
}
  • Follow

Follow a Tour.

Authorization required: login as admin or current user
  POST /tours/:handle/follow/:username
Request JSON Body
{
}

##### **Response**

```json
{
  "defollow": tourId
}
  • Defollow

Defollow a Tour.

Authorization required: login as admin or current user
  DELETE /tours/:handle/follow/:username
Request JSON Body
{
}

##### **Response**

```json
{
  "follow": tourId
}
  • TourPlayers

    • Insert

Attend a tour

Authorization required: login as admin or current user
  POST /tours/:handle/players/:username
Request JSON Body
{
}

##### **Response**

```json
{
  "player": TourPlayer
}
  • Update

Update a tour player

Authorization required: login as admin or creator
  PATCH /tours/:handle/players/:username
Request JSON Body
{
  "prize": "the prize the player got",
  "place": "Integer, the place of the player got at the tour"
}

##### **Response**

```json
{
  "player": TourPlayer
}
  • Delete

Unattend a tour

Authorization required: login as admin or creator
  DELETE /tours/:handle/players/:username
Request JSON Body
{
}

##### **Response**

```json
{
  "deleted": username
}
  • Clocks

    • Get Connection

  WS /tours/:handle/clock

Messages

- Join
{
  "type": "join",
  "name": "username" or uuid(),
  "clockManager": true or false
}
- Sync
{
  "type": "sync",
  "data": Clock
}

Environment Variables

To run this project, you will need to add the following environment variables to your .env file

param default value description
SECRET_KEY secret-dev Secret key for this app
PORT 3002 the port running for this app
NODE_ENV set to "test" when doing the test
DATABASE_URL tour_for_all_test when testing, tour_for_all when not testing
UPLOAD_DIR uploads the folder name for uploading data
UPLOAD_URL /uploads the url for upload folder
S3_UPLOAD false if the app using amazon s3 to upload image
AWS_ACCESS_KEY_ID access key id for amazon service
AWS_SECRET_ACCESS_KEY access key for amazon service
AWS_S3_BUCKET tourforall amazon s3 bucket name

About

A poker tournament publishing system with real-time updating clocks.Frontend using React + Redux + Thunk + Web Socket + axios + Material-UI. Backend using express + express-ws + PostgreSQL.

Topics

Resources

Stars

Watchers

Forks