Heray-Was-Here
Server : LiteSpeed
System : Linux uk-fast-web1372.main-hosting.eu 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64
User : u390967363 ( 390967363)
PHP Version : 8.2.30
Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail
Directory :  /home/u390967363/domains/aibenproperties.com/public_html/app/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/u390967363/domains/aibenproperties.com/public_html/app/ticket-details.php
<?php
ob_start();
session_start();
require_once 'includes/db.php';
require_once 'includes/functions.php';

// Access Control
if (!isset($_SESSION['user_id'])) {
    header("Location: login.php");
    exit;
}

$user_id = $_SESSION['user_id'];
$user_role = $_SESSION['user_role'];
$ticket_id = $_GET['id'] ?? null;

if (!$ticket_id) {
    die("Invalid Ticket ID.");
}

// Fetch Ticket with Security Check
// If Client: Must match user_id
// If Staff: Must match company_id (if applicable)
$query = "SELECT t.*, u.name as client_name, u.email as client_email 
          FROM support_tickets t 
          LEFT JOIN users u ON t.user_id = u.id 
          WHERE t.id = ?";
$params = [$ticket_id];

if ($user_role === 'client') {
    $query .= " AND t.user_id = ?";
    $params[] = $user_id;
} else {
    // Staff check for company
    $companyId = getCurrentCompanyId();
    if ($companyId) {
        $query .= " AND t.company_id = ?";
        $params[] = $companyId;
    }
}

$stmt = $pdo->prepare($query);
$stmt->execute($params);
$ticket = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$ticket) {
    include 'includes/header.php';
    echo "<div class='container py-5'><div class='alert alert-danger'>Ticket not found or access denied.</div></div>";
    include 'includes/footer.php';
    exit;
}

$success_msg = '';
$error_msg = '';

// Handle New Reply
if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['reply_message']) || isset($_FILES['attachment']))) {
    $message = trim($_POST['reply_message'] ?? '');
    
    // Check if we have message OR attachment
    $hasAttachment = isset($_FILES['attachment']) && $_FILES['attachment']['error'] === UPLOAD_ERR_OK;
    
    if (!empty($message) || $hasAttachment) {
        try {
            $pdo->beginTransaction();
            
            // Handle Attachment
            $attachmentPath = null;
            if ($hasAttachment) {
                $attachmentPath = handleFileUpload('attachment', 'uploads/tickets/');
            }
            
            // Insert Reply into ticket_messages
            $stmt = $pdo->prepare("INSERT INTO ticket_messages (ticket_id, sender_id, message, attachment_path) VALUES (?, ?, ?, ?)");
            $stmt->execute([$ticket_id, $user_id, $message, $attachmentPath]);

            $newStatus = $ticket['status'];
            if ($ticket['status'] === 'closed' || $ticket['status'] === 'resolved') {
                $newStatus = 'open'; // Reopen on reply
            } elseif ($user_role !== 'client' && $ticket['status'] === 'open') {
                $newStatus = 'pending'; // Staff replied, waiting on client
            }
            
            $stmt = $pdo->prepare("UPDATE support_tickets SET updated_at = NOW(), status = ? WHERE id = ?");
            $stmt->execute([$newStatus, $ticket_id]);
            
            $pdo->commit();
            $success_msg = "Reply sent successfully.";
            // Refresh ticket data
            $ticket['status'] = $newStatus;

            // Notify the other party
            require_once 'includes/mailer.php';
            if ($ticket['user_id'] != $user_id) {
                // Staff replying to Client (or one user to another?)
                // Usually Staff replying to Client
                sendNotification($ticket['user_id'], 'Ticket Reply', "New reply on your ticket #$ticket_id: " . (strlen($message) > 50 ? substr($message, 0, 50) . '...' : $message), $pdo);
            }
            
        } catch (PDOException $e) {
            $pdo->rollBack();
            $error_msg = "Error sending reply: " . $e->getMessage();
        }
    }
}

// Handle Status Change (Staff Only or Client closing own ticket)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) {
    $new_status = $_POST['status'];
    // Clients can only close/resolve, not set to in_progress
    if ($user_role === 'client' && !in_array($new_status, ['resolved', 'closed'])) {
        $error_msg = "You can only mark tickets as Resolved or Closed.";
    } else {
        try {
            $stmt = $pdo->prepare("UPDATE support_tickets SET status = ?, updated_at = NOW() WHERE id = ?");
            $stmt->execute([$new_status, $ticket_id]);
            $success_msg = "Status updated to " . ucfirst($new_status);
            $ticket['status'] = $new_status;
        } catch (PDOException $e) {
            $error_msg = "Error updating status: " . $e->getMessage();
        }
    }
}

