38916-vm/index.php
Flatlogic Bot fd8a2de90a z
2026-03-01 18:23:38 +00:00

208 lines
8.6 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once __DIR__ . '/auth.php';
$user = requireAuth();
// Filters for Helpers and Curators
$statusFilter = $_GET['status'] ?? '';
$categoryFilter = $_GET['category'] ?? '';
$searchQuery = $_GET['search'] ?? '';
$params = [];
$sql = "SELECT t.*, u.username as creator_name FROM tickets t JOIN users u ON t.user_id = u.id";
$whereClauses = [];
if ($user['role'] === 'user') {
$whereClauses[] = "t.user_id = ?";
$params[] = $user['id'];
} else {
if ($statusFilter) {
$whereClauses[] = "t.status = ?";
$params[] = $statusFilter;
}
if ($categoryFilter) {
$whereClauses[] = "t.category = ?";
$params[] = $categoryFilter;
}
if ($searchQuery) {
$whereClauses[] = "(t.title LIKE ? OR t.description LIKE ?)";
$params[] = "%$searchQuery%";
$params[] = "%$searchQuery%";
}
}
if (!empty($whereClauses)) {
$sql .= " WHERE " . implode(" AND ", $whereClauses);
}
$sql .= " ORDER BY t.created_at DESC";
$stmt = db()->prepare($sql);
$stmt->execute($params);
$tickets = $stmt->fetchAll();
$openTicketsCount = 0;
if ($user['role'] === 'user') {
foreach ($tickets as $t) {
if ($t['status'] !== 'closed') $openTicketsCount++;
}
}
// Stats for Curator
$stats = [];
if ($user['role'] === 'curator') {
$stats['total'] = db()->query("SELECT COUNT(*) FROM tickets")->fetchColumn();
$stats['active'] = db()->query("SELECT COUNT(*) FROM tickets WHERE status != 'closed'")->fetchColumn();
// Avg response time (simplified: difference between ticket creation and first message from a helper/curator)
$stats['avg_response'] = db()->query("
SELECT ROUND(AVG(TIMESTAMPDIFF(HOUR, t.created_at, m.created_at)), 1)
FROM tickets t
JOIN messages m ON t.id = m.ticket_id
JOIN users u ON m.user_id = u.id
WHERE u.role != 'user'
AND m.id = (
SELECT MIN(m2.id)
FROM messages m2
JOIN users u2 ON m2.user_id = u2.id
WHERE m2.ticket_id = t.id AND u2.role != 'user'
)
")->fetchColumn() ?: '...';
}
function getStatusLabel($status) {
$labels = [
'open' => 'Открыт',
'in_progress' => 'В работе',
'awaiting_response' => 'Ожидает ответа',
'closed' => 'Закрыт'
];
return $labels[$status] ?? $status;
}
function getPriorityLabel($priority) {
$labels = [
'low' => 'Низкий',
'medium' => 'Средний',
'high' => 'Высокий'
];
return $labels[$priority] ?? $priority;
}
?>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Панель управления - Система поддержки</title>
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="bg-animations">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
</div>
<div class="main-wrapper">
<nav class="navbar">
<div class="logo">SupportSystem</div>
<div class="user-info">
<span><?= htmlspecialchars($user['username']) ?> (<?= $user['role'] ?>)</span>
<a href="logout.php" class="logout-link">Выйти</a>
</div>
</nav>
<?php if ($user['role'] === 'curator'): ?>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value"><?= $stats['total'] ?></div>
<div class="stat-label">Всего тикетов</div>
</div>
<div class="stat-card">
<div class="stat-value"><?= $stats['active'] ?></div>
<div class="stat-label">Активных</div>
</div>
<div class="stat-card">
<div class="stat-value"><?= $stats['avg_response'] ?> ч</div>
<div class="stat-label">Ср. время ответа</div>
</div>
<div class="stat-card">
<a href="admin.php" style="text-decoration: none;">
<div class="stat-value">👥</div>
<div class="stat-label">Управление пользователями</div>
</a>
</div>
</div>
<?php endif; ?>
<div class="dashboard-header">
<h1>Тикеты</h1>
<?php if ($user['role'] === 'user'): ?>
<?php if ($openTicketsCount < 3): ?>
<a href="create_ticket.php" class="btn-primary" style="padding: 0.5rem 1rem; width: auto; text-decoration: none;">Создать тикет</a>
<?php else: ?>
<span class="text-secondary" style="font-size: 0.875rem;">Максимум 3 открытых тикета</span>
<?php endif; ?>
<?php endif; ?>
</div>
<?php if ($user['role'] !== 'user'): ?>
<form class="filters-area" style="background-color: var(--card-bg); padding: 1rem; border-radius: 0.75rem; border: 1px solid var(--border-color); margin-bottom: 1.5rem; display: flex; gap: 1rem; flex-wrap: wrap; align-items: flex-end;">
<div class="form-group" style="margin-bottom: 0; flex: 1; min-width: 200px;">
<label>Поиск</label>
<input type="text" name="search" value="<?= htmlspecialchars($searchQuery) ?>" placeholder="По теме или описанию...">
</div>
<div class="form-group" style="margin-bottom: 0;">
<label>Статус</label>
<select name="status">
<option value="">Все</option>
<option value="open" <?= $statusFilter === 'open' ? 'selected' : '' ?>>Открыт</option>
<option value="in_progress" <?= $statusFilter === 'in_progress' ? 'selected' : '' ?>>В работе</option>
<option value="awaiting_response" <?= $statusFilter === 'awaiting_response' ? 'selected' : '' ?>>Ожидает ответа</option>
<option value="closed" <?= $statusFilter === 'closed' ? 'selected' : '' ?>>Закрыт</option>
</select>
</div>
<div class="form-group" style="margin-bottom: 0;">
<label>Категория</label>
<select name="category">
<option value="">Все</option>
<option value="technical" <?= $categoryFilter === 'technical' ? 'selected' : '' ?>>Техническая</option>
<option value="question" <?= $categoryFilter === 'question' ? 'selected' : '' ?>>Вопрос</option>
<option value="complaint" <?= $categoryFilter === 'complaint' ? 'selected' : '' ?>>Жалоба</option>
<option value="other" <?= $categoryFilter === 'other' ? 'selected' : '' ?>>Другое</option>
</select>
</div>
<button type="submit" class="btn-primary" style="width: auto; height: 42px; padding: 0 1rem;">Найти</button>
<a href="index.php" style="color: var(--text-secondary); text-decoration: none; padding-bottom: 0.5rem;">Сбросить</a>
</form>
<?php endif; ?>
<div class="ticket-grid">
<?php if (empty($tickets)): ?>
<p class="text-secondary">Тикетов не найдено.</p>
<?php else: ?>
<?php foreach ($tickets as $ticket): ?>
<a href="ticket.php?id=<?= $ticket['id'] ?>" class="ticket-card">
<div class="ticket-badge badge-<?= $ticket['status'] ?>">
<?= getStatusLabel($ticket['status']) ?>
</div>
<h3><?= htmlspecialchars($ticket['title']) ?></h3>
<p><?= htmlspecialchars($ticket['description']) ?></p>
<div class="ticket-meta">
<span>Приоритет: <?= getPriorityLabel($ticket['priority']) ?></span>
<span><?= date('d.m.Y H:i', strtotime($ticket['created_at'])) ?></span>
</div>
<?php if (isset($ticket['creator_name'])): ?>
<div class="ticket-meta" style="margin-top: 0.5rem;">
<span>От: <?= htmlspecialchars($ticket['creator_name']) ?></span>
</div>
<?php endif; ?>
</a>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>