Skip to content

arkanemystic/event-loop

Repository files navigation

EventLoop - Event Transportation App

A full-stack event transportation application built with Next.js, Node.js, Express, Socket.io, and PostgreSQL. Designed for event transportation within a 10-mile radius with smart driver dispatch and real-time tracking.

Features

Core Functionality

  • Smart Dispatch Algorithm: Assigns the best driver based on proximity and availability
  • Real-time Updates: Socket.io for live location tracking and trip status
  • Trip Queuing: Drivers can handle up to 2 trips (1 active + 1 queued)
  • Fixed Locations: Passengers select from predefined pickup/dropoff points
  • Role-Based Access: Separate interfaces for Passengers, Drivers, and Admins

Passenger Features

  • Browser geolocation to detect current location
  • Select destination from predefined locations
  • View pickup location on map
  • Real-time trip status updates
  • Driver assignment notifications with ETA
  • Socket-based ride updates

Driver Features

  • Online/Offline toggle
  • Continuous background location tracking (watchPosition)
  • Location updates emitted every 5 seconds
  • View current and queued trips
  • Google Maps deep link navigation
  • Start/Complete trip actions
  • Visual queue indicator for next ride

Technical Highlights

  • Haversine Formula: Distance calculation without external APIs
  • PostGIS: Spatial queries for proximity matching
  • Monorepo Structure: Organized /client and /server
  • Mobile-First PWA: Responsive design with bottom navigation
  • TypeScript Ready: Can be migrated to TypeScript

Tech Stack

Frontend (/client)

  • Framework: Next.js 14 (Pages Router)
  • Styling: Tailwind CSS
  • Icons: Lucide React
  • Maps: Mapbox GL JS
  • Real-time: Socket.io Client
  • HTTP: Axios

Backend (/server)

  • Runtime: Node.js
  • Framework: Express.js
  • Real-time: Socket.io
  • Database: PostgreSQL (Supabase)
  • Spatial: PostGIS

Project Structure

event-loop/
├── client/                    # Next.js frontend
│   ├── components/
│   │   ├── Layout.js         # Mobile-responsive layout
│   │   ├── MapView.js        # Mapbox map component
│   │   └── ProtectedRoute.js # Auth wrapper
│   ├── context/
│   │   └── UserContext.js    # Global user state
│   ├── lib/
│   │   ├── api.js            # REST API client
│   │   └── socket.js         # Socket.io client
│   ├── pages/
│   │   ├── login.js          # Authentication
│   │   ├── passenger/
│   │   │   └── index.js      # Request ride interface
│   │   ├── driver/
│   │   │   └── index.js      # Drive interface
│   │   └── admin/
│   │       └── index.js      # Admin dashboard
│   └── styles/
│       └── globals.css       # Tailwind + custom styles
│
├── server/                    # Express backend
│   ├── src/
│   │   ├── config/
│   │   │   └── database.js   # PostgreSQL pool
│   │   ├── controllers/
│   │   │   └── tripController.js
│   │   ├── routes/
│   │   │   ├── auth.js
│   │   │   ├── trips.js
│   │   │   └── locations.js
│   │   ├── services/
│   │   │   └── dispatchService.js  # Smart dispatch algorithm
│   │   ├── socket/
│   │   │   └── handlers.js   # Socket.io events
│   │   ├── utils/
│   │   │   └── distance.js   # Haversine formula
│   │   └── index.js          # Main server
│   └── db/
│       ├── schema.sql         # Database schema
│       └── seed.sql           # Sample data
│
└── README.md                  # This file

Setup Instructions

Prerequisites

  • Node.js 16+
  • PostgreSQL 14+ with PostGIS extension
  • Mapbox account (free tier) for maps

1. Clone Repository

git clone <repository-url>
cd event-loop

2. Database Setup

Option A: Supabase (Recommended)

  1. Create account at supabase.com
  2. Create new project
  3. Go to SQL Editor
  4. Run server/db/schema.sql
  5. Run server/db/seed.sql
  6. Copy connection string from Settings → Database

