A modern, full-stack meeting room booking application built with Next.js, Express.js, and Prisma ORM. Features advanced booking management with race condition protection, soft-delete functionality, and admin capabilities.
- User Authentication: Secure user registration and login with JWT tokens
- Room Management: Create, view, and manage meeting rooms
- Booking System: Reserve rooms with time slot management
- Booking Cancellation: Cancel future bookings with soft-delete functionality
- Admin Dashboard: Advanced administrative controls
- Race Condition Protection: Transaction-based booking with FOR UPDATE locking
- Unique Constraints: Prevents double-booking of rooms using database constraints
- Soft Delete: Bookings are marked as deleted but preserved in database
- Admin Controls: Room deletion with cascade handling, user promotion
- Role-Based Access: User and Admin roles with different permissions
- Framework: Express.js with TypeScript
- Database: PostgreSQL
- ORM: Prisma 6.18.0
- Authentication: JWT (jsonwebtoken)
- Security: bcryptjs for password hashing
- Framework: Next.js 15 with App Router
- Language: TypeScript
- Styling: Tailwind CSS
- HTTP Client: Axios
- State Management: React Hooks
- Node.js 18+ and npm
- PostgreSQL database
- Docker and Docker Compose (optional, for containerized setup)
git clone https://github.com/Facelles/last_task.git
cd meeting-bookingcd backend
# Install dependencies
npm install
# Create .env file
cat > .env << EOF
DATABASE_URL="postgresql://user:password@localhost:5432/meeting_booking"
JWT_SECRET="your_jwt_secret_key"
PORT=5050
NODE_ENV=development
EOF
# Run database migrations
npx prisma migrate dev --name init
# Start the backend server
npm run devcd ../frontend
# Install dependencies
npm install
# Create .env.local file (optional, uses default API URL)
cat > .env.local << EOF
NEXT_PUBLIC_API_URL="http://localhost:5050/api"
EOF
# Start the development server
npm run devThe frontend will be available at http://localhost:3000
cd backend
# Build and start services
docker-compose up -d
# Run migrations
docker-compose exec backend npx prisma migrate devmeeting-booking/
βββ backend/
β βββ src/
β β βββ config/ # Database configuration
β β βββ middleware/ # Authentication middleware
β β βββ models/ # Prisma models
β β βββ routes/ # API routes
β β βββ services/ # Business logic
β β βββ types/ # TypeScript type definitions
β β βββ index.ts # Server entry point
β βββ prisma/
β β βββ schema.prisma # Database schema
β βββ package.json
β
βββ frontend/
β βββ src/
β β βββ app/
β β β βββ api/ # API route handlers
β β β βββ auth/ # Authentication pages
β β β βββ bookings/ # Booking management
β β β βββ rooms/ # Room management
β β β βββ dashboard/ # User dashboard
β β β βββ layout.tsx # Root layout
β β βββ hook/ # Custom React hooks
β β βββ services/ # API service layer
β βββ package.json
βββ README.md
- User: Can create bookings, cancel own bookings, view own bookings
- Admin: Full access including room management and user promotion
The first user to register automatically becomes an admin.
Username: admin
Email: admin@test.com
Password: password123
POST /api/auth/register- Register new userPOST /api/auth/login- Login userPOST /api/auth/logout- Logout userGET /api/auth/me- Get current user profilePOST /api/auth/promote- Promote user to admin
GET /api/rooms- Get all roomsGET /api/rooms/:id- Get room detailsPOST /api/rooms- Create new room (authenticated)DELETE /api/rooms/:id- Delete room (admin only)
GET /api/bookings- Get user's bookingsPOST /api/bookings- Create new bookingGET /api/bookings/:id- Get booking detailsDELETE /api/bookings/:id- Cancel booking (soft-delete)POST /api/bookings/check-availability- Check room availability
The booking system uses transaction-based locking to prevent race conditions:
// Bookings are created within a transaction with FOR UPDATE lock
// This ensures only one booking can be created for the same time slot
SELECT ... FROM bookings ... WHERE room_id = ? FOR UPDATE;model Booking {
// ...
deletedAt DateTime? // Null = active, Set = soft-deleted
}@@unique([userId, roomId, startTime, endTime])
// Prevents duplicate bookings for same user, room, and timecd backend
npm run test# Login
curl -X POST http://localhost:5050/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","email":"admin@test.com","password":"password123"}'
# Create booking
curl -X POST http://localhost:5050/api/bookings \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"room_id":1,"start_time":"2025-11-20T10:00:00Z","end_time":"2025-11-20T11:00:00Z"}'cd backend
# Build
npm run build
# Set environment variables on production server
export DATABASE_URL="your_production_db_url"
export JWT_SECRET="your_production_secret"
export NODE_ENV="production"
# Start
npm run startcd frontend
# Build
npm run build
# Start
npm run startDATABASE_URL=postgresql://user:password@localhost:5432/db_name
JWT_SECRET=your_secret_key
PORT=5050
NODE_ENV=development
NEXT_PUBLIC_API_URL=http://localhost:5050/api
npm install
npx prisma generate- Ensure PostgreSQL is running
- Check DATABASE_URL environment variable
- Verify database exists and credentials are correct
# Change PORT in backend .env file
# Or kill process using port:
lsof -ti:5050 | xargs kill -9This project is open source and available under the MIT License.
Created by Facelles
Contributions are welcome! Please feel free to submit a Pull Request.