import React, { useState, useEffect } from "react"; import { Button } from "./ui/button"; import Table from "./ui/table"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "./ui/dialog"; import { Input } from "./ui/input"; import { Textarea } from "./ui/textarea"; import { Label } from "./ui/label"; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "./ui/select"; import { CustomTabs } from "./ui/CustomTabs"; import {localizeTime} from "../lib/localizeTime"; interface Ticket { id: number; title: string; description: string; status: 'open' | 'in-progress' | 'resolved' | 'closed'; // Add 'closed' here created_at: string; updated_at: string; created_by: number; } interface Message { id: number; ticket_id: number; user_id: number; message: string; created_at: string; user_type: string; } const PUBLIC_TICKET_API_URL = import.meta.env.PUBLIC_TICKET_API_URL; function Ticketing() { const [tickets, setTickets] = useState([]); const [messages, setMessages] = useState([]); const [selectedTicket, setSelectedTicket] = useState<(Ticket & { status: 'open' | 'in-progress' | 'resolved' | 'closed' }) | null>(null); const [activeTab, setActiveTab] = useState<'open' | 'in-progress' | 'resolved' | 'closed'>('open'); const [isDialogOpen, setIsDialogOpen] = useState(false); const [isMessageDialogOpen, setIsMessageDialogOpen] = useState(false); const [newMessage, setNewMessage] = useState(''); const [formData, setFormData] = useState({title: '', description: '', status: 'open' as const, }); // Fetch tickets useEffect(() => {fetchTickets(); }, [activeTab]); // Fetch messages when ticket is selected useEffect(() => {if (selectedTicket) {fetchMessages(selectedTicket.id);}}, [selectedTicket]); const fetchTickets = async () => { try { const response = await fetch(`${PUBLIC_TICKET_API_URL}?action=get_tickets&status=${activeTab}`); const data = await response.json(); if (data.success) { setTickets(data.tickets); } } catch (error) { console.error('Error fetching tickets:', error); } }; const fetchMessages = async (ticketId: number) => { try { const response = await fetch(`${PUBLIC_TICKET_API_URL}?action=get_messages&ticket_id=${ticketId}`); const data = await response.json(); console.log('Messages response:', data); // Debug log if (data.success) { setMessages(data.messages || []); } } catch (error) { console.error('Error fetching messages:', error); } }; const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const response = await fetch(PUBLIC_TICKET_API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'create_ticket', ...formData, }), }); const data = await response.json(); if (data.success) { fetchTickets(); // Refresh the list setIsDialogOpen(false); setFormData({ title: '', description: '', status: 'open' }); } } catch (error) { console.error('Error creating ticket:', error); } }; const handleStatusChange = async (ticketId: number, newStatus: 'open' | 'in-progress' | 'resolved' | 'closed') => { try { const response = await fetch(PUBLIC_TICKET_API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'update_ticket_status', ticket_id: ticketId, status: newStatus, }), }); const data = await response.json(); if (data.success) { fetchTickets(); // Refresh the list if (selectedTicket) { setSelectedTicket({ ...selectedTicket, status: newStatus }); } } } catch (error) { console.error('Error updating ticket status:', error); } }; const handleSendMessage = async () => { if (!selectedTicket || !newMessage.trim()) return; try { const response = await fetch(PUBLIC_TICKET_API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'add_message', ticket_id: selectedTicket.id, message: newMessage, user_type: 'user' }), }); const data = await response.json(); if (data.success) { fetchMessages(selectedTicket.id); // Refresh messages setNewMessage(''); } } catch (error) { console.error('Error sending message:', error); } }; const handleDeleteTicket = async (ticketId: number) => { try { const response = await fetch(PUBLIC_TICKET_API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'delete_ticket', ticket_id: ticketId, }), }); const data = await response.json(); if (data.success) { fetchTickets(); // Refresh the list if (selectedTicket?.id === ticketId) { setIsMessageDialogOpen(false); } } } catch (error) { console.error('Error deleting ticket:', error); } }; // Table configuration const tableHeaders = ['ID', 'Title', 'Description', 'Status', 'Created At', 'Actions']; const tableData = tickets.map(ticket => ({ id: ticket.id, title: ticket.title, description: ticket.description, status: ticket.status, created_at: localizeTime(ticket.created_at), actions: (
) })); const statusColors = {open: 'bg-green-500', 'in-progress': 'bg-yellow-500', resolved: 'bg-blue-500', closed: 'bg-red-500', }; return (

Ticket / Report

setActiveTab(value as any)} /> { tableHeaders.map((thead, index) => ( )) } { tableData.length > 0 ? ( { tableData.map((data, index) => ( )) } ) : ( ) }
{thead}
{data.id} {data.title} {data.description} {data.status} {data.created_at} {data.actions}
No {activeTab.charAt(0).toUpperCase() + activeTab.slice(1)} Ticket Found
{/* */} {/* Create Ticket Dialog */} Create New Ticket
{/* Ticket Messages Dialog */} Ticket #{selectedTicket?.id}: {selectedTicket?.title} {selectedTicket && (

Ticket Details

{selectedTicket.description}

Status: {selectedTicket.status} |  Created: {new Date(selectedTicket.created_at).toLocaleString()}

Conversation

{ messages.length > 0 ? ( messages.map(message => (

{message.message}

{localizeTime(message.created_at)}

)) ) : (

No messages yet

) }
{selectedTicket.status === 'closed' ? ( ) : ( <> {selectedTicket.status !== 'in-progress' && ( )} {selectedTicket.status !== 'resolved' && ( )} )}
)}
); } export default Ticketing;