Build a React Support Ticket Dashboard · PRACTICAL GUIDE

Create, Assign and Resolve Tickets with React State

A dashboard becomes useful when an agent can create, update and resolve tickets.

HANDBOOK JOURNEYByte 3 of 5View all Bytes
HANDBOOK JOURNEYByte 3 of 5

Build a React Support Ticket Dashboard

0 of 5 completed · 30 min for this Byte
  1. 01BYTE 01Build a React Project
  2. 02BYTE 02Build a React Ticket Dashboard with Reusable Components
  3. 04BYTE 04Connect Ticket APIs, Routing and Shared State
  4. 05BYTE 05Test, Optimize and Deploy the React Ticket Dashboard

What you will build

Milestone 13: Use the typed Ticket and TicketCard files from Byte 12. Create a form that refuses blank subjects and a reducer that adds or resolves issues. This is the first interactive milestone of the project.

A dashboard becomes useful when an agent can create, update and resolve tickets.

Visible checkpoint: Create adds a card; dispatching a status action updates its status without mutating the original array. You can study this Byte by itself, though the project can also be built progressively.

Understand the concept first

Controlled form fields keep typed values in React state. useReducer can express create, status change and assignment as explicit actions. Reject empty subject values and preserve immutable updates.

In plain language, an interface should show useful information and respond predictably to users. We begin with one small technical change before introducing more features.

Architecture: what happens underneath

BUILD THE PROJECT · CHECKPOINT 1/5

From project files to browser output

index.html

Root mounting point

Expected outcome: The first app screen appears once you run npm run dev.

Execution path

TEXT
01Form input → validation → dispatch action → next state → card updates

Follow the arrows and explain which step is React state, which is a browser action, and which would require a real backend.

Explore a realistic preview

BUILD ONE APPLICATION · BYTE 1/5

Setup & layout

Explore the UI that this Byte helps you build. Demo data only; no actual customer records.

● ● ●   support-desk.localReact preview

Support Desk

Customer support ticket overview

Total2
Open1
Resolved0

Click a ticket to inspect its selected state.

Stage 1: Setup & layout. This preview illustrates the progression, not a connected backend.

Use the visual to predict what a user would see. The preview uses simulated demo data and does not represent a connected enterprise service.

Coding walkthrough step by step

Complete, ordered project checkpoints: Read the source-of-truth build guide. Use the full replacement files from that guide alongside the focused explanations below. Some snippets below demonstrate an insertion rather than a complete file.

Step 1 — Create a reducer for changes

Edit or create the indicated file.

TSX
01// src/ticketReducer.ts02import type {Ticket} from './data/tickets';03export type Action={type:'add';ticket:Ticket}|{type:'status';id:number;status:Ticket['status']};04export function ticketReducer(state:Ticket[],action:Action):Ticket[]{05 switch(action.type){06 case 'add':return [...state,action.ticket];07 case 'status':return state.map(t=>t.id===action.id?{...t,status:action.status}:t);08 }09}

What this step accomplishes: A dashboard becomes useful when an agent can create, update and resolve tickets.

Check: Run your app or inspect the updated component before continuing.

Step 2 — Add reducer and controlled input

Edit or create the indicated file.

TSX
01// src/App.tsx — inside App, replacing the static ticket source02const [tickets,dispatch]=useReducer(ticketReducer,initialTickets);03const [subject,setSubject]=useState('');04function addTicket(){const title=subject.trim();if(!title)return;05 dispatch({type:'add',ticket:{id:Date.now(),subject:title,priority:'Low',status:'Open'}});setSubject('');}

What this step accomplishes: Create adds a card; dispatching a status action updates its status without mutating the original array.

Check: Run your app or inspect the updated component before continuing.

Step 3 — Connect controls to the screen

Edit or create the indicated file.

TSX
01// Add above ticket cards inside the JSX:02<label htmlFor="subject">Issue subject</label>03<input id="subject" value={subject} onChange={e=>setSubject(e.target.value)} className="border p-2"/>04<button type="button" onClick={addTicket}>Create ticket</button>05// Pass tickets.map(...) to cards; to resolve a ticket dispatch:06dispatch({type:'status',id:101,status:'Resolved'});

What this step accomplishes: Create adds a card; dispatching a status action updates its status without mutating the original array.

Check: Run your app or inspect the updated component before continuing.

Expected screen and execution

What you should observe: Create adds a card; dispatching a status action updates its status without mutating the original array.

Trace it: Form input → validation → dispatch action → next state → card updates. A user-visible output is stronger evidence than a code snippet alone.

Interactive decision and diagnosis

If the expected result does not appear, inspect the relevant file and resolve the first console error. Compare your current code to the preceding checkpoint.

Typical issue: The code fragments modify Byte 02; import useReducer, useState and ticketReducer in App. The dispatch call belongs in an event handler, not inside render.

How teams use this pattern

A frontend developer implements the interface, a tester verifies accessible controls and failure behavior, and the product owner describes the expected result. This is a simplified demonstration of that collaboration, not a representation of a particular company's internal infrastructure.

Compare UI and implementation

What the user seesWhat the application does
Create adds a card; dispatching a status action updates its status without mutating the original array.Form input → validation → dispatch action → next state → card updates
An action or failureA typed handler, state transition or error boundary determines the visible response

Hands-on practice

Add a status button to TicketCard using an onResolve callback and validate a blank title.

Evidence: Capture the visible result, explain the code you changed, and reproduce one failure case.

Interview Bit

Question: How does this milestone change what the learner can actually do?

Answer: It connects form validation and reducer actions to visible issue creation and resolution.

Key Takeaways

  1. Controlled inputs keep form values in React state.
  2. Validation rejects an empty issue title.
  3. useReducer centralizes related ticket transitions.
  4. Actions describe an add or resolve request.
  5. Reducers must return new state rather than mutate old data.
  6. A ticket id identifies the record to update.
  7. Derived Open counts change when ticket status changes.
  8. Errors must be readable and recoverable.

Knowledge Check and Primary Sources

PRACTISE AND CHECK

Knowledge Check · 5 questions

Choose one answer per question, check your results, and retry.

0 of 5 answered

Question 1

01.Why use Vite??

Question 2

02.Which file describes the root UI??

Question 3

03.What is a component??

Question 4

04.What does TypeScript help with??

Question 5

05.Why separate data and UI??

Complete all questions to see your score.

Frequently asked: Is a real backend required for this Byte? No; this handbook uses a mock boundary until you supply a real API. Does the demo contain real customer data? No.

Primary sources: Extracting state logic into a reducer · React forms.