SITFD PHP is a functional ticketing shell — it has the data and the workflow APIs, but the UI treats every actor as a text row. No avatar, no role badge, no client/staff distinction, no SLA timer, no macros, no canned responses, no time tracking, no audit trail for department transfer, no per-department analytics, no admin UI to create departments. The Reports page is the singular bright spot. Path to production: a 3-phase build that adds Identity (avatars + role chips), Department Operations (CRUD + transfer + audit), and SLA/Macros (live timer + canned responses). Top 5 fixes can ship in 2 days.
In Zendesk, a ticket header always shows three things: requester name + avatar + role, assignee name + avatar + role, and company. In WHMCS, the same header shows client name + avatar + email + phone. SITFD shows only the requester name as plain text. There is no way to tell at a glance whether a message is from the citizen, the company, the agent, or the supervisor.
A single line of text: Requester · Data Labs Karachi — no avatar, no role badge, no email, no phone, no company, no tier, no custom fields.
Every message in the timeline (whether from the client, the agent, the supervisor, or an internal note) is rendered as a plain text block with the same font and color. Zendesk uses color-coded bubbles: client (blue, left-aligned), agent (green, right-aligned), internal note (yellow/lock icon). WHMCS uses a side-bar with reply type prefix ([Staff Note], [Client Reply], [System]). On SITFD, the only differentiator is a tiny "Internal note" pill that is easy to miss.
┌─────────────────────────────────────────────────────────────┐ │ TICKET HEADER LAB-2026-000004 │ │ Status: in progress Priority: high │ │ Requester · Data Labs Karachi │ ← no avatar, no role, no email │ City: Sukkur · Department: Labor │ ├─────────────────────────────────────────────────────────────┤ │ TIMELINE │ │ │ │ Hi, I am writing to bring to your notice... [client text] │ ← looks like every other message │ — 18 Aug 2026 09:42 │ │ │ │ [Internal note] Escalated to L2 │ ← only differentiator is this tiny pill │ — 18 Aug 2026 10:18 │ │ │ │ We are looking into this. Will revert shortly. [agent] │ │ — 18 Aug 2026 11:05 │ │ │ │ …all use the same font, color, no avatar, no role badge… │ └─────────────────────────────────────────────────────────────┘
<span class="font-medium">Data Labs Karachi</span> — that's it, no chips.Client messages = blue bubble, left-aligned, with avatar. Agent = green bubble, right-aligned with avatar. Internal note = yellow bubble with lock icon. Hover avatar → contact card (email, phone, last 5 tickets).
Timeline shows [Staff Note] / [Client Reply] / [System] prefix in front of every message. Click the prefix → filter all messages of that type. Side-bar shows assignee, department, time logged.
Plain text paragraphs. No bubble, no avatar, no system message type, no type prefix, no side-bar. The only "differentiation" is a 11px "Internal note" pill that is easy to miss.
A ticketing system needs three departmental capabilities: CRUD departments (create, rename, archive), per-department analytics (how many tickets are in each dept right now), and move tickets between departments (with an audit trail). I tested all three.
POC can view /admin/departments (17 departments on login, 19 after I POSTed two test ones — "QA Test Dept 1" and "QA Test Dept 2"). Update via POST /admin/departments/{id}/update succeeded. The new departments appear in the dropdown on the ticket page.
No Create Department button in the UI. POC has to know the URL /admin/departments/create and POST to it. The page returns 200 with no form. No Delete/Archive button either. So the only way to add a dept is via direct API call — a UX bug, not a security one (POC is admin).
| Page | Shows dept breakdown? | Notes |
|---|---|---|
/reports | Yes | 7 report types including "By Department" drill-down. POC sees 7 departments with their counts. |
/dashboard | No | All counters show 0 for POC. Dashboard widget is broken (see §2.4). |
/admin/departments | Partial | Lists department names but no per-dept ticket count or owner count. |
/tickets (filters) | Filter only | Can filter by department dropdown, but no summary count next to each dept. |
POC and Admin can change a ticket's department from the ticket detail page (dropdown shown above the action buttons). The change persists. But the timeline after the move does not show a "moved from Health → Labor" event in the visible UI. The history table internally records it (the audit trail exists), but the user-facing timeline does not render it.
Across all 9 roles, the dashboard metrics show 0 for every counter. The data is there (the Reports page shows 185 tickets, 38 open). The dashboard widget is querying a different endpoint or the wrong column. The dashboard also takes 15 seconds for Admin and 7.7 seconds for DG Labor on first load — likely a cold-cache issue.
| Role | Dashboard load time | New tickets | Open | Resolved | Avg response |
|---|---|---|---|---|---|
| Super Admin | 0.4s | 0 | 0 | 0 | 0 |
| Admin | 15.0s | 0 | 0 | 0 | 0 |
| POC | 0.6s | 0 | 0 | 0 | 0 |
| DG Labor | 7.7s | 0 | 0 | 0 | 0 |
| Labor Staff | 500 | — | — | — | — |
| IT-Verify | 500 | — | — | — | — |
| FD Staff | 0.4s | 0 | 0 | 0 | 0 |
| Agent | 0.3s | 0 | 0 | 0 | 0 |
The timeline is the heart of a ticketing system. It needs to answer three questions at a glance: who said this? who can see this? what changed?
The history table internally records every state change (status, assignee, dept, priority). But the user-facing timeline does not render these as distinct event types. When a ticket moves from Health → Labor → Escalate → Resolve, the timeline shows a flat list of messages with no "system event" markers.
Vertical timeline with 4 event types rendered distinctly: Message (bubbles, color-coded), System Event (gray italic, "Status changed from Open to Pending"), Internal Note (yellow background, lock icon, name + "Internal Note" label), Attachment (file icon). Filter pills at the top: All · Public · Internal · Events.
Every reply prefixed with type: [Staff Note], [Client Reply], [System]. Side-bar shows ticket properties (priority, dept, assigned, status, time logged). No filter pills but the prefix is searchable.
Flat list of message paragraphs. No event type rendering. No filter pills. No side-bar. No [Type] prefix. Internal note only distinguished by a tiny "Internal note" pill in the same font/size as the rest of the text.
SLA is the single most important feature for a complaint system. The user said "how follow-up was done" — SLA tracking is the answer.
| Feature | Zendesk | WHMCS | SITFD PHP |
|---|---|---|---|
| Static SLA deadline | Yes | Yes | Yes — "5d 1h until SLA breach" |
| Live countdown timer | Yes — counts every second | Yes | No — text only, no JS update |
| Business hours / 24×7 | Yes — per policy | Yes | No configuration |
| Breach alert (visual) | Color shifts to red < 1h | Red badge | No shift, no badge |
| Pause SLA on client reply | Configurable | Yes | Paused status exists, but SLA doesn't pause visibly |
| Per-priority SLA | Yes | Yes | No — single SLA policy |
| SLA report | Yes | Yes | No SLA report |
Three productivity features that turn a ticketing shell into a support workstation. All three are missing.
Zendesk macros: insert pre-filled actions (status + assignee + reply + tag) in one click. WHMCS canned responses: pre-written replies triggered by `/shortcut`. SITFD has neither. The reply box is plain textarea.
Missing
WHMCS tracks minutes per ticket per agent. Visible on the ticket and on the bill. Zendesk has "Talk Time" + "Work Time" via its integration. SITFD has no time field on the ticket.
Missing
Tags drive filtering, reporting, and triggers in Zendesk. WHMCS uses departments + status. SITFD has only status + priority + dept + city — no free-form tags.
Missing
Zendesk: merge ticket A into ticket B. All messages, attachments, events move. Both tickets get a "merged into" link. WHMCS: no merge. SITFD: no merge.
Missing
Zendesk: side-channel with a colleague without leaving the ticket. Threaded. Becomes part of the audit trail. SITFD: no side conversations.
Missing
Zendesk CSAT: after resolve, ask the client to rate 1-5. WHMCS: optional. SITFD: no rating.
Missing
| Feature | Zendesk | WHMCS | SITFD PHP | Why it matters |
|---|---|---|---|---|
| Requester avatar + role | Yes | Yes | No | Identity at a glance |
| Per-department analytics | Yes | Yes | Reports only | Operations visibility |
| Create department via UI | Yes | Yes | No UI | Self-service admin |
| Dept transfer with audit trail | Yes | Yes | Works, no visible event | Compliance |
| Live SLA timer | Yes | Yes | No | Breach prevention |
| Business hours SLA | Yes | Yes | No | Operational accuracy |
| Macros / canned responses | Yes | Yes | No | Agent productivity |
| Time tracking | Third-party | Yes | No | Billing + accountability |
| Tags / labels | Yes | No | No | Filtering + reporting |
| Ticket merge | Yes | No | No | Deduplication |
| Side conversations | Yes | No | No | Team collaboration |
| CSAT rating | Yes | Optional | No | Service quality |
| Linked tickets | Yes | Yes | Section exists but empty | Repeat-callers |
| KB search | Yes | Yes | Yes | Self-service |
| Custom fields | Yes | Yes | No UI | Schema flexibility |
| Email-to-ticket | Yes | Yes | Channel shown but not configured | Channel parity |
| WhatsApp integration | Via Sunshine | No | Yes — channel shown | Local context |
| Triggers / automations | Yes | Yes | No | Workflow automation |
| Round-robin assignment | Yes | Yes | No | Fair distribution |
| Customer portal | Yes | Yes | Yes | Self-service |
| Track ticket anonymously | No | No | Yes — /track | Trust + transparency |
From "functional shell" to "production ticketing system" in three sequential phases. Each phase is self-contained and shippable.
<span class="font-medium">Data Labs Karachi</span>The 5 highest-impact fixes that can ship without Phase 1 starting. Each is a single backend tweak + a small UI change.
All 9 roles see zeros on the dashboard while Reports shows 185 tickets. The widget query is broken.
POC has to POST directly to the API. The route exists. Just needs a form + button.
GET /admin/departments/create formHistory table records dept moves, status changes, assignee changes. The timeline just doesn't render them.
Static "5d 1h" text — needs a JS timer that updates every second and shifts color to red < 1h.
Just expose what's already in the database. The profile data is fetched, just not rendered.