// TicketSystem.jsx - Updated with auto-reloading feature import React, { useState, useEffect, useContext, useRef, useCallback } from 'react'; import { createPortal } from 'react-dom'; import { AuthContext } from '../../App.jsx'; import useWebSocket from '../../hooks/useWebSocket.js'; import { MessageCircle, Plus, Search, Filter, Clock, AlertCircle, CheckCircle, X, User, FileText, Tag, AlertTriangle as Priority, Send, Edit, RefreshCw, Calendar, Clock as ClockIcon, Users } from "lucide-react"; import { colors } from '../../theme/colors'; import { dashLayout } from '../../theme/dashboardTokens'; import { DashboardViewShell, PageHeaderBar, StatTile, ActionButton, Dropdown, SectionCard } from '../../components/dashboardPrimitives'; import { UnifiedTooltip } from '../../components/DashboardComponents'; import { WS_BASE_URL } from '../../config/api'; // Ticket Status Badge const StatusBadge = ({ status }) => { const statusConfig = { 'open': { label: 'Open', color: colors.green, bgColor: `${colors.green}20` }, 'pending': { label: 'Pending', color: colors.yellow, bgColor: `${colors.yellow}20` }, 'in_progress': { label: 'In Progress', color: colors.blue, bgColor: `${colors.blue}20` }, 'resolved': { label: 'Resolved', color: colors.cyan, bgColor: `${colors.cyan}20` }, 'closed': { label: 'Closed', color: colors.magenta, bgColor: `${colors.magenta}20` } }; const config = statusConfig[status] || statusConfig.open; return ( {config.label} ); }; // Priority Badge const PriorityBadge = ({ priority }) => { const priorityConfig = { 'low': { label: 'Low', color: colors.cyan, bgColor: `${colors.cyan}20` }, 'medium': { label: 'Medium', color: colors.blue, bgColor: `${colors.blue}20` }, 'high': { label: 'High', color: colors.yellow, bgColor: `${colors.yellow}20` }, 'urgent': { label: 'Urgent', color: colors.red, bgColor: `${colors.red}20` }, 'critical': { label: 'Critical', color: colors.brightRed, bgColor: `${colors.brightRed}20` } }; const config = priorityConfig[priority] || priorityConfig.medium; return ( {config.label} ); }; // Ticket Card Component const TicketCard = ({ ticket, onSelect, onAction, isAdmin = false }) => { const formatDate = (dateString) => { return new Date(dateString).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); }; const formatTime = (dateString) => { return new Date(dateString).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }); }; return (
onSelect(ticket)} >

{ticket.subject}

{ticket.description}

#{ticket.id}
{formatDate(ticket.created_at)}
{formatTime(ticket.created_at)}
{isAdmin && (
{ticket.user_username}
)}
{ticket.message_count || 0} messages
{ticket.last_reply && (
Last reply: {formatDate(ticket.last_reply)}
)}
{isAdmin && ( <> {ticket.status === 'open' && ( )} )}
); }; // Create Ticket Modal const CreateTicketModal = ({ isOpen, onClose, onSubmit }) => { const [formData, setFormData] = useState({ subject: '', description: '', priority: 'medium', category: 'general' }); const categories = [ { value: 'general', label: 'General Support' }, { value: 'billing', label: 'Billing Issue' }, { value: 'technical', label: 'Technical Problem' }, { value: 'server', label: 'Server Issue' }, { value: 'feature', label: 'Feature Request' }, { value: 'other', label: 'Other' } ]; const priorities = [ { value: 'low', label: 'Low Priority' }, { value: 'medium', label: 'Medium Priority' }, { value: 'high', label: 'High Priority' }, { value: 'urgent', label: 'Urgent' }, { value: 'critical', label: 'Critical' } ]; const handleSubmit = (e) => { e.preventDefault(); if (formData.subject.trim() && formData.description.trim()) { onSubmit(formData); setFormData({ subject: '', description: '', priority: 'medium', category: 'general' }); } }; if (!isOpen) return null; return createPortal(

Create New Ticket

setFormData(prev => ({ ...prev, category: value }))} placeholder="Select category" icon={Tag} />
setFormData(prev => ({ ...prev, priority: value }))} placeholder="Select priority" icon={Priority} />
setFormData(prev => ({ ...prev, subject: e.target.value }))} className="w-full rounded-xl px-4 py-3 text-sm focus:outline-none transition-all duration-200 border" style={{ backgroundColor: colors.brightBlack, borderColor: colors.brightBlack, color: colors.brightWhite }} placeholder="Brief description of your issue" required />