Option B: Local PostgreSQL

# Install PostgreSQL and PostGIS
brew install postgresql postgis  # macOS
# or
sudo apt-get install postgresql postgis  # Linux

# Create database
createdb eventloop
psql eventloop -c "CREATE EXTENSION IF NOT EXISTS postgis;"

# Run schema and seed
psql eventloop -f server/db/schema.sql
psql eventloop -f server/db/seed.sql

3. Backend Setup

cd server
npm install

# Create .env file
cp .env.example .env

Edit server/.env:

PORT=5000
DATABASE_URL=postgresql://username:password@localhost:5432/eventloop
NODE_ENV=development
CLIENT_URL=http://localhost:3000

Start server:

npm run dev

Server runs on http://localhost:5000

4. Frontend Setup

cd client
npm install

# Create .env.local file
cp .env.example .env.local

Edit client/.env.local:

NEXT_PUBLIC_API_URL=http://localhost:5000
NEXT_PUBLIC_SOCKET_URL=http://localhost:5000
NEXT_PUBLIC_MAPBOX_TOKEN=pk.your_mapbox_token_here

Get Mapbox token at mapbox.com/account/access-tokens

Start client:

npm run dev

Client runs on http://localhost:3000

Demo Credentials

Passengers (10 accounts)

  • Username: passenger1 to passenger10
  • Password: pass123

Drivers (5 accounts)

  • Username: driver1 to driver5
  • Password: driver123

Admins (3 accounts)

  • Username: admin1 to admin3
  • Password: admin123

Usage Flow

Passenger Flow

  1. Login as passenger1 / pass123
  2. Browser requests geolocation permission
  3. Select destination from dropdown
  4. Click "Request Ride"
  5. System finds nearest pickup location
  6. Smart dispatch finds best driver
  7. Modal shows assigned driver with ETA
  8. Trip status updates in real-time

Driver Flow

  1. Login as driver1 / driver123
  2. Click "Go Online" button
  3. Browser requests location permission
  4. Location tracked continuously (watchPosition)
  5. Updates sent to server every 5 seconds
  6. Wait for ride assignment (socket event)
  7. View trip details (pickup/dropoff)
  8. Click "Navigate to Pickup" → Opens Google Maps
  9. Click "Start Trip" when passenger picked up
  10. Click "Navigate to Dropoff" → Opens Google Maps
  11. Click "Complete Trip" when finished
  12. If queued trip exists, it automatically becomes active

Creating a New Event

  1. Navigate to /create-event
  2. Enter an Event Name (required)
  3. Optionally set a Slug — auto-derived from the name if left blank (e.g. "Acme Summit" → acme-summit)
  4. Click Create Event
  5. On success, the page shows:
    • Event name and slug
    • Auto-generated admin username (e.g. admin@acme-summit)
    • A one-time Login Token — copy it before navigating away
  6. Click Go to Admin Login to be taken to /login with the token pre-filled and auto-submitted

The login token is only shown once. If lost, a new one must be generated directly in the database.

Smart Dispatch Algorithm

Located in server/src/services/dispatchService.js:

  1. Fetch online drivers with < 2 active trips
  2. Calculate scores:
    • IDLE drivers: Direct time to pickup (Haversine distance ÷ 30mph)
    • BUSY drivers: (Time to dropoff) + (Time from dropoff to new pickup)
  3. Return driver with lowest score
  4. Queue trip if driver is BUSY (set queued_order = 1)

API Endpoints

Tenants

  • POST /api/tenants - Create a new tenant and auto-generate its admin user. Returns { tenant, admin: { username, login_token } }. No X-Tenant-ID header required.

Authentication

  • POST /api/auth/login - Login user
  • POST /api/auth/token-login - Login via magic link token (no X-Tenant-ID required)
  • GET /api/auth/me/:userId - Get user details

