How to Build a Helpdesk-Style Complaint Tracking Portal in ReactJs? [Code + GitHub]

By Atit Purani

September 1, 2025

Every business, whether small or large, faces customer complaints. But handling them manually often leads to delays, lost tickets, and unhappy customers.

A simple email inbox or spreadsheet can quickly become a nightmare when customer issues pile up.

That’s where a complaint management system becomes useful. Instead of scattered communication, everything is logged, tracked, and resolved in one place.

Big companies rely on tools like Zendesk or Freshdesk, which are powerful but often expensive and limited in customization.

Trying to build your own helpdesk portal in ReactJS gives you full control?

Don’t worry, here in this blog, you get all the features of a modern ticketing system, without being locked into third-party pricing or restrictions.

What Is a Helpdesk-Style Complaint Tracking System? (And Why Build One in ReactJS?)

A complaint tracking portal is a helpdesk ticketing system where every complaint becomes a “ticket.”

These tickets move through different stages: created, assigned, & resolved to make sure no customer issue is left unattended.

Traditional help desk software does this well, but it comes at a cost.

For startups and developers, building your own in ReactJS means you can customize it exactly to your business needs.

Benefits of building your own:

  • Customization: Add features like AI chatbots, SLA timers, or integrations with your internal apps.
  • Cost savings: Avoid monthly subscription fees for every agent.
  • Integration: Connect seamlessly with your existing CRM, ERP, or business workflows.

With ReactJS, you can create a scalable, fast, and interactive customer complaint tracking system that’s not only cost-effective but also future-proof.

Features Your Complaint Tracking Portal Must Have

features-your-complaint-tracking-portal

When designing your customer support ticket system, here are the must-have features that make it truly effective:

  • Ticket Creation & Updates: Every complaint should generate a trackable ticket. Customers and staff should be able to update their status easily.
  • Role-Based Access (Admin, Staff, User): Control who can view, assign, and resolve tickets with proper role-based access control.
  • SLA Management System: Define timelines for resolution and automatically escalate when deadlines are missed. This makes it a real SLA management software.
  • File Uploads (Attachments): Customers can attach screenshots, invoices, or documents to support their complaint.
  • Notifications (Email, Push, Real-time): Keep customers and staff updated instantly when ticket status changes.
  • Analytics/Dashboard: An incident management system isn’t complete without insights. Add reports on resolution time, SLA breaches, and staff performance.

Tech Stack for Building a ReactJS Helpdesk Portal

Now, let’s look at the tools you’ll need to bring this to life.

  • Frontend: ReactJS (with hooks, components, Tailwind CSS for UI).
  • Backend: Node.js with Express or NestJS for handling APIs.
  • Database: MongoDB or PostgreSQL—both work great for ticket-based schemas.
  • State Management: Redux or React Query for managing tickets and user sessions.
  • Authentication: Firebase/Auth0 for secure login and multi-tenant helpdesk architecture.

In this blog, we’ll build a complaint tracking portal in React with Node step by step.

Step-by-Step Guide: Building the Complaint Tracking Portal in ReactJS

complaint-tracking-portal-in-reactjs

We’ll go through this ticketing system step by step, from setup to deployment, so you can build a full helpdesk portal in ReactJS.

Step 1: Setting up the React project

Create a fresh React app and install dependencies:

          
            npx create-react-app complaint-portal
            cd complaint-portal
            npm install axios react-router-dom react-hook-form tailwindcss @reduxjs/toolkit react-redux
          
          

Initialize TailwindCSS:

          
            npx tailwindcss init -p
          
          

Configure tailwind.config.js:

          
            module.exports = {
              content: ["./src/**/*.{js,jsx,ts,tsx}"],
              theme: { extend: {} },
              plugins: [],
            };
          
          

Step 2: Creating Ticket Models & Schema (Backend with Node.js)

In models/Ticket.js:

          
            const mongoose = require("mongoose");
            const ticketSchema = new mongoose.Schema({
              title: { type: String, required: true },
              description: String,
              status: { type: String, default: "open" },
              priority: { type: String, default: "medium" },
              attachments: [String],
              createdBy: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
              assignedTo: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
              createdAt: { type: Date, default: Date.now },
              dueDate: Date, // for SLA
            });
            
            module.exports = mongoose.model("Ticket", ticketSchema);
          
          

This schema is the backbone of your complaint tracking portal in React with Node.

Step 3: Building Ticket Forms (with React Hook Form)

In TicketForm.js:

          
              import { useForm } from "react-hook-form";
              import axios from "axios";
              
              export default function TicketForm() {
                const { register, handleSubmit } = useForm();
              
                const onSubmit = async (data) => {
                await axios.post("/api/tickets", data);
                alert("Ticket Created Successfully!");
                };
              
                return (
                <form onSubmit={handleSubmit(onSubmit)} className="p-4 bg-white rounded-lg shadow">
                  <input {...register("title")} placeholder="Enter ticket title" className="border p-2 w-full mb-3" />
                  <textarea {...register("description")} placeholder="Describe the issue" className="border p-2 w-full mb-3" />
                  <button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded">Submit Ticket</button>
                </form>
                );
              }
          
          

Step 4: Role-Based Authentication (RBAC)

Use Firebase/Auth0 or JWT. Example with JWT:

          
              // middleware/auth.js
              const jwt = require("jsonwebtoken");
              
              function auth(role) {
                return (req, res, next) => {
                const token = req.headers["authorization"]?.split(" ")[1];
                if (!token) return res.status(401).send("Unauthorized");
                const decoded = jwt.verify(token, "secretkey");
                if (role && decoded.role !== role) return res.status(403).send("Forbidden");
                req.user = decoded;
                next();
                };
              }
              
              module.exports = auth;
          
          

Now you can restrict access, e.g., only admins can assign tickets.

Step 5: Ticket List + Status Updates with React Hooks

In TicketList.js:

          
            import { useEffect, useState } from "react";
            import axios from "axios";
            
            export default function TicketList() {
              const [tickets, setTickets] = useState([]);
            
              useEffect(() => {
                axios.get("/api/tickets").then((res) => setTickets(res.data));
              }, []);
            
              const updateStatus = async (id, status) => {
              await axios.put(`/api/tickets/${id}`, { status });
              setTickets((prev) =>
                prev.map((t) => (t._id === id ? { ...t, status } : t))
              );
              };
            
              return (
              <div>
                {tickets.map((ticket) => (
                  <div key={ticket._id} className="p-3 border rounded mb-2">
                    <h3>{ticket.title}</h3>
                    <p>{ticket.description}</p>
                    <p>Status: {ticket.status}</p>
                    <button onClick={() => updateStatus(ticket._id, "closed")}>Close</button>
                  </div>
                ))}
              </div>
              );
            }
          
        

This is where we use React hooks for ticket status updates.

Step 6: File Uploads for Complaints (Attachments)

          
            <input type="file" onChange={(e) => setFile(e.target.files[0])} />
            Backend with Multer:
            const multer = require("multer");
            const upload = multer({ dest: "uploads/" });
            
            app.post("/api/upload", upload.single("file"), (req, res) => {
              res.json({ file: req.file.filename });
            });
          
        

Step 7: SLA Timers & Ticket Escalation

Add dueDate in tickets and run a cron job to auto-escalate.

          
            const cron = require("node-cron");
            const Ticket = require("./models/Ticket");
            
            cron.schedule("*/10 * * * *", async () => {
              const now = new Date();
              const overdueTickets = await Ticket.find({ dueDate: { $lt: now }, status: "open" });
              overdueTickets.forEach((t) => {
              t.status = "escalated";
              t.save();
              });
            });
          
        

Now your system acts like a real SLA management software.

Step 8: Notifications (Real-Time with WebSockets or Firebase)

Using Socket.IO:

          
            io.on("connection", (socket) => {
              console.log("User connected");
              socket.on("ticketCreated", (ticket) => {
              io.emit("newTicket", ticket);
              });
            });
          
        

Step 9: Admin Dashboard with Tailwind CSS + Charts

Use recharts for analytics. Example ticket resolution chart:

          
            import { PieChart, Pie, Tooltip } from "recharts";
 
            const data = [
              { name: "Open", value: 10 },
              { name: "Closed", value: 20 },
              { name: "Escalated", value: 5 },
            ];
            
            export default function Dashboard() {
              return (
              <PieChart width={400} height={400}>
                <Pie data={data} dataKey="value" outerRadius={150} fill="#8884d8" label />
                <Tooltip />
              </PieChart>
              );
            }
          
        

Step 10: Deployment (Vercel + Backend Hosting)

  • Deploy frontend on Vercel.
  • Deploy backend on Render or Heroku.
  • Connect both using environment variables.

Now you have a production-ready complaint tracking portal.

Here’s the Working Code to Build a Complaint Tracking Portal (Helpdesk-style) in ReactJS.

Why Choose Seven Square As Your Partner for React Ticketing System Development?

Our team has deep expertise in creating complaint management systems, ticketing systems, and ReactJS helpdesk portals that scale with your business.

  • We create ticket forms, role-based access, SLA management systems, and real-time notifications according to your workflow.
  • Our team integrates automation, chatbots, and AI features into ticketing systems so your support is always one step ahead.
  • With Tailwind CSS dashboards and interactive charts, your customer complaint tracking system will be both powerful and easy to use.

Want a Complaint Tracking System? Contact Us Today!

Build vs Buy: React Helpdesk vs. Tools Like Zendesk & Freshdesk

So, why not just use Zendesk or Freshdesk?

Big companies choose them because:

  • They are ready-made solutions with years of refinement.
  • They scale easily and come with 24/7 support.
  • They integrate with many third-party apps.

But here’s the problem: They can be expensive, especially for startups. That’s why many developers look for a Zendesk alternative or Freshdesk alternative, something customizable, cheaper, and flexible.

That’s where building your own with ReactJS outperforms everything. You’re not just stuck with pre-built features.

You can start with an open source ticketing system approach and grow it as your business scales.

From Code to a Full Helpdesk Solution

We started with a simple idea: Turn messy complaint handling into an organized help desk ticketing system.

From ticket creation, SLA management, and notifications to a live GitHub demo, you now have a complete roadmap.

With the right code and creativity, you can transform complaints into opportunities and build your own complaint management system that rivals even enterprise tools.

FAQs

  • Start by creating a React app, set up backend APIs with Node, and add ticket models.
  • Use Redux for state and Firebase/Auth0 for authentication.

  • Yes, you can add timers in your backend logic and escalate tickets automatically, making it a full SLA management software.

  • Both work well. Use MongoDB for flexibility and PostgreSQL if you need structured relations like ticket dependencies.

  • Yes, with React’s fast rendering and modular architecture, you can build a customer complaint tracking app that’s scalable and user-friendly.

Get in Touch

Got a project idea? Let's discuss it over a cup of coffee.

    Get in Touch

    Got a project idea? Let's discuss it over a cup of coffee.

      COLLABORATION

      Got a project? Let’s talk.

      We’re a team of creative tech-enthus who are always ready to help business to unlock their digital potential. Contact us for more information.