📦 Parcel Delivery Client

A modern, modular, and secure web application for managing parcel deliveries. Built with React, TypeScript, shadcn/ui, RTK Query, and Recharts for analytics.


Live Demo: Parcel Delivery Client.
GitHub Repository (Frontend): Parcel Delivery Client.
GitHub Repository (Backend): Parcel Delivery Server.

🧱 Features

  • Authentication: Email/password login, JWT, OTP verification
  • Role-based Access to dashboard: Sender, Receiver, Admin, Super Admin, Delivery Personnel
  • Manage users, parcels, and deliveries
  • Parcel Lifecycle: Request, Approve, Picked, Dispatch, In Transit, Deliver, Block, Cancel, Flagged
  • Real-time Tracking: Track parcels by tracking ID
  • Status Analytics: Bar and Pie charts for delivery status, parcel type, shipping type, and trends
  • Responsive UI: Modern design with shadcn/ui and Tailwind CSS
  • Coupon Support: Admins can create and manage coupons
  • Notifications: Email for OTP verification
  • Contact email using Emailjs
  • Global Error Handling: User-friendly error messages

🧩 Tech Stack

  • React + Vite — Frontend framework
  • TypeScript — Type safety
  • shadcn/ui — Modern UI components
  • Tailwind CSS — Utility-first styling
  • RTK Query — Data fetching and caching
  • Recharts — Analytics and charts
  • Sonner — Toast notifications
  • React Hook Form + Zod — Forms and validation
  • Lucide Icons — Icon set
  • Emailjs for email receiving

🛠️ Getting Started

# 1. Clone the repo
git clone https://github.com/faisal-akbar/b5b6-frontend.git
cd b5b6-frontend
# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env

# 4. Update .env with your MongoDB URI, nodemailer credentials, redis credentials, etc.
VITE_BASE_URL=http://localhost:5000/api/v1
VITE_EMAILJS_SERVICE_ID=your_service_id
VITE_EMAILJS_TEMPLATE_ID=template_id
VITE_EMAILJS_PUBLIC_ID=your_public_id

# 5. Run locally
npm run dev

🔐 Email and password for testing dummy users:

// SUPER_ADMIN
email: "super@gmail.com",
password: "12345678"

// SENDER
email: "john.sender@parcel.com",
password: "sender123"

// RECEIVER
email: "bob.receiver@parcel.com",
 password: "receiver123",

 // ADMIN
email: "admin@parcel.com",
password: "Ph@12345678"

// Sample Id's for delivery personnel

"68ad6b75b010e0e1a1c78d20"

"68ad6b74b010e0e1a1c78d1d"

📦 Public Parcel Status

Use this below sample tracking id:

  • TRK-20250826-404197

📦 Sample Coupon

  • IK5QY5NL
  • TU56CKCZ

📁 Folder Structure

.
├── README.md
├── components.json
├── eslint.config.js
├── index.html
├── package-lock.json
├── package.json
├── public
│   └── vite.svg
├── src
│   ├── App.tsx
│   ├── assets
│   │   ├── icons
│   │   │   └── Logo.tsx
│   │   ├── images
│   │   │   ├── parcel-login.jpg
│   │   │   └── parcel-register.jpg
│   │   └── react.svg
│   ├── components
│   │   ├── DeleteConformation.tsx
│   │   ├── Error.tsx
│   │   ├── ErrorBoundary.tsx
│   │   ├── Information.tsx
│   │   ├── Loading.tsx
│   │   ├── NotFound.tsx
│   │   ├── app-sidebar.tsx
│   │   ├── layout
│   │   │   ├── CommonLayout.tsx
│   │   │   ├── DashboardLayout.tsx
│   │   │   ├── Footer.tsx
│   │   │   ├── ModeToggle.tsx
│   │   │   └── Navbar.tsx
│   │   ├── modules
│   │   │   ├── about
│   │   │   │   ├── AboutFeatures.tsx
│   │   │   │   ├── AboutHero.tsx
│   │   │   │   └── AboutJourney.tsx
│   │   │   ├── admin
│   │   │   │   ├── parcels
│   │   │   │   │   ├── AdminParcelDetails.tsx
│   │   │   │   │   ├── AdminParcelModal.tsx
│   │   │   │   │   ├── AdminParcelTimeLine.tsx
│   │   │   │   │   ├── AdminParcelsTable.tsx
│   │   │   │   │   └── analytics
│   │   │   │   │       ├── DeliveryStatysBarChart.tsx
│   │   │   │   │       ├── OverViewCards.tsx
│   │   │   │   │       ├── ParcelsCharts.tsx
│   │   │   │   │       ├── ShipmentBarChart.tsx
│   │   │   │   │       ├── ShippingTypeChart.tsx
│   │   │   │   │       └── TypePieChart.tsx
│   │   │   │   └── users
│   │   │   │       ├── CreateStuff.tsx
│   │   │   │       └── UsersTable.tsx
│   │   │   ├── authentication
│   │   │   │   ├── LoginForm.tsx
│   │   │   │   └── RegisterForm.tsx
│   │   │   ├── contact
│   │   │   │   ├── ContactHero.tsx
│   │   │   │   └── contactForm.tsx
│   │   │   ├── faq
│   │   │   │   ├── FaqContact.tsx
│   │   │   │   ├── FaqHero.tsx
│   │   │   │   └── FaqSection.tsx
│   │   │   ├── features
│   │   │   │   ├── FeaturesBenefit.tsx
│   │   │   │   ├── FeaturesCTA.tsx
│   │   │   │   ├── FeaturesGrid.tsx
│   │   │   │   └── FeaturesHero.tsx
│   │   │   ├── home
│   │   │   │   ├── Feature.tsx
│   │   │   │   ├── Hero.tsx
│   │   │   │   ├── HomeAbout.tsx
│   │   │   │   ├── HomeCTA.tsx
│   │   │   │   ├── HomeFaq.tsx
│   │   │   │   └── HomeTestimonials.tsx
│   │   │   ├── receiver
│   │   │   │   ├── ReceiverHistoryParcelTable.tsx
│   │   │   │   └── ReceiverIncomingParcelTable.tsx
│   │   │   ├── sender
│   │   │   │   ├── SendParcelModal.tsx
│   │   │   │   ├── SenderParcelTable.tsx
│   │   │   │   ├── StatusDetails.tsx
│   │   │   │   └── StatusTimeLine.tsx
│   │   │   ├── testimonials
│   │   │   │   ├── TestimonialsCTA.tsx
│   │   │   │   └── TestimonialsSection.tsx
│   │   │   └── trackParcel
│   │   │       ├── HelpSection.tsx
│   │   │       ├── ParcelDetails.tsx
│   │   │       ├── TimeLine.tsx
│   │   │       ├── Track.tsx
│   │   │       ├── TrackParcelForm.tsx
│   │   │       └── TrackParcelHero.tsx
│   │   └── ui
│   │       ├── Password.tsx
│   │       ├── accordion.tsx
│   │       ├── alert-dialog.tsx
│   │       ├── avatar.tsx
│   │       ├── badge.tsx
│   │       ├── button.tsx
│   │       ├── card.tsx
│   │       ├── chart.tsx
│   │       ├── checkbox.tsx
│   │       ├── dialog.tsx
│   │       ├── dropdown-menu.tsx
│   │       ├── form.tsx
│   │       ├── input-otp.tsx
│   │       ├── input.tsx
│   │       ├── label.tsx
│   │       ├── nav-user.tsx
│   │       ├── navigation-menu.tsx
│   │       ├── pagination.tsx
│   │       ├── popover.tsx
│   │       ├── select.tsx
│   │       ├── separator.tsx
│   │       ├── shadcn-io
│   │       │   └── spinner
│   │       │       └── index.tsx
│   │       ├── sheet.tsx
│   │       ├── sidebar.tsx
│   │       ├── skeleton.tsx
│   │       ├── sonner.tsx
│   │       ├── table.tsx
│   │       ├── textarea.tsx
│   │       └── tooltip.tsx
│   ├── config
│   │   └── index.ts
│   ├── context
│   │   └── theme-context.ts
│   ├── hooks
│   │   ├── use-mobile.ts
│   │   └── useTheme.ts
│   ├── index.css
│   ├── lib
│   │   ├── axios.ts
│   │   ├── emailjs.ts
│   │   └── utils.ts
│   ├── main.tsx
│   ├── pages
│   │   ├── About.tsx
│   │   ├── Contact.tsx
│   │   ├── FAQ.tsx
│   │   ├── Features.tsx
│   │   ├── HomePage.tsx
│   │   ├── Login.tsx
│   │   ├── Register.tsx
│   │   ├── Testimonials.tsx
│   │   ├── TrackParcel.tsx
│   │   ├── Unauthorized.tsx
│   │   ├── Verify.tsx
│   │   ├── admin
│   │   │   ├── analytics
│   │   │   │   └── Analytics.tsx
│   │   │   ├── parcels
│   │   │   │   ├── ViewParcelDetails.tsx
│   │   │   │   └── ViewParcels.tsx
│   │   │   └── user
│   │   │       └── AllUsers.tsx
│   │   ├── receiver
│   │   │   ├── DeliveryHistory.tsx
│   │   │   └── IncomingParcels.tsx
│   │   └── sender
│   │       ├── MyParcels.tsx
│   │       └── ParcelStatus.tsx
│   ├── providers
│   │   └── theme-provider.tsx
│   ├── redux
│   │   ├── api
│   │   │   ├── axiosBaseQuery.ts
│   │   │   └── baseApi.ts
│   │   ├── features
│   │   │   ├── auth
│   │   │   │   └── authApi.ts
│   │   │   ├── coupon
│   │   │   │   └── couponApi.ts
│   │   │   ├── parcel
│   │   │   │   └── parcelApi.ts
│   │   │   └── user
│   │   │       └── userApi.ts
│   │   ├── hooks.ts
│   │   └── store.ts
│   ├── routes
│   │   ├── adminSidebarItems.ts
│   │   ├── constants.ts
│   │   ├── index.tsx
│   │   ├── receiverSidebarItems.ts
│   │   └── senderSidebarItems.ts
│   ├── types
│   │   ├── auth-type.ts
│   │   ├── index.ts
│   │   ├── parcel-type.ts
│   │   ├── sender-parcel-type.ts
│   │   └── user-type.ts
│   ├── utils
│   │   ├── generateRoutes.ts
│   │   ├── getNameInitials.ts
│   │   ├── getSidebarItems.ts
│   │   ├── getStatusColor.ts
│   │   └── withAuth.tsx
│   └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── vercel.json
└── vite.config.ts

👤 User Roles

RoleResponsibilities
SENDERsend/cancel/delete parcels, view own parcels, status
RECEIVERView incoming parcels, confirm delivery, delivery history
DELIVERY_PERSONNELCurrently admin can assign to parcel, and create
ADMINManage users, create admins and personnel, view analytics
SUPER_ADMINSimilar to admin

Dashboard Screenshots

Admin Dashboard

Parcel Analytics

Parcel Management

Parcel Details

User Management


Sender Dashboard

My Parcels

Parcel Status


Receiver Dashboard

Incoming Parcels

Delivery History


📦 Parcel Delivery Server

A modular and secure backend system for managing parcel deliveries. It features real-time tracking, role-based access control, and full parcel lifecycle management.


Live Demo: Parcel Delivery System.

Postman Collection: Parcel Delivery Server Postman Collection.

🧱 Features

  • 🔐 Authentication: Email/password-based login using JWT.
  • 🔁 Role-based access (SENDER, RECEIVER, ADMIN, SUPER_ADMIN, DELIVERY_PERSONNEL)
  • 📦 Parcel lifecycle: Request, approve, picked, dispatch, deliver, block, cancel, flagged
  • 🔄 Status Tracking: Track status changes for each parcel.
  • 📲 OTP-based registration verification support
  • 🧱 Scalable Modular Architecture
  • 🎟️ Coupon support (only admin/super admin can create)
  • ⚠️ Global error and validation handling
  • 📧 Email notifications for OTP and password reset

🧩 Tech Stack

  • Node.js + Express — Backend framework
  • MongoDB + Mongoose — NoSQL Database with ODM
  • Zod — Schema validation
  • TypeScript — Optional typing (if enabled)
  • JWT — Authentication
  • dotenv — Config management
  • Redis — Caching and session management
  • EJS — Email templating
  • Postman — API testing and documentation
  • ESLint — Code quality and linting
  • Prettier — Code formatting
  • Nodemailer — Email sending
  • Vercel — Deployment platform

🛠️ Getting Started

# 1. Clone the repo
git clone https://github.com/faisal-akbar/b5a5.git
cd b5a5
# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env

# 4. Update .env with your MongoDB URI, nodemailer credentials, redis credentials, etc.
PORT=5000
DB_URL=mongodb+srv://<db_user>:<db_password>@cluster0.4pnfxkm.mongodb.net/percel_delivery_system?retryWrites=true&w=majority&appName=Cluster0
NODE_ENV=development

# JWT
JWT_ACCESS_SECRET=access_secret
JWT_ACCESS_EXPIRES=3d

JWT_REFRESH_SECRET=refresh_secret
JWT_REFRESH_EXPIRES=10d

# BCRYPT
BCRYPT_SALT_ROUND=10

# SUPER ADMIN
SUPER_ADMIN_EMAIL=super@gmail.com
SUPER_ADMIN_PASSWORD=12345678

# Express Session
EXPRESS_SESSION_SECRET=express-session

# Frontend URL
FRONTEND_URL=http://localhost:5173

# SMTP GMAIL
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_USER=fexample@gmail.com
SMTP_PASS=your_smtp_password_here
SMTP_FROM=fexample@gmail.com

# redis
REDIS_HOST=hostname_of_your_redis_server
REDIS_PORT=14282
REDIS_USERNAME=default
REDIS_PASSWORD=your_redis_password_here

# 5. Run locally
npm run dev

👤 Dummy Users for Testing

I have added two function to create dummy users, one for super admin seedSuperAdmin() (enabled by default) and one for sender, receiver and admin. Uncomment this line seedDummyUsers() in src/server.ts if you want to seed dummy users.

Email and password for some dummy users:

// SUPER_ADMIN
email: "super@gmail.com",
password: "12345678"

// ADMIN
email: "admin@parcel.com",
password: "Ph@12345678"

// SENDER
email: "john.sender@parcel.com",
password: "sender123"

// RECEIVER
email: "bob.receiver@parcel.com",
 password: "receiver123",

📁 Folder Structure

── Parcel Delivery.postman_collection.json
├── README.md
├── eslint.config.mjs
├── package-lock.json
├── package.json
├── src
│   ├── app
│   │   ├── config
│   │   │   ├── env.ts
│   │   │   └── redis.config.ts
│   │   ├── interfaces
│   │   │   ├── error.types.ts
│   │   │   └── index.d.ts
│   │   ├── middlewares
│   │   │   ├── checkAuth.ts
│   │   │   ├── globalErrorHandler.ts
│   │   │   ├── notFound.ts
│   │   │   └── validateRequest.ts
│   │   ├── modules
│   │   │   ├── auth
│   │   │   │   ├── auth.controller.ts
│   │   │   │   ├── auth.routes.ts
│   │   │   │   └── auth.service.ts
│   │   │   ├── coupon
│   │   │   │   ├── coupon.controller.ts
│   │   │   │   ├── coupon.interface.ts
│   │   │   │   ├── coupon.model.ts
│   │   │   │   ├── coupon.routes.ts
│   │   │   │   ├── coupon.service.ts
│   │   │   │   ├── coupon.utils.ts
│   │   │   │   └── coupon.validation.ts
│   │   │   ├── otp
│   │   │   │   ├── otp.controller.ts
│   │   │   │   ├── otp.routes.ts
│   │   │   │   ├── otp.service.ts
│   │   │   │   └── otp.validation.ts
│   │   │   ├── parcel
│   │   │   │   ├── parcel.controller.ts
│   │   │   │   ├── parcel.interface.ts
│   │   │   │   ├── parcel.model.ts
│   │   │   │   ├── parcel.routes.ts
│   │   │   │   ├── parcel.service.ts
│   │   │   │   ├── parcel.utils.ts
│   │   │   │   └── parcel.validation.ts
│   │   │   └── user
│   │   │       ├── user.contants.ts
│   │   │       ├── user.controller.ts
│   │   │       ├── user.interface.ts
│   │   │       ├── user.model.ts
│   │   │       ├── user.routes.ts
│   │   │       ├── user.service.ts
│   │   │       └── user.validation.ts
│   │   ├── routes
│   │   │   └── index.ts
│   │   └── utils
│   │       ├── builder
│   │       │   ├── QueryBuilder.ts
│   │       │   └── constants.ts
│   │       ├── catchAsync.ts
│   │       ├── errorHelpers
│   │       │   ├── AppError.ts
│   │       │   ├── handleCastError.ts
│   │       │   ├── handleDuplicateError.ts
│   │       │   ├── handlerValidationError.ts
│   │       │   └── handlerZodError.ts
│   │       ├── generateTrackingId.ts
│   │       ├── jwt
│   │       │   ├── jwt.ts
│   │       │   ├── setCookie.ts
│   │       │   └── userTokens.ts
│   │       ├── seedDummyUser.ts
│   │       ├── seedSuperAdmin.ts
│   │       ├── sendEmail.ts
│   │       ├── sendResponse.ts
│   │       └── templates
│   │           ├── forgetPassword.ejs
│   │           └── otp.ejs
│   ├── app.ts
│   └── server.ts
├── tsconfig.json
└── vercel.json