Locations

  • GET /api/locations - Get all locations
  • GET /api/locations/:id - Get location by ID

Trips

  • POST /api/trips/request - Request ride
  • POST /api/trips/:id/complete - Complete trip
  • GET /api/trips/driver/:driverId - Get driver's trips
  • GET /api/trips/passenger/:passengerId - Get passenger's trips

Socket.io Events

Client → Server

authenticate

socket.emit('authenticate', { user_id: 4, role: 'driver' });

update_location (Driver only)

socket.emit('update_location', {
  user_id: 4,
  latitude: 40.7128,
  longitude: -74.0060
});

driver_status_change

socket.emit('driver_status_change', {
  user_id: 4,
  is_online: true
});

trip_status_update

socket.emit('trip_status_update', {
  trip_id: 1,
  status: 'IN_PROGRESS',
  driver_id: 4
});

Server → Client

connection_success - Connection established

new_ride - New trip assigned

{
  trip: { /* trip details */ },
  isQueued: false,
  queuePosition: 0
}

trip_status_update - Trip status changed

driver_location_update - Driver location changed (admin only)

admin_dashboard_update - Full dashboard data (admin only)

Database Schema

users

  • id, username, password, role (passenger/driver/admin)

drivers

  • user_id, is_online, current_lat, current_long, current_socket_id, status (IDLE/BUSY)

locations

  • id, name, latitude, longitude

trips

  • id, passenger_id, driver_id, pickup_location_id, dropoff_location_id
  • status (REQUESTED/ASSIGNED/IN_PROGRESS/COMPLETED)
  • queued_order (0 = current, 1+ = queued)

Development

Run Tests

# Backend tests (when implemented)
cd server
npm test

# Frontend tests (when implemented)
cd client
npm test

Build for Production

# Backend
cd server
npm start

# Frontend
cd client
npm run build
npm start

Environment Variables

Backend (server/.env)

PORT=5000
DATABASE_URL=postgresql://...
NODE_ENV=production
CLIENT_URL=https://your-frontend.com

Frontend (client/.env.local)

NEXT_PUBLIC_API_URL=https://your-backend.com
NEXT_PUBLIC_SOCKET_URL=https://your-backend.com
NEXT_PUBLIC_MAPBOX_TOKEN=pk.your_token

Deployment

Backend (Render, Railway, Heroku)

  1. Push to GitHub
  2. Connect repository to hosting platform
  3. Set environment variables
  4. Deploy

Frontend (Vercel, Netlify)

  1. Push to GitHub
  2. Connect repository to Vercel
  3. Set environment variables
  4. Deploy

Database (Supabase)

Already cloud-hosted. Just use connection string in production.

Future Enhancements

  • Admin dashboard with live map
  • Trip history pages
  • Driver ratings and reviews
  • Price calculation
  • Payment integration
  • Push notifications (FCM)
  • Service worker for offline support
  • Real routing with OSRM or Mapbox Directions
  • Driver earnings dashboard
  • Trip cancellation
  • Multi-language support
  • Unit and integration tests

Troubleshooting

"Map unavailable" error

  • Set NEXT_PUBLIC_MAPBOX_TOKEN in client/.env.local
  • Get token at mapbox.com/account/access-tokens

Socket connection fails

  • Check backend is running on correct port
  • Verify NEXT_PUBLIC_SOCKET_URL matches backend URL
  • Check CORS settings in server/src/index.js

Location not updating

  • Grant location permissions in browser
  • Check browser console for errors
  • Verify driver is "Online"

Database connection error

  • Check DATABASE_URL is correct
  • Verify PostgreSQL is running
  • Ensure PostGIS extension is enabled

License

Apache 2.0

Contributors

Devakh Rashie

About

A full-stack ride-sharing application built with Next.js, Node.js, Express, Socket.io, and PostgreSQL. Designed for event transportation with smart driver dispatch and real-time tracking.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors