Support Ticket System Html Template Free -

<!-- Modal for new ticket --> <div id="ticketModal" class="modal"> <div class="modal-card"> <h2><i class="fas fa-life-ring"></i> Create new ticket</h2> <form id="ticketForm"> <div class="form-group"> <label>Subject *</label> <input type="text" id="ticketSubject" placeholder="e.g., Login issue, Billing question" required> </div> <div class="form-group"> <label>Priority</label> <select id="ticketPriority"> <option value="Low">Low</option> <option value="Medium" selected>Medium</option> <option value="High">High</option> </select> </div> <div class="form-group"> <label>Description (optional)</label> <textarea id="ticketDesc" rows="3" placeholder="Brief details..."></textarea> </div> <div class="modal-actions"> <button type="button" class="close-modal" id="closeModalBtn">Cancel</button> <button type="submit" class="btn-primary" style="border-radius: 40px;">Create ticket</button> </div> </form> </div> </div>

.action-icons i:hover color: #3b82f6;

/* filter bar */ .filter-bar background: white; border-radius: 20px; padding: 0.8rem 1.5rem; margin-bottom: 1.8rem; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; border: 1px solid #e2e8f0; support ticket system html template free

.modal-card h2 font-size: 1.5rem; margin-bottom: 1rem; "In progress" : ticket

// render tickets based on filters & search function renderTickets() let filtered = [...tickets]; // status filter if (currentStatusFilter !== "all") filtered = filtered.filter(t => t.status === currentStatusFilter); // search filter (ID or subject) if (currentSearchQuery.trim() !== "") const query = currentSearchQuery.trim().toLowerCase(); filtered = filtered.filter(t => t.id.toLowerCase().includes(query) // sort by id desc (newest first) filtered.sort((a,b) => b.id.localeCompare(a.id)); if (filtered.length === 0) tbody.innerHTML = `<tr><td colspan="6" style="text-align:center; padding: 2rem;">No tickets found. Create a new one! <i class="fas fa-smile-wink"></i></td></tr>`; return; tbody.innerHTML = filtered.map(ticket => let statusClass = ""; let statusIcon = ""; if (ticket.status === "open") statusClass = "open"; statusIcon = "fa-circle-info"; else if (ticket.status === "in-progress") statusClass = "in-progress"; statusIcon = "fa-arrows-spin"; else statusClass = "resolved"; statusIcon = "fa-circle-check"; let priorityClass = ""; if (ticket.priority === "High") priorityClass = "high"; else if (ticket.priority === "Medium") priorityClass = "medium"; else priorityClass = "low"; return ` <tr data-id="$ticket.id"> <td style="font-weight:500;">$ticket.id</td> <td><div class="ticket-subject"><i class="fas fa-message"></i> $escapeHtml(ticket.subject)</div></td> <td><span class="status-badge $statusClass"><i class="fas $statusIcon"></i> $ticket.status === "in-progress" ? "In progress" : ticket.status.charAt(0).toUpperCase() + ticket.status.slice(1)</span></td> <td><span class="priority $priorityClass">$ticket.priority</span></td> <td style="font-size:0.8rem;">$ticket.createdAt</td> <td class="action-icons"> <i class="fas fa-eye" title="View details" data-id="$ticket.id" data-action="view"></i> <i class="fas fa-pen" title="Change status" data-id="$ticket.id" data-action="edit"></i> <i class="fas fa-trash-alt" title="Delete" data-id="$ticket.id" data-action="delete"></i> </td> </tr> `; ).join(""); // attach event listeners to action icons after render document.querySelectorAll(".action-icons i").forEach(icon => icon.addEventListener("click", (e) => e.stopPropagation(); const ticketId = icon.getAttribute("data-id"); const action = icon.getAttribute("data-action"); if (action === "delete") if (confirm("Are you sure you want to delete this ticket?")) tickets = tickets.filter(t => t.id !== ticketId); updateStats(); renderTickets(); else if (action === "view") const ticket = tickets.find(t => t.id === ticketId); if (ticket) alert(`📋 Ticket $ticket.id\nSubject: $ticket.subject\nStatus: $ticket.status\nPriority: $ticket.priority\nCreated: $ticket.createdAt\nDescription: $ticket.description `); else if (action === "edit") // quick status toggle: cycle statuses open -> in-progress -> resolved const ticket = tickets.find(t => t.id === ticketId); if (ticket) if (ticket.status === "open") ticket.status = "in-progress"; else if (ticket.status === "in-progress") ticket.status = "resolved"; else ticket.status = "open"; updateStats(); renderTickets(); ); ); // simple XSS prevention function escapeHtml(str) return str.replace(/[&<>]/g, function(m) if(m === '&') return '&'; if(m === '<') return '<'; if(m === '>') return '>'; return m; ).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, function(c) return c; ); // add new ticket function addTicket(subject, priority, description) if (!subject.trim()) return false; const newId = generateTicketId(); const today = new Date().toISOString().slice(0,10); const newTicket = ; tickets.push(newTicket); updateStats(); renderTickets(); return true; // modal logic function openModal() modal.style.display = "flex"; function closeModal() modal.style.display = "none"; document.getElementById("ticketForm").reset(); newTicketBtn.addEventListener("click", openModal); closeModalBtn.addEventListener("click", closeModal); window.addEventListener("click", (e) => if (e.target === modal) closeModal(); ); ticketForm.addEventListener("submit", (e) => e.preventDefault(); const subject = document.getElementById("ticketSubject").value; const priority = document.getElementById("ticketPriority").value; const desc = document.getElementById("ticketDesc").value; if (!subject.trim()) alert("Please enter a subject"); return; addTicket(subject, priority, desc); closeModal(); ); // filter buttons logic filterBtns.forEach(btn => btn.addEventListener("click", () => filterBtns.forEach(b => b.classList.remove("active")); btn.classList.add("active"); currentStatusFilter = btn.getAttribute("data-filter"); renderTickets(); ); ); // search input searchInput.addEventListener("input", (e) => currentSearchQuery = e.target.value; renderTickets(); ); // export as CSV (free feature) function exportToCSV() let csvRows = []; csvRows.push(["Ticket ID", "Subject", "Status", "Priority", "Created Date", "Description"]); for (const ticket of tickets) csvRows.push([ ticket.id, `"$ticket.subject.replace(/"/g, '""')"`, ticket.status, ticket.priority, ticket.createdAt, `"$ "").replace(/"/g, '""')"` ]); const csvContent = csvRows.map(row => row.join(",")).join("\n"); const blob = new Blob([csvContent], type: "text/csv;charset=utf-8;" ); const link = document.createElement("a"); const url = URL.createObjectURL(blob); link.href = url; link.setAttribute("download", "support_tickets_export.csv"); document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); exportBtn.addEventListener("click", exportToCSV); // initial render updateStats(); renderTickets(); </script> </body> </html> span class="priority $priorityClass"&gt

.ticket-subject font-weight: 500; display: flex; align-items: center; gap: 8px;

logoAlibaba

Contact us

AMZScout Corp., 1735 Market Street, Suite 3750, Philadelphia, Pennsylvania 19103

Growthco DMCC, Unit No: BA402, DMCC Business Centre, Level No 1, Jewellery & Gemplex 3, Dubai, UAE

© AMZScout. All rights reserved 2016-2026