update
This commit is contained in:
197
gnx-react/components/pages/support/TicketStatusCheck.tsx
Normal file
197
gnx-react/components/pages/support/TicketStatusCheck.tsx
Normal file
@@ -0,0 +1,197 @@
|
||||
"use client";
|
||||
import { useState, FormEvent } from 'react';
|
||||
import { checkTicketStatus, SupportTicket } from '@/lib/api/supportService';
|
||||
|
||||
const TicketStatusCheck = () => {
|
||||
const [ticketNumber, setTicketNumber] = useState('');
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
const [searchError, setSearchError] = useState<string | null>(null);
|
||||
const [ticket, setTicket] = useState<SupportTicket | null>(null);
|
||||
|
||||
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
setIsSearching(true);
|
||||
setSearchError(null);
|
||||
setTicket(null);
|
||||
|
||||
try {
|
||||
const response = await checkTicketStatus(ticketNumber);
|
||||
setTicket(response);
|
||||
} catch (error: any) {
|
||||
if (error.message === 'Ticket not found') {
|
||||
setSearchError('Ticket not found. Please check your ticket number and try again.');
|
||||
} else {
|
||||
setSearchError('An error occurred while searching. Please try again.');
|
||||
}
|
||||
} finally {
|
||||
setIsSearching(false);
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ticket-status-check">
|
||||
<div className="row justify-content-center">
|
||||
<div className="col-12 col-lg-8">
|
||||
<div className="form-header text-center">
|
||||
<h2>Check Ticket Status</h2>
|
||||
<p>Enter your ticket number to view the current status and details of your support request.</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="status-search-form">
|
||||
<div className="search-input-group">
|
||||
<input
|
||||
type="text"
|
||||
value={ticketNumber}
|
||||
onChange={(e) => setTicketNumber(e.target.value)}
|
||||
placeholder="Enter your ticket number (e.g., TKT-20231015-ABCDE)"
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
disabled={isSearching}
|
||||
>
|
||||
{isSearching ? (
|
||||
<>
|
||||
<span className="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
|
||||
Searching...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="fa-solid fa-search me-2"></i>
|
||||
Check Status
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{searchError && (
|
||||
<div className="alert alert-danger mt-4" role="alert">
|
||||
<i className="fa-solid fa-triangle-exclamation me-2"></i>
|
||||
{searchError}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{ticket && (
|
||||
<div className="ticket-details">
|
||||
<div className="ticket-header">
|
||||
<div className="ticket-number">
|
||||
<i className="fa-solid fa-ticket me-2"></i>
|
||||
{ticket.ticket_number}
|
||||
</div>
|
||||
<div
|
||||
className="ticket-status-badge"
|
||||
style={{ backgroundColor: ticket.status_color }}
|
||||
>
|
||||
{ticket.status_name}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="ticket-info">
|
||||
<h3>{ticket.title}</h3>
|
||||
<div className="ticket-meta">
|
||||
<div className="meta-item">
|
||||
<i className="fa-solid fa-calendar me-2"></i>
|
||||
<strong>Created:</strong> {formatDate(ticket.created_at)}
|
||||
</div>
|
||||
<div className="meta-item">
|
||||
<i className="fa-solid fa-clock me-2"></i>
|
||||
<strong>Last Updated:</strong> {formatDate(ticket.updated_at)}
|
||||
</div>
|
||||
{ticket.priority_name && (
|
||||
<div className="meta-item">
|
||||
<i className="fa-solid fa-flag me-2"></i>
|
||||
<strong>Priority:</strong>
|
||||
<span
|
||||
className="priority-badge ms-2"
|
||||
style={{ backgroundColor: ticket.priority_color }}
|
||||
>
|
||||
{ticket.priority_name}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{ticket.category_name && (
|
||||
<div className="meta-item">
|
||||
<i className="fa-solid fa-folder me-2"></i>
|
||||
<strong>Category:</strong> {ticket.category_name}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="ticket-description">
|
||||
<h4>Description</h4>
|
||||
<p>{ticket.description}</p>
|
||||
</div>
|
||||
|
||||
{ticket.messages && ticket.messages.length > 0 && (
|
||||
<div className="ticket-messages">
|
||||
<h4>Messages ({ticket.messages.length})</h4>
|
||||
<div className="messages-list">
|
||||
{ticket.messages
|
||||
.filter(msg => !msg.is_internal)
|
||||
.map((message, index) => (
|
||||
<div key={message.id} className="message-item">
|
||||
<div className="message-header">
|
||||
<div className="message-author">
|
||||
<i className="fa-solid fa-user-circle me-2"></i>
|
||||
{message.author_name || message.author_email}
|
||||
</div>
|
||||
<div className="message-date">
|
||||
{formatDate(message.created_at)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="message-content">
|
||||
{message.content}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{ticket.activities && ticket.activities.length > 0 && (
|
||||
<div className="ticket-timeline">
|
||||
<h4>Activity Timeline</h4>
|
||||
<div className="timeline-list">
|
||||
{ticket.activities.slice(0, 5).map((activity, index) => (
|
||||
<div key={activity.id} className="timeline-item">
|
||||
<div className="timeline-icon">
|
||||
<i className="fa-solid fa-circle"></i>
|
||||
</div>
|
||||
<div className="timeline-content">
|
||||
<div className="timeline-description">
|
||||
{activity.description}
|
||||
</div>
|
||||
<div className="timeline-date">
|
||||
{formatDate(activity.created_at)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TicketStatusCheck;
|
||||
|
||||
Reference in New Issue
Block a user