import React, { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import apiClient from '../../../utils/apiClient'; interface Ticket { id: number; title: string; message: string; status: string; priority: string; category: string; createdAt: string; updatedAt: string; responses: Response[]; assignedTo?: number; closedAt?: string; } interface Response { id: number; message: string; isInternal: boolean; createdAt: string; userId: number; user: { username: string; operator: boolean; }; } const TicketsPage: React.FC = () => { const [tickets, setTickets] = useState([]); const [loading, setLoading] = useState(true); const [filters, setFilters] = useState({ status: 'all', category: 'all', priority: 'all' }); useEffect(() => { fetchTickets(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters]); const fetchTickets = async () => { try { const params: Record = {}; if (filters.status !== 'all') params.status = filters.status; if (filters.category !== 'all') params.category = filters.category; if (filters.priority !== 'all') params.priority = filters.priority; const response = await apiClient.get('/api/ticket', { params }); setTickets(response.data.tickets || []); setLoading(false); } catch (error) { console.error('Ошибка загрузки тикетов:', error); setLoading(false); } }; const getStatusBadge = (status: string) => { const badges: Record = { open: { color: 'bg-green-100 text-green-800', text: 'Открыт', emoji: '🟢' }, in_progress: { color: 'bg-blue-100 text-blue-800', text: 'В работе', emoji: '🔵' }, awaiting_reply: { color: 'bg-yellow-100 text-yellow-800', text: 'Ожидает ответа', emoji: '🟡' }, resolved: { color: 'bg-purple-100 text-purple-800', text: 'Решён', emoji: '🟣' }, closed: { color: 'bg-gray-100 text-gray-800', text: 'Закрыт', emoji: '⚪' } }; const badge = badges[status] || badges.open; return ( {badge.emoji} {badge.text} ); }; const getPriorityBadge = (priority: string) => { const badges: Record = { urgent: { color: 'bg-red-100 text-red-800 border-red-300', text: 'Срочно', emoji: '🔴' }, high: { color: 'bg-orange-100 text-orange-800 border-orange-300', text: 'Высокий', emoji: '🟠' }, normal: { color: 'bg-gray-100 text-gray-800 border-gray-300', text: 'Обычный', emoji: '⚪' }, low: { color: 'bg-green-100 text-green-800 border-green-300', text: 'Низкий', emoji: '🟢' } }; const badge = badges[priority] || badges.normal; return ( {badge.emoji} {badge.text} ); }; const getCategoryIcon = (category: string) => { const icons: Record = { general: '💬', technical: '⚙️', billing: '💰', other: '📝' }; return icons[category] || icons.general; }; const formatRelativeTime = (dateString: string) => { const date = new Date(dateString); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMs / 3600000); const diffDays = Math.floor(diffMs / 86400000); if (diffMins < 1) return 'только что'; if (diffMins < 60) return `${diffMins} мин. назад`; if (diffHours < 24) return `${diffHours} ч. назад`; if (diffDays < 7) return `${diffDays} дн. назад`; return date.toLocaleDateString('ru-RU'); }; if (loading) { return (

Загрузка тикетов...

); } return (
{/* Header */}

Тикеты поддержки

Управляйте вашими обращениями в службу поддержки

Создать тикет
{/* Filters */}
{/* Status Filter */}
{/* Category Filter */}
{/* Priority Filter */}
{/* Tickets Grid */} {tickets.length === 0 ? (
📭

Нет тикетов

У вас пока нет открытых тикетов поддержки

Создать первый тикет
) : (
{tickets.map((ticket) => (
{/* Header */}
{getCategoryIcon(ticket.category)}

{ticket.title}

{getPriorityBadge(ticket.priority)}

{ticket.message.substring(0, 150)}...

{getStatusBadge(ticket.status)}
{/* Footer */}
🕒 {formatRelativeTime(ticket.updatedAt)} 💬 {ticket.responses?.length || 0} ответов {ticket.closedAt && ( 🔒 Закрыт )}
Открыть →
))}
)}
); }; export default TicketsPage;