👤 User Roles

RoleResponsibilities
SENDERsend/cancel/delete parcels, view own parcels, status
RECEIVERView incoming parcels, confirm delivery, delivery history
DELIVERY_PERSONNELCurrently admin can assign to parcel, and create
ADMINManage users, create admins and personnel, manage coupons
SUPER_ADMINSimilar to admin but can create super admins

📡 API Endpoints

🔐 Auth

MethodEndpointDescription
POST/loginUser login
POST/refresh-tokenRefresh JWT token
POST/logoutLogout user
POST/change-passwordChange password
POST/forgot-passwordForgot password request
POST/reset-passwordReset password

📲 OTP

MethodEndpointDescription
POST/sendSend OTP to phone
POST/verifyVerify OTP

👤 Users

MethodEndpointRoleDescription
POST/registerPublicRegister sender/receiver
POST/create-adminADMIN/SUPER_ADMINCreate new admin
POST/create-delivery-personnelADMIN/SUPER_ADMINRegister delivery personnel
GET/all-usersADMIN/SUPER_ADMINGet all users
GET/meAuthenticatedGet logged-in user
GET/:idAuthenticatedGet user by ID
PATCH/:idAuthenticatedUpdate user profile
PATCH/:id/block-userADMIN/SUPER_ADMINBlock/unblock user

📦 Parcels

MethodEndpointRoleDescription
POST/SENDERCreate parcel
POST/cancel/:idSENDERCancel parcel
POST/delete/:idSENDERDelete parcel
GET/meSENDERView sender's parcels
GET/:id/status-logSENDERView parcel status log
GET/me/incomingRECEIVERIncoming parcels
GET/me/historyRECEIVERDelivery history
PATCH/confirm/:idRECEIVERConfirm delivery
GET/tracking/:trackingIdPublicTrack parcel
GET/ADMINGet all parcels
POST/create-parcelADMINAdmin creates parcel
PATCH/:id/delivery-statusADMINUpdate delivery status
PATCH/:id/block-statusADMINBlock/unblock a parcel
GET/:id/detailsADMINGet parcel details

📦 stats

MethodEndpointRoleDescription
GET/parcelsADMINParcel statistics
GET/userADMINUser statistics

🎟️ Coupons

MethodEndpointRoleDescription
POST/ADMINCreate new coupon

🔁 Parcel Lifecycle

🔄 Normal Flow

REQUESTED → APPROVED → PICKED → DISPATCHED → IN_TRANSIT → DELIVERED

🛑 Exception Flows

Any Stage → FLAGGED → BLOCKED/CANCELLED
PICKED/DISPATCHED/IN_TRANSIT → RETURNED → REQUESTED
IN_TRANSIT → RESCHEDULED → IN_TRANSIT/DELIVERED/CANCELLED