// Fetch Messages
$stmt = $pdo->prepare("SELECT m.*, u.name as sender_name, u.role as sender_role 
                       FROM ticket_messages m 
                       LEFT JOIN users u ON m.sender_id = u.id 
                       WHERE m.ticket_id = ? 
                       ORDER BY m.created_at ASC");
$stmt->execute([$ticket_id]);
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);

$canAssign = tableHasColumn('support_tickets', 'assignee_id');
$canDue = tableHasColumn('support_tickets', 'due_date');
$staffOptions = [];
if ($canAssign && $user_role !== 'client') {
    $cmp = getCurrentCompanyId();
    $roles = ['customer_rep','operations','operations_officer','agent','sales_agent','estate_manager','admin','super_admin'];
    $in = implode(",", array_fill(0, count($roles), "?"));
    if ($cmp) {
        $q = "SELECT id, name, role FROM users WHERE company_id = ? AND role IN ($in) ORDER BY name ASC";
        $params = array_merge([$cmp], $roles);
    } else {
        $q = "SELECT id, name, role FROM users WHERE role IN ($in) ORDER BY name ASC";
        $params = $roles;
    }
    $st = $pdo->prepare($q);
    $st->execute($params);
    $staffOptions = $st->fetchAll(PDO::FETCH_ASSOC);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_assignment']) && $canAssign && $user_role !== 'client') {
    $assignee_id = (int)($_POST['assignee_id'] ?? 0);
    if ($assignee_id > 0) {
        $stmt = $pdo->prepare("UPDATE support_tickets SET assignee_id = ?, updated_at = NOW() WHERE id = ?");
        $stmt->execute([$assignee_id, $ticket_id]);
        $success_msg = "Assignment updated.";
        $ticket['assignee_id'] = $assignee_id;
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_due_date']) && $canDue) {
    $due_date = $_POST['due_date'] ?? null;
    if ($due_date) {
        $stmt = $pdo->prepare("UPDATE support_tickets SET due_date = ?, updated_at = NOW() WHERE id = ?");
        $stmt->execute([$due_date, $ticket_id]);
        $success_msg = "Due date updated.";
        $ticket['due_date'] = $due_date;
    }
}

$back = strtolower(trim((string)($_GET['back'] ?? '')));
$backType = strtolower(trim((string)($_GET['type'] ?? '')));
$backUrl = '';
$backLabel = '';
if ($user_role === 'client') {
    $backUrl = 'client-support.php';
    $backLabel = 'Back to My Tickets';
} else {
    if ($back === 'support') {
        $backUrl = 'support.php' . ($backType === 'complaint' ? '?type=complaint' : '');
        $backLabel = ($backType === 'complaint') ? 'Back to Complaints' : 'Back to Support';
    } elseif ($back === 'hr') {
        $backUrl = 'hr-dashboard.php';
        $backLabel = 'Back to HR Dashboard';
    } else {
        $ref = (string)($_SERVER['HTTP_REFERER'] ?? '');
        $refPath = (string)(parse_url($ref, PHP_URL_PATH) ?? '');
        $refQs = (string)(parse_url($ref, PHP_URL_QUERY) ?? '');
        $refBase = $refPath !== '' ? basename($refPath) : '';
        $allowed = ['support.php','hr-dashboard.php','customer-care.php'];
        if (in_array($refBase, $allowed, true)) {
            $backUrl = $refBase . ($refQs !== '' ? ('?' . $refQs) : '');
            $backLabel = ($refBase === 'support.php') ? 'Back to Support' : (($refBase === 'hr-dashboard.php') ? 'Back to HR Dashboard' : 'Back to Customer Care');
        } elseif ((function_exists('isHRTier') && isHRTier($user_role)) || in_array(strtolower(str_replace([' ', '-'], '_', (string)$user_role)), ['hr','hr_manager'], true)) {
            $backUrl = 'hr-dashboard.php';
            $backLabel = 'Back to HR Dashboard';
        } else {
            $backUrl = 'support.php';
            $backLabel = 'Back to Support';
        }
    }
}

include 'includes/header.php';
?>

<div class="container-fluid px-4 py-4">
    <div class="mb-3">
        <a href="<?= htmlspecialchars($backUrl) ?>" class="text-decoration-none text-muted"><i class="fa-solid fa-arrow-left me-1"></i> <?= htmlspecialchars($backLabel) ?></a>
    </div>

    <div class="d-flex justify-content-between align-items-start mb-4">
        <div>
            <h2 class="mb-1">Ticket #<?= $ticket['id'] ?>: <?= htmlspecialchars($ticket['subject']) ?></h2>
            <div class="d-flex align-items-center gap-3 text-muted small">
                <span><i class="fa-regular fa-clock me-1"></i> <?= date('M d, Y H:i', strtotime($ticket['created_at'])) ?></span>
                <span><i class="fa-regular fa-user me-1"></i> <?= htmlspecialchars($ticket['client_name']) ?></span>
            </div>
        </div>
        <div class="d-flex align-items-center gap-2">
            <?php 
            $statusClass = match($ticket['status']) {
                'open' => 'bg-success',
                'pending' => 'bg-warning text-dark',
                'resolved' => 'bg-info text-dark',
                'closed' => 'bg-secondary',
                default => 'bg-secondary'
            };
            ?>
            <span class="badge <?= $statusClass ?> fs-6"><?= ucfirst($ticket['status']) ?></span>
            
            <?php if ($user_role !== 'client'): ?>
                <div class="dropdown">
                    <button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
                        Update Status
                    </button>
                    <ul class="dropdown-menu">
                        <li><button class="dropdown-item" type="submit" form="statusForm" name="status" value="open">Open</button></li>
                        <li><button class="dropdown-item" type="submit" form="statusForm" name="status" value="pending">Pending</button></li>
                        <li><button class="dropdown-item" type="submit" form="statusForm" name="status" value="resolved">Resolved</button></li>
                        <li><button class="dropdown-item" type="submit" form="statusForm" name="status" value="closed">Closed</button></li>
                    </ul>
                    <form id="statusForm" method="POST">
                        <input type="hidden" name="update_status" value="1">
                    </form>
                </div>
            <?php elseif ($ticket['status'] !== 'closed' && $ticket['status'] !== 'resolved'): ?>
                 <form method="POST" class="d-inline">
                    <input type="hidden" name="update_status" value="1">
                    <button type="submit" name="status" value="resolved" class="btn btn-outline-success btn-sm">Mark Resolved</button>
                </form>
            <?php endif; ?>
        </div>
    </div>

    <?php if ($success_msg): ?>
        <div class="alert alert-success alert-dismissible fade show"><?= $success_msg ?> <button class="btn-close" data-bs-dismiss="alert"></button></div>
    <?php endif; ?>
    <?php if ($error_msg): ?>
        <div class="alert alert-danger alert-dismissible fade show"><?= $error_msg ?> <button class="btn-close" data-bs-dismiss="alert"></button></div>
    <?php endif; ?>

    <div class="row">
        <div class="col-lg-8">
            <!-- Messages Area -->
            <div class="card shadow-sm mb-4">
                <div class="card-body bg-light" style="max-height: 600px; overflow-y: auto;">
                    
                    <!-- Original Description (if not in messages) -->
                    <?php 
                    // Check if the first message in DB is same as ticket message to avoid duplication
                    // or just always show ticket message as the header
                    ?>
                    
                    <?php if (empty($messages)): ?>
                        <div class="d-flex mb-3">
                            <div class="flex-shrink-0">
                                <div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
                                    <?= strtoupper(substr($ticket['client_name'], 0, 1)) ?>
                                </div>
                            </div>
                            <div class="flex-grow-1 ms-3">
                                <div class="card border-0 shadow-sm">
                                    <div class="card-header bg-white border-0 d-flex justify-content-between">
                                        <strong class="text-primary"><?= htmlspecialchars($ticket['client_name']) ?></strong>
                                        <small class="text-muted"><?= date('M d, Y H:i', strtotime($ticket['created_at'])) ?></small>
                                    </div>
                                    <div class="card-body py-2">
                                        <p class="mb-0"><?= nl2br(htmlspecialchars($ticket['message'])) ?></p>
                                    </div>
                                </div>
                            </div>
                        </div>
                    <?php endif; ?>

                    <?php foreach ($messages as $msg): ?>
                        <?php 
                        $isMe = $msg['sender_id'] == $user_id;
                        $roleBadge = match($msg['sender_role']) {
                            'client' => 'badge bg-light text-dark border',
                            'admin', 'super_admin' => 'badge bg-danger',
                            default => 'badge bg-info text-dark'
                        };
                        ?>
                        <div class="d-flex mb-3 <?= $isMe ? 'flex-row-reverse' : '' ?>">
                            <div class="flex-shrink-0">
                                <div class="rounded-circle <?= $isMe ? 'bg-success' : 'bg-secondary' ?> text-white d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
                                    <?= strtoupper(substr($msg['sender_name'] ?? 'U', 0, 1)) ?>
                                </div>
                            </div>
                            <div class="flex-grow-1 mx-3" style="max-width: 80%;">
                                <div class="card border-0 shadow-sm <?= $isMe ? 'bg-navy-light' : '' ?>">
                                    <div class="card-header bg-white border-0 d-flex justify-content-between align-items-center">
                                        <div>
                                            <strong class="<?= $isMe ? 'text-success' : 'text-dark' ?>">
                                                <?= $isMe ? 'You' : htmlspecialchars($msg['sender_name']) ?>
                                            </strong>
                                            <span class="<?= $roleBadge ?> ms-2 small" style="font-size: 0.7em;"><?= ucfirst($msg['sender_role']) ?></span>
                                        </div>
                                        <small class="text-muted ms-3"><?= date('M d, H:i', strtotime($msg['created_at'])) ?></small>
                                    </div>
                                    <div class="card-body py-2">
                                        <p class="mb-0"><?= nl2br(htmlspecialchars($msg['message'])) ?></p>
                                        <?php if (!empty($msg['attachment_path'])): ?>
                                            <div class="mt-2 border-top pt-2">
                                                <a href="<?= htmlspecialchars($msg['attachment_path']) ?>" target="_blank" class="text-decoration-none small text-primary">
                                                    <i class="fa-solid fa-paperclip me-1"></i>View Attachment
                                                </a>
                                            </div>
                                        <?php endif; ?>
                                    </div>
                                </div>
                            </div>
                        </div>
                    <?php endforeach; ?>

                </div>
                
                <!-- Reply Box -->
                <?php if ($ticket['status'] !== 'closed'): ?>
                <div class="card-footer bg-white">
                    <form method="POST" enctype="multipart/form-data">
                        <div class="mb-3">
                            <label class="form-label visually-hidden">Reply</label>
                            <textarea name="reply_message" class="form-control" rows="3" placeholder="Type your reply here..."></textarea>
                        </div>
                        <div class="d-flex justify-content-between align-items-center">
                            <div>
                                <label class="btn btn-sm btn-light border text-muted" for="replyAttachment">
                                    <i class="fa-solid fa-paperclip me-1"></i>Attach File
                                </label>
                                <input type="file" name="attachment" id="replyAttachment" class="d-none" onchange="document.getElementById('fileName').textContent = this.files[0].name">
                                <span id="fileName" class="small text-muted ms-2"></span>
                            </div>
                            <button type="submit" class="btn btn-primary">
                                <i class="fa-solid fa-paper-plane me-2"></i>Send Reply
                            </button>
                        </div>
                    </form>
                </div>
                <?php else: ?>
                    <div class="card-footer bg-light text-center text-muted">
                        This ticket is closed. Please create a new ticket for further assistance.
                    </div>
                <?php endif; ?>
            </div>
        </div>
        
        <div class="col-lg-4">
            <!-- Sidebar Info -->
            <div class="card shadow-sm mb-4">
                <div class="card-header bg-white fw-bold">Ticket Info</div>
                <div class="card-body">
                    <div class="mb-3">
                        <label class="small text-muted d-block">Priority</label>
                        <span class="badge bg-light text-dark border"><?= ucfirst($ticket['priority']) ?></span>
                    </div>
                    <?php if ($canAssign && $user_role !== 'client'): ?>
                    <div class="mb-3">
                        <label class="small text-muted d-block">Assignee</label>
                        <form method="POST" class="d-flex gap-2">
                            <input type="hidden" name="update_assignment" value="1">
                            <select name="assignee_id" class="form-select form-select-sm" style="max-width: 240px;">
                                <option value="0">Unassigned</option>
                                <?php foreach ($staffOptions as $opt): ?>
                                    <option value="<?= $opt['id'] ?>" <?= isset($ticket['assignee_id']) && (int)$ticket['assignee_id'] === (int)$opt['id'] ? 'selected' : '' ?>>
                                        <?= htmlspecialchars($opt['name']) ?> (<?= htmlspecialchars($opt['role']) ?>)
                                    </option>
                                <?php endforeach; ?>
                            </select>
                            <button class="btn btn-sm btn-outline-primary">Save</button>
                        </form>
                    </div>
                    <?php endif; ?>
                    <?php if ($canDue): ?>
                    <div class="mb-3">
                        <label class="small text-muted d-block">Due Date</label>
                        <form method="POST" class="d-flex gap-2">
                            <input type="hidden" name="update_due_date" value="1">
                            <input type="date" name="due_date" class="form-control form-control-sm" style="max-width: 180px;" value="<?= htmlspecialchars($ticket['due_date'] ?? '') ?>">
                            <button class="btn btn-sm btn-outline-primary">Save</button>
                        </form>
                    </div>
                    <?php endif; ?>
                    <div class="mb-3">
                        <label class="small text-muted d-block">Department</label>
                        <span>General Support</span>
                    </div>
                    <?php if ($user_role !== 'client'): ?>
                    <div class="mb-3">
                        <label class="small text-muted d-block">Client Email</label>
                        <a href="mailto:<?= $ticket['client_email'] ?>"><?= $ticket['client_email'] ?></a>
                    </div>
                    <?php endif; ?>
                </div>
            </div>
        </div>
    </div>
</div>

<?php include 'includes/footer.php'; ?>

Hry