LeaveFlow: Modern Leave Management System
LeaveFlow is a SaaS-based HR tool designed to automate and simplify leave management for organizations. It provides a real-time, role-based dashboard for admins and employees, with features like leave requests, approval workflows, company holidays, team management, and real-time chat .
Architecture Overview
Key Features & Workflows
Tech Stack Deep Dive
Project Structure Explained
Database Design & Prisma ORM
Authentication & Authorization Flow
API Layer & Endpoints
Real-Time Features (Pusher)
Payment Integration (Stripe)
UI/UX & Component Library
Deployment & Scalability
Testing & Debugging
Contribution Guidelines
License & Legal
LeaveFlow follows a modern full-stack architecture with:
Frontend : Next.js (App Router) for SSR/SSG and React for UI.
Backend : Next.js API routes for RESTful endpoints.
Database : PostgreSQL with Prisma ORM for type-safe queries.
Real-Time : Pusher for chat and notifications.
Auth : NextAuth.js for Google OAuth and session management.
Payments : Stripe for subscriptions and one-time payments.
High-Level Architecture Diagram
┌───────────────────────────────────────────────────────────────┐
│ Client (Browser) │
└───────────────┬───────────────────┬───────────────────────────┘
│ │
┌───────────────▼───────┐ ┌───────▼───────────────────────────┐
│ Next.js Frontend │ │ Next.js API (Backend) │
│ - React Components │ │ - REST Endpoints │
│ - Tailwind CSS │ │ - Prisma ORM │
│ - ShadCN UI │ │ - Stripe/Pusher Integrations │
└───────────────┬───────┘ └──────────────┬────────────────────────┘
│ │
┌───────────────▼──────────────────────────▼───────────────────┐
│ PostgreSQL Database │
│ - Users, Companies, TimeOffRequests, ChatMessages, etc. │
└───────────────────────────────────────────────────────────────┘
✨ Key Features & Workflows
Admin Dashboard :
View pending/approved leave requests .
Manage employees, company holidays, and working days .
Generate reports and invitation codes .
Real-time chat with employees.
Employee Dashboard :
Submit leave requests .
View personal leave history and company holidays .
Chat with admins/colleagues .
2. Leave Request Workflow
Employee submits a request (with start/end dates, type, and reason).
Admin reviews the request in the dashboard.
Admin approves/rejects the request.
System updates the employee’s available leave balance.
Employee is notified via real-time chat or email (future feature).
Built with Pusher for instant messaging.
Supports 1:1 and group chats .
Typing indicators and read receipts .
Configure working days (e.g., Mon-Fri).
Add company holidays (one-time or recurring).
Update company profile (logo, name, website).
5. Subscription & Payments
Stripe integration for:
One-time payments (7-day, 14-day, 1-month plans).
Recurring subscriptions (future).
Webhook handling for payment success/failure.
Filter leave requests by date, employee, or status .
Export reports as PDF/Excel .
Category
Technology
Purpose
Frontend
Next.js (App Router)
SSR, SSG, and React for dynamic UI.
Styling
Tailwind CSS + ShadCN
Utility-first CSS and pre-built components.
State Management
React Query + Zustand
Data fetching, caching, and global state.
Backend
Next.js API Routes
RESTful endpoints for frontend-backend communication.
Database
PostgreSQL + Prisma
Relational database with type-safe ORM.
Auth
NextAuth.js
Google OAuth, session management, and role-based access.
Real-Time
Pusher
Chat, notifications, and live updates.
Payments
Stripe
Subscriptions, one-time payments, and webhooks.
Animations
Framer Motion
Smooth UI transitions and micro-interactions.
Forms
React Hook Form + Zod
Type-safe form validation and submission.
Testing
Jest + React Testing Lib
Unit and integration testing (WIP).
Deployment
Vercel/Docker
Serverless deployment and containerization.
📂 Project Structure Explained
sajid-tech-saas-resources-tool/
├── app/
│ ├── (dashboard)/ # Authenticated routes (Admin/Employee)
│ │ ├── admin/ # Admin-specific pages (e.g., time-off requests, reports)
│ │ └── employee/ # Employee-specific pages (e.g., leave requests, calendar)
│ ├── (public)/ # Public landing pages (marketing, FAQ)
│ ├── api/ # API routes (REST endpoints)
│ │ ├── admin/ # Admin APIs (e.g., approve requests, manage employees)
│ │ └── employee/ # Employee APIs (e.g., submit requests)
│ └── auth/ # Authentication pages (sign-in, success)
├── components/ # Reusable UI components
│ ├── dashboard/ # Dashboard-specific components (e.g., tables, forms)
│ ├── landing/ # Landing page components (e.g., hero section, FAQ)
│ └── ui/ # ShadCN UI components (e.g., buttons, cards)
├── hooks/ # Custom React hooks (e.g., useChat, usePusher)
├── lib/ # Utility functions and configs
│ ├── auth.ts # NextAuth configuration
│ ├── prisma.ts # Prisma client setup
│ └── pusher.ts # Pusher client setup
├── prisma/ # Prisma schema and migrations
└── types/ # TypeScript types (e.g., ChatRoom, User)
Key Directories Explained
app/(dashboard)/ :
Contains role-specific layouts (admin, employee).
Uses middleware to enforce authentication and role-based access.
app/api/ :
RESTful endpoints for frontend-backend communication.
Admin APIs : Manage employees, requests, and company settings.
Employee APIs : Submit requests, fetch personal data.
components/dashboard/ :
Admin components : admin-calendar.tsx, time-off-request-table.tsx.
Employee components : employee-calendar.tsx, request-table.tsx.
lib/ :
auth.ts : NextAuth configuration (Google OAuth).
prisma.ts : Prisma client singleton for database access.
pusher.ts : Pusher client for real-time features.
🗃 Database Design & Prisma ORM
User :
Stores employee/admin profiles .
Fields: id, email, role, companyId, availableDays.
Company :
Stores company details (name, logo, working days).
Fields: id, name, workingDays, holidays.
TimeOffRequest :
Tracks leave requests .
Fields: id, employeeId, startDate, endDate, status.
ChatRoom & ChatMessage :
Powers real-time chat .
Fields: id, participants, messages.
Subscription :
Manages Stripe subscriptions .
Fields: userId, stripeCustomerId, planType, status.
// Fetch all pending leave requests for a company
const pendingRequests = await prisma . timeOffRequest . findMany ( {
where : {
employee : { companyId : "company_123" } ,
status : "PENDING" ,
} ,
include : { employee : true } ,
} ) ;
🔐 Authentication & Authorization Flow
User clicks "Sign in with Google" on /auth/signin.
NextAuth redirects to Google OAuth.
On success, NextAuth creates a session and redirects to /auth/success.
Middleware checks session.user.role and redirects to /admin or /employee.
Middleware (middleware.ts) enforces role-based routing:
if ( pathname . startsWith ( "/admin" ) && token . role !== "ADMIN" ) {
return NextResponse . redirect ( new URL ( "/" , request . url ) ) ;
}
API routes also check roles:
if ( user . role !== "ADMIN" ) {
return NextResponse . json ( { error : "Unauthorized" } , { status : 403 } ) ;
}
JWT-based sessions stored in HTTP-only cookies.
Session data includes:
{
user : {
id : string ,
email : string ,
role : "ADMIN" | "EMPLOYEE" ,
onboardingCompleted : boolean ,
}
}
Endpoint
Method
Description
/api/admin/dashboard
GET
Fetch dashboard stats (pending requests, etc.).
/api/admin/employees
GET
List all employees.
/api/admin/time-off-requests/[id]
PUT
Approve/reject a leave request.
/api/admin/holidays
POST
Add a company holiday.
/api/admin/working-days
PUT
Update company working days.
Endpoint
Method
Description
/api/employee/time-off-requests
POST
Submit a new leave request.
/api/employee/colleagues
GET
Fetch colleagues for chat.
Endpoint
Method
Description
/api/auth/[...nextauth]
GET/POST
NextAuth.js authentication routes.
/api/auth/current-user
GET
Fetch current user data.
Endpoint
Method
Description
/api/chat
GET/POST
Fetch/create chat rooms.
/api/chat/[roomId]/messages
GET/POST
Fetch/send messages in a room.
💬 Real-Time Features (Pusher)
Frontend subscribes to Pusher channels:
pusherClient . subscribe ( `chat-${ roomId } ` ) ;
Backend triggers events on actions (e.g., new message):
await pusherServer . trigger ( `chat-${ roomId } ` , 'new-message' , messageData ) ;
Frontend listens for events and updates UI:
channel . bind ( 'new-message' , ( data ) => {
setMessages ( [ ...messages , data ] ) ;
} ) ;
chat-{roomId}: Room-specific messages.
user-{userId}: User-specific notifications (e.g., new chat room).
company-{companyId}: Company-wide updates (e.g., new holiday).
💳 Payment Integration (Stripe)
Admin selects a plan (7-day, 14-day, 1-month).
Frontend calls /api/admin/create-checkout-session with planId.
Backend creates a Stripe Checkout Session :
const checkoutSession = await stripe . checkout . sessions . create ( {
payment_method_types : [ 'card' ] ,
line_items : [ { price : priceIds [ planId ] , quantity : 1 } ] ,
success_url : `${ APP_URL } /admin/success?session_id={CHECKOUT_SESSION_ID}` ,
} ) ;
User is redirected to Stripe Checkout.
Stripe webhook (/api/admin/webhooks) updates the database on success.
checkout.session.completed: Extend/activate subscription.
customer.subscription.updated: Update subscription status.
customer.subscription.deleted: Mark subscription as canceled.
🎨 UI/UX & Component Library
ShadCN UI :
Pre-built, accessible components (e.g., Button, Card, Table).
Customized for LeaveFlow’s branding.
Tailwind CSS :
Utility-first styling for rapid development.
Framer Motion :
Animations for modals, dropdowns, and transitions.
Example Component: StatCard
const StatCard = ( { title, value, icon : Icon , color, description } : StatCardProps ) => (
< div className = "bg-white rounded-lg border border-purple-200 p-3" >
< div className = "flex items-center justify-between" >
< div className = "space-y-1" >
< p className = "text-xs font-medium text-gray-500 uppercase" > { title } </ p >
< h3 className = "text-xl font-bold text-gray-900" > { value } </ h3 >
{ description && < p className = "text-xs text-gray-500" > { description } </ p > }
</ div >
< div className = { `w-8 h-8 flex items-center justify-center rounded-lg ${ color } ` } >
< Icon className = "w-4 h-4 text-white" />
</ div >
</ div >
</ div >
) ;
🚀 Deployment & Scalability
Push to GitHub .
Import into Vercel .
Add environment variables in Vercel’s dashboard.
Deploy (automatic CI/CD).
FROM node:18-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npx prisma generate
EXPOSE 3000
CMD ["npm" , "start" ]
Scalability Considerations
Database : Use PostgreSQL read replicas for heavy read operations.
Real-Time : Pusher scales automatically with usage.
Caching : Implement Redis for frequent queries (e.g., dashboard stats).
Unit Tests : Jest for individual functions/components.
Integration Tests : React Testing Library for component interactions.
E2E Tests : Cypress for user flows (WIP).
Prisma Studio : Visualize database data.
Stripe CLI : Test webhooks locally.
stripe listen --forward-to localhost:3000/api/admin/webhooks
Pusher Debug Console : Monitor real-time events.
🤝 Contribution Guidelines
Fork the repository .
Create a feature branch :
git checkout -b feature/your-feature
Commit changes :
git commit -m " Add your feature"
Push to the branch :
git push origin feature/your-feature
Open a Pull Request .
TypeScript : Strict typing for all functions/components.
ESLint/Prettier : Follow existing code style.
Commit Messages : Use Conventional Commits .
This project is licensed under the Apache License 2.0 . See LICENSE for details.
Dependency
License
Purpose
Next.js
MIT
Frontend framework
Prisma
Apache 2.0
Database ORM
Stripe
MIT
Payments
Pusher
MIT
Real-time features
Tailwind CSS
MIT
Styling
ShadCN UI
MIT
UI components
For questions, bug reports, or feature requests:
LeaveFlow is built with ❤️ to simplify HR workflows for teams of all sizes. Star ⭐ the repo if you find it useful, and contribute to make it even better!