A full-stack training session management application built with Next.js 15, PostgreSQL, and Drizzle ORM.
- Authentication & Authorization: JWT-based auth with role-based access control (Admin & Platoon-scoped users)
- CRUD Operations: Create, read, update, and delete training sessions
- Advanced Filtering: Filter sessions by course, platoon, instructor, and date range
- Bulk Upload: Upload sessions via CSV/XLSX files with preview and error reporting
- Security: CSRF protection, rate limiting, and secure authentication
- Modern UI: Built with Tailwind CSS and shadcn/ui components
- Frontend: Next.js 15 (App Router), React, TypeScript, Tailwind CSS, shadcn/ui
- Backend: Next.js API Routes
- Database: PostgreSQL with Drizzle ORM
- Validation: Zod
- Authentication: JWT with bcryptjs
- File Parsing: papaparse (CSV), xlsx (Excel)
- Node.js 20+
- PostgreSQL database
npm installCreate a .env.local file in the root directory:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/training_planner
JWT_SECRET=your-super-secret-jwt-key-change-in-production
CSRF_SECRET=your-super-secret-csrf-key-change-in-productionMake sure PostgreSQL is running, then:
# Generate migration files
npm run db:generate
# Push schema to database
npm run db:push
# Seed the database with sample data
npm run db:seednpm run devOpen http://localhost:3000 in your browser.
After seeding the database, you can log in with:
-
Admin User:
- Email:
admin@example.com - Password:
password123 - Can manage all sessions
- Email:
-
Platoon A Manager:
- Email:
platoon.a@example.com - Password:
password123 - Can only manage Platoon A sessions
- Email:
-
Platoon B Manager:
- Email:
platoon.b@example.com - Password:
password123 - Can only manage Platoon B sessions
- Email:
POST /api/auth/login- LoginPOST /api/auth/logout- LogoutGET /api/auth/csrf- Get CSRF tokenGET /api/auth/me- Get current user
GET /api/v1/sessions- List sessions (with filters)POST /api/v1/sessions- Create sessionPATCH /api/v1/sessions/:id- Update sessionDELETE /api/v1/sessions/:id- Delete sessionPOST /api/v1/sessions/bulk-upload- Bulk upload sessions
GET /api/v1/courses- List coursesGET /api/v1/subjects- List subjectsGET /api/v1/platoons- List platoonsGET /api/v1/instructors- List instructors
Course,Subject,Platoon,Instructor,Planned At,Duration (min),Venue,Notes
CS-101,PROG-101,PLT-A,john.smith@example.com,2025-11-25T09:00:00,90,Room 101,Introduction
MATH-201,CALC-201,PLT-B,jane.doe@example.com,2025-11-26T14:00:00,60,Room 305,Advanced topics- Course: Course code or title
- Subject: Subject code or title
- Platoon: Platoon key or name
- Instructor: Instructor name or email
- Planned At: ISO datetime (YYYY-MM-DDTHH:mm:ss)
- Duration (min): Number of minutes
- Venue: Venue name
- Notes: Optional notes
- JWT Authentication: Secure token-based authentication
- CSRF Protection: All state-changing operations require CSRF token
- Rate Limiting: Bulk upload endpoint is rate-limited (5 requests per minute)
- Role-Based Access Control: Admin and platoon-scoped permissions
- Input Validation: All inputs validated with Zod schemas
- users: Authentication and authorization
- courses: Training courses
- subjects: Course subjects
- instructors: Training instructors
- platoons: Training platoons
- sessions: Training sessions (links all entities)
npm run dev # Start development server
npm run build # Build for production
npm run start # Start production server
npm run db:generate # Generate Drizzle migrations
npm run db:push # Push schema to database
npm run db:studio # Open Drizzle Studio
npm run db:seed # Seed database with sample datamy-app/
├── app/
│ ├── api/ # API routes
│ ├── dashboard/ # Dashboard pages
│ ├── login/ # Login page
│ └── layout.tsx # Root layout
├── components/
│ ├── sessions/ # Session-related components
│ └── ui/ # UI components (shadcn/ui)
├── lib/
│ ├── auth/ # Authentication utilities
│ ├── db/ # Database schema and connection
│ └── validations/ # Zod schemas
└── public/ # Static assets