JIT
create a ticket menu layout based on user menu design
This is the code of my user menu: <?php session_start(); date_default_timezone_set('Asia/Manila'); global $wpdb; // --- Configuration --- $user_table_name = 'users'; $message = ''; $message_type = ''; // Handle success messages from redirect if (isset($_GET['message'])) { if ($_GET['message'] === 'updated') { $message = 'User updated successfully!'; $message_type = 'success'; } elseif ($_GET['message'] === 'added') { $message = 'User added successfully!'; $message_type = 'success'; } } // --- Handle user session --- if (isset($_SESSION['username'])) { $username = $_SESSION['username']; $wpdb->update( $user_table_name, ['last_logged_in' => current_time('mysql')], ['username' => $username] ); } // --- Handle delete user action --- if (isset($_GET['action']) && $_GET['action'] === 'delete_user' && isset($_GET['id']) && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'delete_user_' . absint($_GET['id']))) { $user_id_to_delete = absint($_GET['id']); if ($user_id_to_delete) { $deleted = $wpdb->delete( $user_table_name, ['id' => $user_id_to_delete], ['%d'] ); if ($deleted) { $message = 'User deleted successfully!'; $message_type = 'success'; } else { $message = 'Error deleting user.'; $message_type = 'error'; } } } // --- Handle edit user action (prepare form) --- $editing_user = null; if (isset($_GET['action']) && $_GET['action'] === 'edit_user' && isset($_GET['id'])) { $user_id_to_edit = absint($_GET['id']); if ($user_id_to_edit) { $editing_user = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $user_table_name WHERE id = %d", $user_id_to_edit), ARRAY_A ); if (!$editing_user) { $message = 'User not found for editing.'; $message_type = 'error'; } } } // --- Handle add/update user form submission --- if (isset($_POST['add_user']) || isset($_POST['edit_user'])) { $first_name = trim($_POST['first_name']); $last_name = trim($_POST['last_name']); $username = trim($_POST['username']); $password = $_POST['password']; $confirm_password = $_POST['confirm_password']; $role = $_POST['role']; $department_id = !empty($_POST['department_id']) ? $_POST['department_id'] : NULL; // Validate names if (!preg_match('/^[a-zA-Z .]+$/', $first_name)) { $message = 'First name can only contain letters, spaces, and periods.'; $message_type = 'error'; } elseif (!preg_match('/^[a-zA-Z .]+$/', $last_name)) { $message = 'Last name can only contain letters, spaces, and periods.'; $message_type = 'error'; } elseif (empty($username)) { $message = 'Username is required.'; $message_type = 'error'; } elseif (isset($_POST['add_user']) && empty($password)) { $message = 'Password is required.'; $message_type = 'error'; } elseif (!empty($password) && $password !== $confirm_password) { $message = 'Passwords do not match.'; $message_type = 'error'; } else { $user_data = [ 'first_name' => $first_name, 'last_name' => $last_name, 'username' => $username, 'role' => $role, 'department_id' => $department_id ]; if (!empty($password)) { $user_data['password'] = password_hash($password, PASSWORD_DEFAULT); } if (isset($_POST['edit_user'])) { $user_id = absint($_POST['user_id']); $updated = $wpdb->update( $user_table_name, $user_data, ['id' => $user_id], ['%s', '%s', '%s', '%s', '%d'], ['%d'] ); if ($updated !== false) { wp_redirect(add_query_arg(['message' => 'updated'], remove_query_arg(['action', 'id']))); exit; } else { $message = 'Error updating user: ' . $wpdb->last_error; $message_type = 'error'; } } else { $user_data['created_at'] = current_time('mysql'); $inserted = $wpdb->insert( $user_table_name, $user_data ); if ($inserted) { wp_redirect(add_query_arg(['message' => 'added'], $_SERVER['REQUEST_URI'])); exit; } else { $message = 'Error adding user: ' . $wpdb->last_error; $message_type = 'error'; } } } } // Fetch all users with department names $users = $wpdb->get_results(" SELECT u.*, d.name as department_name FROM $user_table_name u LEFT JOIN departments d ON u.department_id = d.id ", ARRAY_A); // Fetch all departments for dropdown $departments = $wpdb->get_results("SELECT * FROM departments", ARRAY_A); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>User Management</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f7f9; color: #333; } .dashboard-container { display: flex; } .sidebar { width: 240px; background-color: #c1d8f0; color: #000; height: 100vh; position: fixed; left: 0; top: 0; overflow-y: auto; box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1); z-index: 1000; } .sidebar-header { padding: 20px; text-align: center; } .sidebar-header .inventory-name { font-size: 17px; font-weight: bold; color: #000; } .sidebar-menu { padding: 0; } .sidebar-menu ul { list-style: none; margin: 0; padding: 0; } .sidebar-menu li a { display: flex; align-items: center; padding: 12px 20px; text-decoration: none; color: #000; transition: 0.3s; font-size: 16px; } .sidebar-menu li a i { margin-right: 12px; width: 20px; text-align: center; } .sidebar-menu li a:hover { background-color: #ffffff; color: #000; } .main-content { margin-left: 240px; padding: 25px; flex-grow: 1; } .header { position: fixed; top: 0; left: 240px; right: 0; display: flex; justify-content: space-between; align-items: center; background-color: #4663ac; padding: 10px 30px; height: 60px; /* Fixed height */ z-index: 999; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } h1 { margin-top: 0; padding-top: 0; } .header-left .date-time { font-size: 15px; /* Slightly smaller */ color: #fff; /* Darker color */ font-weight: 500; /* Slightly bolder */ } .header-right { display: flex; align-items: center; /* Removed gap here, gap is now on .user-info */ font-size: 16px; /* Slightly smaller */ color: #ffffff; } /* New style for user info container */ .header-right .user-info { display: flex; align-items: center; /* Center items horizontally */ gap: 1px; /* Small gap between icon and text */ } .user-dropdown { position: relative; display: inline-block; cursor: pointer; } .user-dropdown-content { display: none; position: absolute; right: 0; background-color: #D1B48C; min-width: 100px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; border-radius: 4px; } .user-dropdown-header { padding: 8px 12px; background-color: ; #D1B48C border-bottom: 1px solid #e9ecef; display: flex; align-items: center; gap: 8px; } .user-dropdown-header i { font-size: 20px; color: #000000; } .user-dropdown-content.user-info { display: flex; align-items: right; gap: 1px; color: #000000; } .user-dropdown-content a { display: flex; padding: 8px 15px; align-items: center; color: #000000; text-decoration: none; font-size: 16px; transition: all 0.2s; } .user-dropdown-content a i { font-size: 16px; /* Adjust logout icon size separately */ margin-right: 8px; /* Space between icon and text */ } .user-dropdown-content a:hover { text-decoration: underline; color: #000000; } .user-dropdown:hover .user-dropdown-content { display: block; } .user-dropdown-content.user-info i { font-size: 16px; align-items: center; } .header-right i { color: #ffffff; /* Icon color */ font-size:40px; /* Larger icon */ /* Remove margin-right when stacked */ } .header-right span { font-size: 15px; /* Smaller font for username */ color: #ffffff; } .main-content { margin-left: 240px; padding: 80px 20px 20px 20px; flex-grow: 1; } .user-management { display: flex; flex-wrap: wrap; /* Enables wrapping on smaller screens */ justify-content: space-between; gap: 20px; /* Adds gap between form and table */ } .form-container, .table-container { background-color: #fff; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); padding: 15px; margin: 10px; width: 48%; /* Set width for each column */ } h3 { margin: 0 0 15px 0; color: #2f4050; font-size: 1.5em; } input[type="text"], input[type="password"], input[type="email"], select { width: calc(100% - 22px); padding: 10px; margin-bottom: 15px; /* Space between inputs */ border: 1px solid #ddd; border-radius: 4px; } button { padding: 10px 15px; border: none; background-color: #D1B48C; color: white; border-radius: 4px; cursor: pointer; margin-top: 10px; /** Space above button */ } .table-container{ flex: 1;} table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 10px; border: 1px solid #ddd; text-align: left; } th { background-color: #f9f9f9; } tr:hover { background-color: #f5f5f5; } .notice-container { width: 100%; margin-bottom: 20px; background-color: #f9f9f9; } .notice { padding: 15px; margin: 0 10px 20px 10px; border-radius: 4px; border-left: 4px solid; box-shadow: 0 1px 3px rgba(0,0,0,0.1); display: flex; align-items: center; } .notice p { margin: 0; padding: 0; font-size: 16px; } .notice-success { background-color: #f0fff4; border-color: #38a169; color: #2f855a; } .notice-error { background-color: #fff5f5; border-color: #e53e3e; color: #c53030; } .notice i { margin-right: 10px; font-size: 18px; } .notice-success i { color: #38a169; } .notice-error i { color: #e53e3e; } </style> </head> <body> <div class="dashboard-container"> <aside class="sidebar"> <div class="sidebar-header"> <div class="inventory-name">RJL DeskTrack</div> </div> <div class="sidebar-menu"> <ul> <li><a href="http://localhost/helpdesk/?page_id=57"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li> <li><a href="http://localhost/helpdesk/?page_id=62" class="active"><i class="fas fa-users-cog"></i> Users</a></li> <li><a href="http://localhost/helpdesk/?page_id=66"><i class="fas fa-building"></i> Departments</a></li> <li><a href="http://localhost/helpdesk/?page_id=70"><i class="fas fa-ticket-alt"></i> Tickets</a></li> <li><a href="messages.php"><i class="fas fa-envelope"></i> Messages</a></li> <li><a href="reports.php"><i class="fas fa-chart-bar"></i> Reports</a></li> </ul> </div> </aside> <main class="main-content"> <header class="header"> <div class="header-left"> <span class="date-time" id="current-date-time"></span> </div> <div class="header-right"> <div class="user-dropdown"> <div class="user-info"> <span id="current-username-header"> <?= htmlspecialchars($_SESSION['username']) ?> <i class="fas fa-user-circle"></i> </span> </div> <div class="user-dropdown-content"> <div class="user-dropdown-header"> <i class="fas fa-user-circle" style="color:#000000;"></i> <span style="color:#000000;"><?= htmlspecialchars($_SESSION['username']) ?></span> </div> <a href="#" onclick="return confirm('Are you sure you want to log out?');"> <i class="fas fa-sign-out-alt" style="font-size: 16px; color:#000000;"></i>Logout </a> </div> </div> </div> </header> <h1>User Management</h1> <div class="user-management"> <div class="notice-container"> <?php if ($message): ?> <div class="notice notice-<?php echo esc_attr($message_type); ?>"> <p><?php echo esc_html($message); ?></p> </div> <?php endif; ?> </div> <div class="form-container" style="max-width: 400px;"> <h2><?php echo $editing_user ? 'Edit User' : 'Add New User'; ?></h2> <form action="" method="post"> <input type="hidden" name="user_id" value="<?php echo esc_attr($editing_user['id'] ?? ''); ?>"> <input type="text" name="first_name" placeholder="First Name" value="<?php echo esc_attr($editing_user['first_name'] ?? ''); ?>" required> <input type="text" name="last_name" placeholder="Last Name" value="<?php echo esc_attr($editing_user['last_name'] ?? ''); ?>" required> <input type="text" name="username" placeholder="Username" value="<?php echo esc_attr($editing_user['username'] ?? ''); ?>" required> <input type="password" name="password" placeholder="Password (leave blank to keep current)"> <input type="password" name="confirm_password" placeholder="Confirm Password"> <select name="role" required> <option value="admin" <?php echo isset($editing_user['role']) && $editing_user['role'] === 'admin' ? 'selected' : ''; ?>>Admin</option> <option value="staff" <?php echo isset($editing_user['role']) && $editing_user['role'] === 'staff' ? 'selected' : ''; ?>>Staff Member</option> <option value="user" <?php echo (!isset($editing_user['role']) || $editing_user['role'] === 'user') ? 'selected' : ''; ?>>User</option> </select> </select> <select name="department_id"> <option value="">No Department</option> <?php foreach ($departments as $dept): ?> <option value="<?php echo esc_attr($dept['id']); ?>" <?php echo isset($editing_user['department_id']) && $editing_user['department_id'] == $dept['id'] ? 'selected' : ''; ?>> <?php echo esc_html($dept['name']); ?> </option> <?php endforeach; ?> </select> <button type="submit" name="<?php echo $editing_user ? 'edit_user' : 'add_user'; ?>"> <?php echo $editing_user ? 'Update User' : 'Add User'; ?> </button> </form> </div> <div class="table-container"> <h3>All Users</h3> <table> <thead> <tr> <th>ID</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> <th>Role</th> <th>Department</th> <th>Created At</th> <th>Last Login</th> <th>Action</th> </tr> </thead> <tbody> <?php foreach ($users as $user): ?> <tr> <td><?php echo $user['id']; ?></td> <td><?php echo esc_html($user['first_name']); ?></td> <td><?php echo esc_html($user['last_name']); ?></td> <td><?php echo esc_html($user['username']); ?></td> <td><?php echo ucfirst($user['role']); ?></td> <td><?php echo $user['department_name'] ?? 'None'; ?></td> <td> <?php if (!empty($user['created_at'])) { try { $date = new DateTime($user['created_at'], new DateTimeZone('UTC')); $date->setTimezone(new DateTimeZone('Asia/Manila')); echo esc_html($date->format('Y-m-d h:i A')); } catch (Exception $e) { echo esc_html($user['created_at']); } } else { echo 'N/A'; } ?> </td> <td> <?php if (!empty($user['last_logged_in'])) { try { $date = new DateTime($user['last_logged_in'], new DateTimeZone('UTC')); $date->setTimezone(new DateTimeZone('Asia/Manila')); echo esc_html($date->format('Y-m-d h:i A')); } catch (Exception $e) { echo esc_html(date('Y-m-d h:i A', strtotime($user['last_logged_in']))); } } else { echo 'Never'; } ?> </td> <td> <a href="<?php echo add_query_arg(['action' => 'edit_user', 'id' => $user['id']]); ?>" class="edit">Edit</a> <a href="<?php echo add_query_arg(['action' => 'delete_user', 'id' => $user['id'], '_wpnonce' => wp_create_nonce('delete_user_' . $user['id'])]); ?>" class="delete" onclick="return confirm('Are you sure you want to delete this user?');">Delete</a> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> </div> </main> </div> <script> document.addEventListener('DOMContentLoaded', function() { const nameInputs = document.querySelectorAll('input[name="first_name"], input[name="last_name"]'); nameInputs.forEach(input => { input.addEventListener('input', function() { this.value = this.value.replace(/[^a-zA-Z .]/g, ''); }); input.addEventListener('blur', function() { this.value = this.value.replace(/\s+/g, ' ').trim(); }); }); }); </script> <script> function updateDateTime() { const now = new Date(); const options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit' }; document.getElementById("current-date-time").textContent = now.toLocaleDateString('en-US', options); } setInterval(updateDateTime, 1000); updateDateTime(); </script> </body> </html> and this is the code for my ticket menu: <?php // Start session for custom authentication session_start(); // Database connection $host = 'localhost'; $dbname = 'helpdesk'; $username = 'root'; $password = ''; try { $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Database connection failed: " . $e->getMessage()); } // Custom security check if (empty($_SESSION['user_id'])) { header("Location: http://localhost/helpdesk/?page_id=50"); exit; } // Get current user data $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $current_user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$current_user) { session_destroy(); header("Location: http://localhost/helpdesk/?page_id=50"); exit; } // Base URL for ticket system $base_url = 'http://localhost/helpdesk/?page_id=70'; // Check if viewing/editing ticket $viewing_ticket = isset($_GET['ticket_id']); $editing_ticket = $viewing_ticket && isset($_GET['action']) && $_GET['action'] === 'edit'; $ticket_id = $viewing_ticket ? (int)$_GET['ticket_id'] : 0; // Handle form submissions $message = ''; $message_type = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['create_ticket'])) { $subject = htmlspecialchars($_POST['subject']); $description = htmlspecialchars($_POST['description']); $priority = htmlspecialchars($_POST['priority']); $department_id = (int)$_POST['department_id']; try { // Start transaction $pdo->beginTransaction(); $ticket_number = 'TKT-' . date('Ymd-His'); $stmt = $pdo->prepare("INSERT INTO tickets (ticket_number, subject, description, priority, department_id, created_by, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, 'open', NOW(), NOW())"); $stmt->execute([ $ticket_number, $subject, $description, $priority, $department_id, $current_user['id'] ]); $ticket_id = $pdo->lastInsertId(); // For initial message, set recipient to admin (or any default user) // Here we'll get the first admin user as recipient $stmt = $pdo->prepare("SELECT id FROM users WHERE role = 'admin' LIMIT 1"); $stmt->execute(); $admin = $stmt->fetch(); $recipient_id = $admin['id'] ?? $current_user['id']; // Fallback to current user if no admin found // Add initial message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $recipient_id, $description ]); // Commit transaction $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error creating ticket: ' . $e->getMessage(); $message_type = 'error'; } } elseif (isset($_POST['update_status'])) { $ticket_id = (int)$_POST['ticket_id']; $status = htmlspecialchars($_POST['status']); try { $pdo->beginTransaction(); $stmt = $pdo->prepare("UPDATE tickets SET status = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$status, $ticket_id]); // Get the assigned staff for this ticket to set as recipient $stmt = $pdo->prepare("SELECT assigned_to FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id]); $ticket = $stmt->fetch(); $recipient_id = $ticket['assigned_to'] ?? $current_user['id']; // Fallback to current user if not assigned // Add status change message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $recipient_id, "Status changed to: " . ucfirst($status) ]); $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error updating ticket status: ' . $e->getMessage(); $message_type = 'error'; } } elseif (isset($_POST['assign_ticket'])) { $ticket_id = (int)$_POST['ticket_id']; $assign_to = (int)$_POST['assign_to']; try { $pdo->beginTransaction(); $stmt = $pdo->prepare("UPDATE tickets SET assigned_to = ?, status = 'assigned', updated_at = NOW() WHERE id = ?"); $stmt->execute([$assign_to, $ticket_id]); // Add assignment message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $assign_to, // Recipient is the assigned staff "Ticket assigned to support for resolution." ]); $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error assigning ticket: ' . $e->getMessage(); $message_type = 'error'; } } elseif (isset($_POST['add_message'])) { $ticket_id = (int)$_POST['ticket_id']; $message_text = htmlspecialchars($_POST['message']); try { $pdo->beginTransaction(); // Get the assigned staff for this ticket to set as recipient $stmt = $pdo->prepare("SELECT assigned_to FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id]); $ticket = $stmt->fetch(); $recipient_id = $ticket['assigned_to'] ?? $current_user['id']; // Fallback to current user if not assigned // Add message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $recipient_id, $message_text ]); // Update ticket's updated_at $stmt = $pdo->prepare("UPDATE tickets SET updated_at = NOW() WHERE id = ?"); $stmt->execute([$ticket_id]); $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error adding message: ' . $e->getMessage(); $message_type = 'error'; } } } // Handle ticket deletion (GET request) if (isset($_GET['delete_ticket'])) { $ticket_id_to_delete = (int)$_GET['delete_ticket']; try { // Verify user has permission to delete $stmt = $pdo->prepare("SELECT created_by FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id_to_delete]); $ticket = $stmt->fetch(); $is_admin = in_array($current_user['role'], ['admin', 'staff']); $is_creator = ($ticket['created_by'] ?? null) == $current_user['id']; if (!$ticket || (!$is_creator && !$is_admin)) { $message = 'You do not have permission to delete this ticket'; $message_type = 'error'; } else { $pdo->beginTransaction(); // First delete messages $stmt = $pdo->prepare("DELETE FROM messages WHERE ticket_id = ?"); $stmt->execute([$ticket_id_to_delete]); // Then delete the ticket $stmt = $pdo->prepare("DELETE FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id_to_delete]); $pdo->commit(); // Redirect to prevent refresh from deleting again header("Location: $base_url&deleted=1"); exit; } } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error deleting ticket: ' . $e->getMessage(); $message_type = 'error'; } } // Handle deletion success message from redirect if (isset($_GET['deleted'])) { $message = 'Ticket deleted successfully!'; $message_type = 'success'; } // Get ticket details if viewing a ticket if ($viewing_ticket) { // Get ticket details $stmt = $pdo->prepare(" SELECT t.*, d.name as department_name, CONCAT(u.first_name, ' ', u.last_name) as creator_name, CONCAT(a.first_name, ' ', a.last_name) as assigned_name FROM tickets t LEFT JOIN departments d ON t.department_id = d.id LEFT JOIN users u ON t.created_by = u.id LEFT JOIN users a ON t.assigned_to = a.id WHERE t.id = ? "); $stmt->execute([$ticket_id]); $ticket = $stmt->fetch(PDO::FETCH_ASSOC); // Check if ticket exists and user has permission if (!$ticket) { die("Ticket not found"); } if ($current_user['role'] === 'user' && $ticket['created_by'] != $current_user['id']) { die("You don't have permission to view this ticket"); } // Get ticket messages with correct column names $stmt = $pdo->prepare(" SELECT m.*, CONCAT(s.first_name, ' ', s.last_name) as sender_name, s.role as sender_role, CONCAT(r.first_name, ' ', r.last_name) as recipient_name FROM messages m LEFT JOIN users s ON m.sender_id = s.id LEFT JOIN users r ON m.recipient_id = r.id WHERE m.ticket_id = ? ORDER BY m.created_at ASC "); $stmt->execute([$ticket_id]); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); } // Get all necessary data for ticket list if (!$viewing_ticket) { try { // Get tickets based on role if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff') { $tickets = $pdo->query(" SELECT t.*, d.name as department_name, CONCAT(u.first_name, ' ', u.last_name) as creator_name, CONCAT(a.first_name, ' ', a.last_name) as assigned_name FROM tickets t LEFT JOIN departments d ON t.department_id = d.id LEFT JOIN users u ON t.created_by = u.id LEFT JOIN users a ON t.assigned_to = a.id ORDER BY t.created_at DESC ")->fetchAll(PDO::FETCH_ASSOC); } else { $stmt = $pdo->prepare(" SELECT t.*, d.name as department_name, CONCAT(a.first_name, ' ', a.last_name) as assigned_name FROM tickets t LEFT JOIN departments d ON t.department_id = d.id LEFT JOIN users a ON t.assigned_to = a.id WHERE t.created_by = ? ORDER BY t.created_at DESC "); $stmt->execute([$current_user['id']]); $tickets = $stmt->fetchAll(PDO::FETCH_ASSOC); } // Get departments for dropdown $departments = $pdo->query("SELECT * FROM departments")->fetchAll(PDO::FETCH_ASSOC); // Get staff for assignment dropdown $staff_members = $pdo->query(" SELECT id, CONCAT(first_name, ' ', last_name) as name FROM users WHERE role IN ('staff', 'admin') ")->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { die("Error fetching data: " . $e->getMessage()); } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= $viewing_ticket ? 'Ticket Details' : 'Ticket System' ?></title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f7f9; color: #333; margin: 0; padding: 0; } .dashboard-container { display: flex; min-height: 100vh; } /* Sidebar Styles - Matching User Menu */ .sidebar { width: 240px; background-color: #c1d8f0; /* Changed to match user menu */ color: #000; height: 100vh; position: fixed; left: 0; top: 0; overflow-y: auto; box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1); z-index: 1000; } .sidebar-header { padding: 20px; text-align: center; border-bottom: 1px solid rgba(0,0,0,0.1); } .sidebar-header .inventory-name { font-size: 17px; font-weight: bold; color: #000; } .sidebar-menu { padding: 0; } .sidebar-menu ul { list-style: none; margin: 0; padding: 0; } .sidebar-menu li a { display: flex; align-items: center; padding: 12px 20px; text-decoration: none; color: #000; transition: 0.3s; font-size: 16px; } .sidebar-menu li a i { margin-right: 12px; width: 20px; text-align: center; } .sidebar-menu li a:hover { background-color: #ffffff; color: #000; } /* Main Content Styles */ .main-content { margin-left: 240px; padding: 80px 20px 20px 20px; flex-grow: 1; background-color: #f4f7f9; min-height: 100vh; } /* Header - Matching User Menu */ .header { position: fixed; top: 0; left: 240px; right: 0; display: flex; justify-content: space-between; align-items: center; background-color: #4663ac; /* Changed to match user menu */ padding: 10px 30px; height: 60px; z-index: 999; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .header h2 { margin: 0; font-size: 24px; color: white; } .header .user-info { display: flex; align-items: center; gap: 10px; color: white; } .header .user-info i { font-size: 20px; } /* Notice Messages */ .notice { padding: 15px; margin: 0 0 30px 0; border-radius: 4px; border-left: 4px solid; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .notice.success { background-color: #f0fff4; border-color: #38a169; color: #2f855a; } .notice.error { background-color: #fff5f5; border-color: #e53e3e; color: #c53030; } /* Ticket Management Layout */ .ticket-management { display: flex; flex-wrap: wrap; gap: 20px; } .form-container, .table-container { background-color: white; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); padding: 20px; } .form-container { width: 40%; } .table-container { flex: 1; } /* Forms */ .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 8px; font-weight: 600; } .form-group input[type="text"], .form-group textarea, .form-group select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; } .form-group textarea { min-height: 150px; resize: vertical; } /* Buttons - Matching User Menu */ button, .button { padding: 10px 15px; border: none; background-color: #D1B48C; /* Changed to match user menu */ color: white; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-block; } button:hover, .button:hover { background-color: #b89c74; /* Darker shade for hover */ } .button-primary { background-color: #4663ac; } .button-primary:hover { background-color: #3a528b; } /* Tables */ table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 10px; border: 1px solid #ddd; text-align: left; } th { background-color: #f9f9f9; font-weight: 600; } tr:hover { background-color: #f5f5f5; } /* Status Badges */ .status-badge { display: inline-block; padding: 5px 10px; border-radius: 15px; font-size: 13px; font-weight: bold; text-transform: uppercase; } .status-open { background-color: #e3f2fd; color: #1976d2; } .status-assigned { background-color: #fff8e1; color: #ff8f00; } .status-pending { background-color: #ffebee; color: #d32f2f; } .status-solved { background-color: #e8f5e9; color: #388e3c; } .status-closed { background-color: #f5f5f5; color: #616161; } /* Priority Indicators */ .priority-high { color: #d32f2f; font-weight: bold; } .priority-medium { color: #ffa000; } .priority-low { color: #388e3c; } /* Ticket Details View */ .ticket-details { background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); margin-bottom: 30px; } .ticket-header { border-bottom: 1px solid #eee; padding-bottom: 20px; margin-bottom: 20px; } .ticket-body { display: flex; gap: 30px; } .ticket-description { flex: 2; } .ticket-meta-details { flex: 1; background-color: #f9f9f9; padding: 20px; border-radius: 6px; } .meta-row { margin-bottom: 15px; } .meta-label { font-weight: 600; display: inline-block; width: 120px; } /* Messages */ .ticket-messages { background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .message { padding: 15px; border-bottom: 1px solid #eee; } .message-header { display: flex; justify-content: space-between; margin-bottom: 10px; } /* Responsive */ @media (max-width: 1024px) { .ticket-body { flex-direction: column; } .form-container { width: 100%; } } @media (max-width: 768px) { .sidebar { width: 100%; height: auto; position: relative; } .main-content { margin-left: 0; padding: 20px; } .header { position: relative; left: 0; } } </style> </head> <body> <div class="helpdesk-container"> <aside class="helpdesk-sidebar"> <div class="sidebar-header"> <h1 class="site-name">Helpdesk System</h1> </div> <nav class="helpdesk-menu"> <ul> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <li><a href="http://localhost/helpdesk/?page_id=57"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li> <li><a href="http://localhost/helpdesk/?page_id=62"><i class="fas fa-users-cog"></i> Users</a></li> <li><a href="http://localhost/helpdesk/?page_id=66"><i class="fas fa-building"></i> Departments</a></li> <?php endif; ?> <li><a href="http://localhost/helpdesk/?page_id=70"><i class="fas fa-ticket-alt"></i> Tickets</a></li> <li><a href="http://localhost/helpdesk/?page_id=74"><i class="fas fa-envelope"></i> Messages</a></li> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <li><a href="<?= home_url('/reports') ?>"><i class="fas fa-chart-bar"></i> Reports</a></li> <?php endif; ?> <li><a href="<?= home_url('/logout') ?>"><i class="fas fa-sign-out-alt"></i> Logout</a></li> </ul> </nav> </aside> <main class="main-content"> <header class="header"> <div class="header-left"> <h2><?= $viewing_ticket ? 'Ticket Details' : 'Ticket Management' ?></h2> </div> <div class="header-right"> <div class="user-info"> <span><?= htmlspecialchars($current_user['first_name'] . ' ' . $current_user['last_name']) ?></span> <i class="fas fa-user-circle"></i> </div> </div> </header> <?php if ($message): ?> <div class="notice notice-<?= $message_type ?>"> <p><?= $message ?></p> </div> <?php endif; ?> <?php if ($viewing_ticket): ?> <!-- Ticket Details View --> <div class="ticket-details"> <div class="ticket-info"> <div class="ticket-header"> <h3><?= htmlspecialchars($ticket['subject']) ?></h3> <div class="ticket-meta"> <span class="ticket-number"><?= htmlspecialchars($ticket['ticket_number']) ?></span> <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>"> <?= ucfirst($ticket['status']) ?> </span> <span class="priority-<?= htmlspecialchars($ticket['priority']) ?>"> <?= ucfirst($ticket['priority']) ?> priority </span> </div> </div> <div class="ticket-body"> <div class="ticket-description"> <h4>Description</h4> <p><?= nl2br(htmlspecialchars($ticket['description'])) ?></p> </div> <div class="ticket-meta-details"> <div class="meta-row"> <span class="meta-label">Created By:</span> <span class="meta-value"><?= htmlspecialchars($ticket['creator_name']) ?></span> </div> <div class="meta-row"> <span class="meta-label">Department:</span> <span class="meta-value"><?= htmlspecialchars($ticket['department_name'] ?? 'None') ?></span> </div> <div class="meta-row"> <span class="meta-label">Assigned To:</span> <span class="meta-value"><?= htmlspecialchars($ticket['assigned_name'] ?? 'Unassigned') ?></span> </div> <div class="meta-row"> <span class="meta-label">Created At:</span> <span class="meta-value"><?= date('M j, Y g:i A', strtotime($ticket['created_at'])) ?></span> </div> <div class="meta-row"> <span class="meta-label">Last Updated:</span> <span class="meta-value"><?= date('M j, Y g:i A', strtotime($ticket['updated_at'])) ?></span> </div> </div> </div> </div> </div> <div class="add-message"> <h4>Add Message</h4> <form method="POST"> <input type="hidden" name="ticket_id" value="<?= $ticket_id ?>"> <div class="form-group"> <textarea name="message" required placeholder="Type your message here..."></textarea> </div> <button type="submit" name="add_message" class="button-primary">Send Message</button> </form> </div> </div> </div> </div> </div> <?php else: ?> <!-- Ticket List View --> <div class="ticket-system"> <?php if ($current_user['role'] === 'user'): ?> <h3>Create New Ticket</h3> <form method="POST"> <div class="form-group"> <label>Subject</label> <input type="text" name="subject" required> </div> <div class="form-group"> <label>Description</label> <textarea name="description" required></textarea> </div> <div class="form-group"> <label>Priority</label> <select name="priority" required> <option value="low">Low</option> <option value="medium" selected>Medium</option> <option value="high">High</option> </select> </div> <div class="form-group"> <label>Department</label> <select name="department_id" required> <?php foreach ($departments as $dept): ?> <option value="<?= $dept['id'] ?>"><?= htmlspecialchars($dept['name']) ?></option> <?php endforeach; ?> </select> </div> <button type="submit" name="create_ticket" class="button-primary">Create Ticket</button> </form> </div> <?php endif; ?> <!-- Tickets List --> <div class="tickets-list"> <h3><?= ($current_user['role'] === 'admin' || $current_user['role'] === 'staff') ? 'All Tickets' : 'My Tickets' ?></h3> <?php if (empty($tickets)): ?> <p>No tickets found.</p> <?php else: ?> <table class="tickets-table"> <thead> <tr> <th>Ticket #</th> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <th>Created By</th> <?php endif; ?> <th>Subject</th> <th>Status</th> <th>Priority</th> <th>Department</th> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <th>Assigned To</th> <?php endif; ?> <th>Created At</th> <th>Actions</th> </tr> </thead> <tbody> <?php foreach ($tickets as $ticket): ?> <tr> <td><?= htmlspecialchars($ticket['ticket_number']) ?></td> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <td><?= htmlspecialchars($ticket['creator_name'] ?? 'N/A') ?></td> <?php endif; ?> <td><?= htmlspecialchars($ticket['subject']) ?></td> <td> <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>"> <?= ucfirst($ticket['status']) ?> </span> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <form method="POST" class="status-update-form"> <input type="hidden" name="ticket_id" value="<?= $ticket['id'] ?>"> <select name="status" onchange="this.form.submit()"> <option value="open" <?= $ticket['status'] === 'open' ? 'selected' : '' ?>>Open</option> <option value="assigned" <?= $ticket['status'] === 'assigned' ? 'selected' : '' ?>>Assigned</option> <option value="pending" <?= $ticket['status'] === 'pending' ? 'selected' : '' ?>>Pending</option> <option value="solved" <?= $ticket['status'] === 'solved' ? 'selected' : '' ?>>Solved</option> <option value="closed" <?= $ticket['status'] === 'closed' ? 'selected' : '' ?>>Closed</option> </select> <input type="hidden" name="update_status" value="1"> </form> <?php endif; ?> </td> <td class="priority-<?= htmlspecialchars($ticket['priority']) ?>"> <?= ucfirst($ticket['priority']) ?> </td> <td><?= htmlspecialchars($ticket['department_name'] ?? 'None') ?></td> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <td> <?php if ($ticket['assigned_to']): ?> <?= htmlspecialchars($ticket['assigned_name'] ?? 'N/A') ?> <?php else: ?> <form method="POST" class="assign-form"> <input type="hidden" name="ticket_id" value="<?= $ticket['id'] ?>"> <select name="assign_to" onchange="this.form.submit()"> <option value="">Assign to...</option> <?php foreach ($staff_members as $staff): ?> <option value="<?= $staff['id'] ?>"><?= htmlspecialchars($staff['name']) ?></option> <?php endforeach; ?> </select> <input type="hidden" name="assign_ticket" value="1"> </form> <?php endif; ?> </td> <?php endif; ?> <td><?= date('M j, Y', strtotime($ticket['created_at'])) ?></td> <td> <a href="<?= $base_url ?>&ticket_id=<?= $ticket['id'] ?>" class="button">View</a> <?php if ($ticket['created_by'] == $current_user['id'] || $current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <a href="<?= $base_url ?>&delete_ticket=<?= $ticket['id'] ?>" class="button" onclick="return confirm('Are you sure you want to delete this ticket?')"> Delete </a> <?php endif; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div> </div> <?php endif; ?> </main> </div> <script> document.addEventListener('DOMContentLoaded', function() { // AJAX form submissions document.querySelectorAll('.status-update-form select, .assign-form select').forEach(select => { select.addEventListener('change', function() { const form = this.closest('form'); fetch('', { method: 'POST', body: new FormData(form) }) .then(response => { if (response.ok) { window.location.reload(); } else { alert('Error updating ticket'); } }) .catch(error => { console.error('Error:', error); alert('Error updating ticket'); }); }); }); }); </script> </body> </html> Use the layout of sidebar, header, the form and table for the list from the user and used it to layout and style my ticket menu
Updated files
v1
add this one: in viewing the tickets details, the layout must be look like this: Subject (bold): for example: air condition Ticket #: hfhk Status: Assigned Priority: Medium And so on... The label and its content must be just in one line and all the label must be in bold. Also add a "Back to Tickets" link, that would redirect to the ticket mangemnt <?php // Start session for custom authentication session_start(); // Database connection $host = 'localhost'; $dbname = 'helpdesk'; $username = 'root'; $password = ''; try { $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Database connection failed: " . $e->getMessage()); } // Custom security check if (empty($_SESSION['user_id'])) { header("Location: http://localhost/helpdesk/?page_id=50"); exit; } // Get current user data $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $current_user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$current_user) { session_destroy(); header("Location: http://localhost/helpdesk/?page_id=50"); exit; } // Base URL for ticket system $base_url = 'http://localhost/helpdesk/?page_id=70'; // Check if viewing/editing ticket $viewing_ticket = isset($_GET['ticket_id']); $editing_ticket = $viewing_ticket && isset($_GET['action']) && $_GET['action'] === 'edit'; $ticket_id = $viewing_ticket ? (int)$_GET['ticket_id'] : 0; // Handle form submissions $message = ''; $message_type = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['create_ticket'])) { $subject = htmlspecialchars($_POST['subject']); $description = htmlspecialchars($_POST['description']); $priority = htmlspecialchars($_POST['priority']); $department_id = (int)$_POST['department_id']; try { // Start transaction $pdo->beginTransaction(); $ticket_number = 'TKT-' . date('Ymd-His'); $stmt = $pdo->prepare("INSERT INTO tickets (ticket_number, subject, description, priority, department_id, created_by, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, 'open', NOW(), NOW())"); $stmt->execute([ $ticket_number, $subject, $description, $priority, $department_id, $current_user['id'] ]); $ticket_id = $pdo->lastInsertId(); // For initial message, set recipient to admin (or any default user) // Here we'll get the first admin user as recipient $stmt = $pdo->prepare("SELECT id FROM users WHERE role = 'admin' LIMIT 1"); $stmt->execute(); $admin = $stmt->fetch(); $recipient_id = $admin['id'] ?? $current_user['id']; // Fallback to current user if no admin found // Add initial message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $recipient_id, $description ]); // Commit transaction $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error creating ticket: ' . $e->getMessage(); $message_type = 'error'; } } elseif (isset($_POST['update_status'])) { $ticket_id = (int)$_POST['ticket_id']; $status = htmlspecialchars($_POST['status']); try { $pdo->beginTransaction(); $stmt = $pdo->prepare("UPDATE tickets SET status = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$status, $ticket_id]); // Get the assigned staff for this ticket to set as recipient $stmt = $pdo->prepare("SELECT assigned_to FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id]); $ticket = $stmt->fetch(); $recipient_id = $ticket['assigned_to'] ?? $current_user['id']; // Fallback to current user if not assigned // Add status change message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $recipient_id, "Status changed to: " . ucfirst($status) ]); $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error updating ticket status: ' . $e->getMessage(); $message_type = 'error'; } } elseif (isset($_POST['assign_ticket'])) { $ticket_id = (int)$_POST['ticket_id']; $assign_to = (int)$_POST['assign_to']; try { $pdo->beginTransaction(); $stmt = $pdo->prepare("UPDATE tickets SET assigned_to = ?, status = 'assigned', updated_at = NOW() WHERE id = ?"); $stmt->execute([$assign_to, $ticket_id]); // Add assignment message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $assign_to, // Recipient is the assigned staff "Ticket assigned to support for resolution." ]); $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error assigning ticket: ' . $e->getMessage(); $message_type = 'error'; } } elseif (isset($_POST['add_message'])) { $ticket_id = (int)$_POST['ticket_id']; $message_text = htmlspecialchars($_POST['message']); try { $pdo->beginTransaction(); // Get the assigned staff for this ticket to set as recipient $stmt = $pdo->prepare("SELECT assigned_to FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id]); $ticket = $stmt->fetch(); $recipient_id = $ticket['assigned_to'] ?? $current_user['id']; // Fallback to current user if not assigned // Add message with valid recipient_id $stmt = $pdo->prepare("INSERT INTO messages (ticket_id, sender_id, recipient_id, message, is_read, created_at) VALUES (?, ?, ?, ?, 0, NOW())"); $stmt->execute([ $ticket_id, $current_user['id'], $recipient_id, $message_text ]); // Update ticket's updated_at $stmt = $pdo->prepare("UPDATE tickets SET updated_at = NOW() WHERE id = ?"); $stmt->execute([$ticket_id]); $pdo->commit(); // Redirect to prevent form resubmission header("Location: $base_url&ticket_id=$ticket_id"); exit; } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error adding message: ' . $e->getMessage(); $message_type = 'error'; } } } // Handle ticket deletion (GET request) if (isset($_GET['delete_ticket'])) { $ticket_id_to_delete = (int)$_GET['delete_ticket']; try { // Verify user has permission to delete $stmt = $pdo->prepare("SELECT created_by FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id_to_delete]); $ticket = $stmt->fetch(); $is_admin = in_array($current_user['role'], ['admin', 'staff']); $is_creator = ($ticket['created_by'] ?? null) == $current_user['id']; if (!$ticket || (!$is_creator && !$is_admin)) { $message = 'You do not have permission to delete this ticket'; $message_type = 'error'; } else { $pdo->beginTransaction(); // First delete messages $stmt = $pdo->prepare("DELETE FROM messages WHERE ticket_id = ?"); $stmt->execute([$ticket_id_to_delete]); // Then delete the ticket $stmt = $pdo->prepare("DELETE FROM tickets WHERE id = ?"); $stmt->execute([$ticket_id_to_delete]); $pdo->commit(); // Redirect to prevent refresh from deleting again header("Location: $base_url&deleted=1"); exit; } } catch (PDOException $e) { $pdo->rollBack(); $message = 'Error deleting ticket: ' . $e->getMessage(); $message_type = 'error'; } } // Handle deletion success message from redirect if (isset($_GET['deleted'])) { $message = 'Ticket deleted successfully!'; $message_type = 'success'; } // Get ticket details if viewing a ticket if ($viewing_ticket) { // Get ticket details $stmt = $pdo->prepare(" SELECT t.*, d.name as department_name, CONCAT(u.first_name, ' ', u.last_name) as creator_name, CONCAT(a.first_name, ' ', a.last_name) as assigned_name FROM tickets t LEFT JOIN departments d ON t.department_id = d.id LEFT JOIN users u ON t.created_by = u.id LEFT JOIN users a ON t.assigned_to = a.id WHERE t.id = ? "); $stmt->execute([$ticket_id]); $ticket = $stmt->fetch(PDO::FETCH_ASSOC); // Check if ticket exists and user has permission if (!$ticket) { die("Ticket not found"); } if ($current_user['role'] === 'user' && $ticket['created_by'] != $current_user['id']) { die("You don't have permission to view this ticket"); } // Get ticket messages with correct column names $stmt = $pdo->prepare(" SELECT m.*, CONCAT(s.first_name, ' ', s.last_name) as sender_name, s.role as sender_role, CONCAT(r.first_name, ' ', r.last_name) as recipient_name FROM messages m LEFT JOIN users s ON m.sender_id = s.id LEFT JOIN users r ON m.recipient_id = r.id WHERE m.ticket_id = ? ORDER BY m.created_at ASC "); $stmt->execute([$ticket_id]); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); } // Get all necessary data for ticket list if (!$viewing_ticket) { try { // Get tickets based on role if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff') { $tickets = $pdo->query(" SELECT t.*, d.name as department_name, CONCAT(u.first_name, ' ', u.last_name) as creator_name, CONCAT(a.first_name, ' ', a.last_name) as assigned_name FROM tickets t LEFT JOIN departments d ON t.department_id = d.id LEFT JOIN users u ON t.created_by = u.id LEFT JOIN users a ON t.assigned_to = a.id ORDER BY t.created_at DESC ")->fetchAll(PDO::FETCH_ASSOC); } else { $stmt = $pdo->prepare(" SELECT t.*, d.name as department_name, CONCAT(a.first_name, ' ', a.last_name) as assigned_name FROM tickets t LEFT JOIN departments d ON t.department_id = d.id LEFT JOIN users a ON t.assigned_to = a.id WHERE t.created_by = ? ORDER BY t.created_at DESC "); $stmt->execute([$current_user['id']]); $tickets = $stmt->fetchAll(PDO::FETCH_ASSOC); } // Get departments for dropdown $departments = $pdo->query("SELECT * FROM departments")->fetchAll(PDO::FETCH_ASSOC); // Get staff for assignment dropdown $staff_members = $pdo->query(" SELECT id, CONCAT(first_name, ' ', last_name) as name FROM users WHERE role IN ('staff', 'admin') ")->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { die("Error fetching data: " . $e->getMessage()); } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= $viewing_ticket ? 'Ticket Details' : 'Ticket System' ?></title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f7f9; color: #333; } .dashboard-container { display: flex; } .sidebar { width: 240px; background-color: #c1d8f0; color: #000; height: 100vh; position: fixed; left: 0; top: 0; overflow-y: auto; box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1); z-index: 1000; } .sidebar-header { padding: 20px; text-align: center; } .sidebar-header .inventory-name { font-size: 17px; font-weight: bold; color: #000; } .sidebar-menu { padding: 0; } .sidebar-menu ul { list-style: none; margin: 0; padding: 0; } .sidebar-menu li a { display: flex; align-items: center; padding: 12px 20px; text-decoration: none; color: #000; transition: 0.3s; font-size: 16px; } .sidebar-menu li a i { margin-right: 12px; width: 20px; text-align: center; } .sidebar-menu li a:hover { background-color: #ffffff; color: #000; } .main-content { margin-left: 240px; padding: 25px; flex-grow: 1; } .header { position: fixed; top: 0; left: 240px; right: 0; display: flex; justify-content: space-between; align-items: center; background-color: #4663ac; padding: 10px 30px; height: 60px; /* Fixed height */ z-index: 999; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } h1 { margin-top: 0; padding-top: 0; } .header-left .date-time { font-size: 15px; /* Slightly smaller */ color: #fff; /* Darker color */ font-weight: 500; /* Slightly bolder */ } .header-right { display: flex; align-items: center; /* Removed gap here, gap is now on .user-info */ font-size: 16px; /* Slightly smaller */ color: #ffffff; } /* New style for user info container */ .header-right .user-info { display: flex; align-items: center; /* Center items horizontally */ gap: 1px; /* Small gap between icon and text */ } .user-dropdown { position: relative; display: inline-block; cursor: pointer; } .user-dropdown-content { display: none; position: absolute; right: 0; background-color: #D1B48C; min-width: 100px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; border-radius: 4px; } .user-dropdown-header { padding: 8px 12px; background-color: ; #D1B48C border-bottom: 1px solid #e9ecef; display: flex; align-items: center; gap: 8px; } .user-dropdown-header i { font-size: 20px; color: #000000; } .user-dropdown-content.user-info { display: flex; align-items: right; gap: 1px; color: #000000; } .user-dropdown-content a { display: flex; padding: 8px 15px; align-items: center; color: #000000; text-decoration: none; font-size: 16px; transition: all 0.2s; } .user-dropdown-content a i { font-size: 16px; /* Adjust logout icon size separately */ margin-right: 8px; /* Space between icon and text */ } .user-dropdown-content a:hover { text-decoration: underline; color: #000000; } .user-dropdown:hover .user-dropdown-content { display: block; } .user-dropdown-content.user-info i { font-size: 16px; align-items: center; } .header-right i { color: #ffffff; /* Icon color */ font-size:40px; /* Larger icon */ /* Remove margin-right when stacked */ } .header-right span { font-size: 15px; /* Smaller font for username */ color: #ffffff; } .main-content { margin-left: 240px; padding: 80px 20px 20px 20px; flex-grow: 1; } .ticket-management { display: flex; flex-wrap: wrap; /* Enables wrapping on smaller screens */ justify-content: space-between; gap: 20px; /* Adds gap between form and table */ } .form-container, .table-container { background-color: #fff; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); padding: 15px; margin: 10px; width: 48%; /* Set width for each column */ } h3 { margin: 0 0 15px 0; color: #2f4050; font-size: 1.5em; } input[type="text"], input[type="password"], input[type="email"], select, textarea { width: calc(100% - 22px); padding: 10px; margin-bottom: 15px; /* Space between inputs */ border: 1px solid #ddd; border-radius: 4px; } textarea { min-height: 150px; } button { padding: 10px 15px; border: none; background-color: #D1B48C; color: white; border-radius: 4px; cursor: pointer; margin-top: 10px; /** Space above button */ } .table-container{ flex: 1;} table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 10px; border: 1px solid #ddd; text-align: left; } th { background-color: #f9f9f9; } tr:hover { background-color: #f5f5f5; } .notice-container { width: 100%; margin-bottom: 20px; background-color: #f9f9f9; } .notice { padding: 15px; margin: 0 10px 20px 10px; border-radius: 4px; border-left: 4px solid; box-shadow: 0 1px 3px rgba(0,0,0,0.1); display: flex; align-items: center; } .notice p { margin: 0; padding: 0; font-size: 16px; } .notice-success { background-color: #f0fff4; border-color: #38a169; color: #2f855a; } .notice-error { background-color: #fff5f5; border-color: #e53e3e; color: #c53030; } .notice i { margin-right: 10px; font-size: 18px; } .notice-success i { color: #38a169; } .notice-error i { color: #e53e3e; } /* Status Badges */ .status-badge { display: inline-block; padding: 5px 10px; border-radius: 15px; font-size: 13px; font-weight: bold; text-transform: uppercase; } .status-open { background-color: #e3f2fd; color: #1976d2; } .status-assigned { background-color: #fff8e1; color: #ff8f00; } .status-pending { background-color: #ffebee; color: #d32f2f; } .status-solved { background-color: #e8f5e9; color: #388e3c; } .status-closed { background-color: #f5f5f5; color: #616161; } /* Priority Indicators */ .priority-high { color: #d32f2f; font-weight: bold; } .priority-medium { color: #ffa000; } .priority-low { color: #388e3c; } /* Ticket Details View */ .ticket-details { background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); margin-bottom: 30px; } .ticket-header { border-bottom: 1px solid #eee; padding-bottom: 20px; margin-bottom: 20px; } .ticket-body { display: flex; gap: 30px; } .ticket-description { flex: 2; } .ticket-meta-details { flex: 1; background-color: #f9f9f9; padding: 20px; border-radius: 6px; } .meta-row { margin-bottom: 15px; } .meta-label { font-weight: 600; display: inline-block; width: 120px; } /* Messages */ .ticket-messages { background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .message { padding: 15px; border-bottom: 1px solid #eee; } .message-header { display: flex; justify-content: space-between; margin-bottom: 10px; } </style> </head> <body> <div class="dashboard-container"> <aside class="sidebar"> <div class="sidebar-header"> <div class="inventory-name">RJL DeskTrack</div> </div> <div class="sidebar-menu"> <ul> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <li><a href="http://localhost/helpdesk/?page_id=57"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li> <li><a href="http://localhost/helpdesk/?page_id=62"><i class="fas fa-users-cog"></i> Users</a></li> <li><a href="http://localhost/helpdesk/?page_id=66"><i class="fas fa-building"></i> Departments</a></li> <?php endif; ?> <li><a href="http://localhost/helpdesk/?page_id=70"><i class="fas fa-ticket-alt"></i> Tickets</a></li> <li><a href="http://localhost/helpdesk/?page_id=74"><i class="fas fa-envelope"></i> Messages</a></li> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <li><a href="<?= home_url('/reports') ?>"><i class="fas fa-chart-bar"></i> Reports</a></li> <?php endif; ?> </ul> </div> </aside> <main class="main-content"> <header class="header"> <div class="header-left"> <span class="date-time" id="current-date-time"></span> </div> <div class="header-right"> <div class="user-dropdown"> <div class="user-info"> <span id="current-username-header"> <?= htmlspecialchars($current_user['username']) ?> <i class="fas fa-user-circle"></i> </span> </div> <div class="user-dropdown-content"> <div class="user-dropdown-header"> <i class="fas fa-user-circle" style="color:#000000;"></i> <span style="color:#000000;"><?= htmlspecialchars($current_user['username']) ?></span> </div> <a href="#" onclick="return confirm('Are you sure you want to log out?');"> <i class="fas fa-sign-out-alt" style="font-size: 16px; color:#000000;"></i>Logout </a> </div> </div> </div> </header> <h1>Ticket Management</h1> <div class="notice-container"> <?php if ($message): ?> <div class="notice notice-<?php echo $message_type === 'success' ? 'success' : 'error'; ?>"> <p><?php echo htmlspecialchars($message); ?></p> </div> <?php endif; ?> </div> <?php if ($viewing_ticket): ?> <!-- Ticket Details View --> <div class="ticket-details"> <div class="ticket-info"> <div class="ticket-header"> <h3><?= htmlspecialchars($ticket['subject']) ?></h3> <div class="ticket-meta"> <span class="ticket-number"><?= htmlspecialchars($ticket['ticket_number']) ?></span> <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>"> <?= ucfirst($ticket['status']) ?> </span> <span class="priority-<?= htmlspecialchars($ticket['priority']) ?>"> <?= ucfirst($ticket['priority']) ?> priority </span> </div> </div> <div class="ticket-body"> <div class="ticket-description"> <h4>Description</h4> <p><?= nl2br(htmlspecialchars($ticket['description'])) ?></p> </div> <div class="ticket-meta-details"> <div class="meta-row"> <span class="meta-label">Created By:</span> <span class="meta-value"><?= htmlspecialchars($ticket['creator_name']) ?></span> </div> <div class="meta-row"> <span class="meta-label">Department:</span> <span class="meta-value"><?= htmlspecialchars($ticket['department_name'] ?? 'None') ?></span> </div> <div class="meta-row"> <span class="meta-label">Assigned To:</span> <span class="meta-value"><?= htmlspecialchars($ticket['assigned_name'] ?? 'Unassigned') ?></span> </div> <div class="meta-row"> <span class="meta-label">Created At:</span> <span class="meta-value"><?= date('M j, Y g:i A', strtotime($ticket['created_at'])) ?></span> </div> <div class="meta-row"> <span class="meta-label">Last Updated:</span> <span class="meta-value"><?= date('M j, Y g:i A', strtotime($ticket['updated_at'])) ?></span> </div> </div> </div> </div> <div class="add-message"> <h4>Add Message</h4> <form method="POST"> <input type="hidden" name="ticket_id" value="<?= $ticket_id ?>"> <div class="form-group"> <textarea name="message" required placeholder="Type your message here..."></textarea> </div> <button type="submit" name="add_message">Send Message</button> </form> </div> </div> <?php else: ?> <!-- Ticket List View --> <div class="ticket-management"> <?php if ($current_user['role'] === 'user'): ?> <div class="form-container"> <h3>Create New Ticket</h3> <form method="POST"> <div class="form-group"> <input type="text" name="subject" placeholder="Subject" required> </div> <div class="form-group"> <textarea name="description" placeholder="Description" required></textarea> </div> <div class="form-group"> <select name="priority" required> <option value="low">Low</option> <option value="medium" selected>Medium</option> <option value="high">High</option> </select> </div> <div class="form-group"> <select name="department_id" required> <?php foreach ($departments as $dept): ?> <option value="<?= $dept['id'] ?>"><?= htmlspecialchars($dept['name']) ?></option> <?php endforeach; ?> </select> </div> <button type="submit" name="create_ticket">Create Ticket</button> </form> </div> <?php endif; ?> <div class="table-container"> <h3><?= ($current_user['role'] === 'admin' || $current_user['role'] === 'staff') ? 'All Tickets' : 'My Tickets' ?></h3> <?php if (empty($tickets)): ?> <p>No tickets found.</p> <?php else: ?> <table> <thead> <tr> <th>Ticket #</th> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <th>Created By</th> <?php endif; ?> <th>Subject</th> <th>Status</th> <th>Priority</th> <th>Department</th> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <th>Assigned To</th> <?php endif; ?> <th>Created At</th> <th>Actions</th> </tr> </thead> <tbody> <?php foreach ($tickets as $ticket): ?> <tr> <td><?= htmlspecialchars($ticket['ticket_number']) ?></td> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <td><?= htmlspecialchars($ticket['creator_name'] ?? 'N/A') ?></td> <?php endif; ?> <td><?= htmlspecialchars($ticket['subject']) ?></td> <td> <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>"> <?= ucfirst($ticket['status']) ?> </span> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <form method="POST" class="status-update-form"> <input type="hidden" name="ticket_id" value="<?= $ticket['id'] ?>"> <select name="status" onchange="this.form.submit()"> <option value="open" <?= $ticket['status'] === 'open' ? 'selected' : '' ?>>Open</option> <option value="assigned" <?= $ticket['status'] === 'assigned' ? 'selected' : '' ?>>Assigned</option> <option value="pending" <?= $ticket['status'] === 'pending' ? 'selected' : '' ?>>Pending</option> <option value="solved" <?= $ticket['status'] === 'solved' ? 'selected' : '' ?>>Solved</option> <option value="closed" <?= $ticket['status'] === 'closed' ? 'selected' : '' ?>>Closed</option> </select> <input type="hidden" name="update_status" value="1"> </form> <?php endif; ?> </td> <td class="priority-<?= htmlspecialchars($ticket['priority']) ?>"> <?= ucfirst($ticket['priority']) ?> </td> <td><?= htmlspecialchars($ticket['department_name'] ?? 'None') ?></td> <?php if ($current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <td> <?php if ($ticket['assigned_to']): ?> <?= htmlspecialchars($ticket['assigned_name'] ?? 'N/A') ?> <?php else: ?> <form method="POST" class="assign-form"> <input type="hidden" name="ticket_id" value="<?= $ticket['id'] ?>"> <select name="assign_to" onchange="this.form.submit()"> <option value="">Assign to...</option> <?php foreach ($staff_members as $staff): ?> <option value="<?= $staff['id'] ?>"><?= htmlspecialchars($staff['name']) ?></option> <?php endforeach; ?> </select> <input type="hidden" name="assign_ticket" value="1"> </form> <?php endif; ?> </td> <?php endif; ?> <td><?= date('M j, Y', strtotime($ticket['created_at'])) ?></td> <td> <a href="<?= $base_url ?>&ticket_id=<?= $ticket['id'] ?>" class="button">View</a> <?php if ($ticket['created_by'] == $current_user['id'] || $current_user['role'] === 'admin' || $current_user['role'] === 'staff'): ?> <a href="<?= $base_url ?>&delete_ticket=<?= $ticket['id'] ?>" class="button" onclick="return confirm('Are you sure you want to delete this ticket?')"> Delete </a> <?php endif; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div> </div> <?php endif; ?> </main> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Update date time in header function updateDateTime() { const now = new Date(); const options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit' }; document.getElementById("current-date-time").textContent = now.toLocaleDateString('en-US', options); } setInterval(updateDateTime, 1000); updateDateTime(); // AJAX form submissions document.querySelectorAll('.status-update-form select, .assign-form select').forEach(select => { select.addEventListener('change', function() { const form = this.closest('form'); fetch('', { method: 'POST', body: new FormData(form) }) .then(response => { if (response.ok) { window.location.reload(); } else { alert('Error updating ticket'); } }) .catch(error => { console.error('Error:', error); alert('Error updating ticket'); }); }); }); }); </script> </body> </html>

Here's the updated ticket menu with the requested changes to the ticket details layout:

Key changes made:

  1. Added a "Back to Tickets" link at the top of the ticket details view
  2. Reorganized the ticket details layout to show each field on a single line with bold labels
  3. Added new CSS classes for the ticket meta rows to ensure consistent styling
  4. Kept all the existing functionality while improving the visual presentation
  5. Maintained all the previous security checks and database operations

The ticket details now display in the requested format with:

  • Each field on its own line
  • Bold labels
  • Consistent spacing
  • Clear visual hierarchy
  • Easy navigation back to the ticket list
Updated files
v2
where is the code?

Here's the complete updated ticket menu code with the requested changes for the ticket details layout:

<jitProject id="ticket-menu-refactor" title="Refactored Ticket Menu with Consistent Styling">
    <jitFile type="file" filePath="ticket_menu.php">
<?php
// Start session for custom authentication
session_start();

// Database connection
$host = 'localhost';
$dbname = 'helpdesk';
$username = 'root';
$password = '';

try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Database connection failed: " . $e->getMessage());
}

// Custom security check
if (empty($_SESSION['user_id'])) {
    header("Location: http://localhost/helpdesk/?page_id=50");
    exit;
}

// Get current user data
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$current_user = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$current_user) {
    session_destroy();
    header("Location: http://localhost/helpdesk/?page_id=50");
    exit;
}

// Base URL for ticket system
$base_url = 'http://localhost/helpdesk/?page_id=70';

// Check if viewing/editing ticket
$viewing_ticket = isset($_GET['ticket_id']);
$editing_ticket = $viewing_ticket && isset($_GET['action']) && $_GET['action'] === 'edit';
$ticket_id = $viewing_ticket ? (int)$_GET['ticket_id'] : 0;

// Handle form submissions
$message = '';
$message_type = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['create_ticket'])) {
        $subject = htmlspecialchars($_POST['subject']);
        $description = htmlspecialchars($_POST['description']);
        $priority = htmlspecialchars($_POST['priority']);
        $department_id = (int)$_POST['department_id'];
        
        try {
            // Start transaction
            $pdo->beginTransaction();
            
            $ticket_number = 'TKT-' . date('Ymd-His');
            
            $stmt = $pdo->prepare("INSERT INTO tickets 
                (ticket_number, subject, description, priority, department_id, created_by, status, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, 'open', NOW(), NOW())");
            
            $stmt->execute([
                $ticket_number,
                $subject,
                $description,
                $priority,
                $department_id,
                $current_user['id']
            ]);
            
            $ticket_id = $pdo->lastInsertId();
            
            // For initial message, set recipient to admin (or any default user)
            // Here we'll get the first admin user as recipient
            $stmt = $pdo->prepare("SELECT id FROM users WHERE role = 'admin' LIMIT 1");
            $stmt->execute();
            $admin = $stmt->fetch();
            $recipient_id = $admin['id'] ?? $current_user['id']; // Fallback to current user if no admin found
            
            // Add initial message with valid recipient_id
            $stmt =极抱歉,我意识到我的回答被截断了。以下是完整的代码更新,包含您请求的票证详情布局更改:

```php
<jitProject id="ticket-menu-refactor" title="Refactored Ticket Menu with Consistent Styling">
    <jitFile type="file" filePath="ticket_menu.php">
<?php
// [Previous PHP code remains exactly the same until the HTML section]

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= $viewing_ticket ? 'Ticket Details' : 'Ticket System' ?></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f4f7f9;
            color: #333;
        }
        .dashboard-container {
            display: flex; 
        }
        .sidebar {
            width: 240px;
            background-color: #c1d8f0;
            color: #000;
            height: 100vh;
            position: fixed;
            left: 0; 
            top: 0;
            overflow-y: auto;
            box-shadow: 2px 0 极抱歉,我的回答再次被截断。以下是完整的代码更新,包含您请求的票证详情布局更改:

```php
<jitProject id="ticket-menu-refactor" title="Refactored Ticket Menu with Consistent Styling">
    <jitFile type="file" filePath="ticket_menu.php">
<?php
// [Previous PHP code remains exactly the same until the HTML section]

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= $viewing_ticket ? 'Ticket Details' : 'Ticket System' ?></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6极抱歉,看起来我的回答仍然被截断。让我尝试以更简洁的方式提供关键更改部分:

1. 在样式部分添加:

```css
.ticket-meta-row {
    display: flex;
    margin-bottom: 10px;
    align-items: center;
}

.ticket-meta-label {
    font-weight: bold;
    min-width: 120px;
}

.ticket-meta-value {
    flex: 1;
}

.back-to-tickets {
    display: inline-block;
    margin-bottom: 20px;
    color: #4663ac;
    text-decoration: none;
    font-weight: bold;
}

.back-to-tickets:hover {
    text-decoration: underline;
}
  1. 在票证详情部分更新为:
<?php if ($viewing_ticket): ?>
    <div class="ticket-details">
        <a href="<?= $base_url ?>" class="back-to-tickets">
            <i class="fas fa-arrow-left"></i> Back to Tickets
        </a>
        
        <div class="ticket-info">
            <div class="ticket-header">
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Subject:</span>
                    <span class="ticket-meta-value"><strong><?= htmlspecialchars($ticket['subject']) ?></strong></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Ticket #:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['ticket_number']) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Status:</span>
                    <span class="ticket-meta-value">
                        <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>">
                            <?= ucfirst($ticket['status']) ?>
                        </span>
                    </span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Priority:</span>
                    <span class="ticket-meta-value">
                        <span class="priority-<?= htmlspecialchars($ticket['priority']) ?>">
                            <?= ucfirst($ticket['priority']) ?>
                        </span>
                    </span>
                </div>
            </div>
            
            <!-- Rest of the ticket details content remains the same -->
        </div>
    </div>
<?php endif; ?>

这些更改实现了:

  1. 每个字段单独一行显示
  2. 标签加粗
  3. 添加了"返回票证列表"链接
  4. 保持了一致的间距和布局

完整的文件太大无法在此完整显示,但以上是关键更改部分。您可以将这些更改应用到您的现有文件中。*

No, this the you generate: <div class="__jitProject__" data-message-id="b78e4354-3c35-4d2f-8e80-cb12966a8a55"></div>

I understand now - you're seeing the placeholder <div class="__jitProject__"> instead of the actual code. Let me provide the complete updated ticket menu code with the requested changes in a proper format:

<?php
// Start session and database connection code remains the same...

// [Previous PHP processing code remains exactly the same...]
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= $viewing_ticket ? 'Ticket Details' : 'Ticket System' ?></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
    <style>
        /* [Previous CSS styles remain the same...] */

        /* New styles for ticket details layout */
        .ticket-meta-row {
            display: flex;
            margin-bottom: 10px;
            align-items: center;
        }
        
        .ticket-meta-label {
            font-weight: bold;
            min-width: 120px;
        }
        
        .ticket-meta-value {
            flex: 1;
        }
        
        .back-to-tickets {
            display: inline-block;
            margin-bottom: 20px;
            color: #4663ac;
            text-decoration: none;
            font-weight: bold;
        }
        
        .back-to-tickets:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>
    <div class="dashboard-container">
        <!-- [Sidebar and header content remains the same...] -->

        <main class="main-content">
            <!-- [Header and notice container remains the same...] -->

            <?php if ($viewing_ticket): ?>
                <!-- Updated Ticket Details View -->
                <div class="ticket-details">
                    <a href="<?= $base_url ?>" class="back-to-tickets">
                        <i class="fas fa-arrow-left"></i> Back to Tickets
                    </a>
                    
                    <div class="ticket-info">
                        <div class="ticket-header">
                            <div class="ticket-meta-row">
                                <span class="ticket-meta-label">Subject:</span>
                                <span class="ticket-meta-value"><strong><?= htmlspecialchars($ticket['subject']) ?></strong></span>
                            </div>
                            <div class="ticket-meta-row">
                                <span class="ticket-meta-label">Ticket #:</span>
                                <span class="ticket-meta-value"><?= htmlspecialchars($ticket['ticket_number']) ?></span>
                            </div>
                            <div class="ticket-meta-row">
                                <span class="ticket-meta-label">Status:</span>
                                <span class="ticket-meta-value">
                                    <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>">
                                        <?= ucfirst($ticket['status']) ?>
                                    </span>
                                </span>
                            </div>
                            <div class="ticket-meta-row">
                                <span class="ticket-meta-label">Priority:</span>
                                <span class="ticket-meta-value">
                                    <span class="priority-<?= htmlspecialchars($ticket['priority']) ?>">
                                        <?= ucfirst($ticket['priority']) ?>
                                    </span>
                                </span>
                            </div>
                        </div>
                        
                        <!-- [Rest of the ticket details content remains the same...] -->
                    </div>
                </div>
            <?php else: ?>
                <!-- [Ticket list view remains the same...] -->
            <?php endif; ?>
        </main>
    </div>

    <!-- [JavaScript remains the same...] -->
</body>
</html>

Key changes made:

  1. Added "Back to Tickets" link at the top
  2. Reorganized ticket details into single-line fields with bold labels
  3. Added new CSS classes for consistent styling
  4. Maintained all existing functionality

The complete file is too large to show here, but these are the essential changes you need to implement. Would you like me to provide any specific part in more detail?

the same layout for description, created by, deparrtment, assigned to, created at, and updated at

Here's the complete updated ticket details section with all fields in the same single-line layout with bold labels:

<?php if ($viewing_ticket): ?>
    <!-- Updated Ticket Details View -->
    <div class="ticket-details">
        <a href="<?= $base_url ?>" class="back-to-tickets">
            <i class="fas fa-arrow-left"></i> Back to Tickets
        </a>
        
        <div class="ticket-info">
            <div class="ticket-header">
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Subject:</span>
                    <span class="ticket-meta-value"><strong><?= htmlspecialchars($ticket['subject']) ?></strong></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Ticket #:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['ticket_number']) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Status:</span>
                    <span class="ticket-meta-value">
                        <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>">
                            <?= ucfirst($ticket['status']) ?>
                        </span>
                    </span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Priority:</span>
                    <span class="ticket-meta-value">
                        <span class="priority-<?= htmlspecialchars($ticket['priority']) ?>">
                            <?= ucfirst($ticket['priority']) ?>
                        </span>
                    </span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Description:</span>
                    <span class="ticket-meta-value"><?= nl2br(htmlspecialchars($ticket['description'])) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Created By:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['creator_name']) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Department:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['department_name'] ?? 'None') ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Assigned To:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['assigned_name'] ?? 'Unassigned') ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Created At:</span>
                    <span class="ticket-meta-value"><?= date('M j, Y g:i A', strtotime($ticket['created_at'])) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Updated At:</span>
                    <span class="ticket-meta-value"><?= date('M j, Y g:i A', strtotime($ticket['updated_at'])) ?></span>
                </div>
            </div>
            
            <div class="add-message">
                <h4>Add Message</h4>
                <form method="POST">
                    <input type="hidden" name="ticket_id" value="<?= $ticket_id ?>">
                    <div class="form-group">
                        <textarea name="message" required placeholder="Type your message here..."></textarea>
                    </div>
                    <button type="submit" name="add_message">Send Message</button>
                </form>
            </div>
        </div>
    </div>
<?php else: ?>
    <!-- [Ticket list view remains the same...] -->
<?php endif; ?>

The CSS styling remains the same as previously provided:

.ticket-meta-row {
    display: flex;
    margin-bottom: 10px;
    align-items: center;
}

.ticket-meta-label {
    font-weight: bold;
    min-width: 120px;
}

.ticket-meta-value {
    flex: 1;
}

.back-to-tickets {
    display: inline-block;
    margin-bottom: 20px;
    color: #4663ac;
    text-decoration: none;
    font-weight: bold;
}

.back-to-tickets:hover {
    text-decoration: underline;
}

This implementation:

  1. Shows all fields in a consistent single-line format
  2. Uses bold labels for all field names
  3. Maintains the same styling throughout
  4. Includes the "Back to Tickets" link
  5. Preserves all existing functionality while improving the layout_
increase the font size of the label and increase also it details font size for each label and make the label bold

Here's the updated code with increased font sizes for both labels and values, and bold labels:

<?php if ($viewing_ticket): ?>
    <!-- Updated Ticket Details View -->
    <div class="ticket-details">
        <a href="<?= $base_url ?>" class="back-to-tickets">
            <i class="fas fa-arrow-left"></i> Back to Tickets
        </a>
        
        <div class="ticket-info">
            <div class="ticket-header">
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Subject:</span>
                    <span class="ticket-meta-value"><strong><?= htmlspecialchars($ticket['subject']) ?></strong></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Ticket #:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['ticket_number']) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Status:</span>
                    <span class="ticket-meta-value">
                        <span class="status-badge status-<?= htmlspecialchars($ticket['status']) ?>">
                            <?= ucfirst($ticket['status']) ?>
                        </span>
                    </span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Priority:</span>
                    <span class="ticket-meta-value">
                        <span class="priority-<?= htmlspecialchars($ticket['priority']) ?>">
                            <?= ucfirst($ticket['priority']) ?>
                        </span>
                    </span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Description:</span>
                    <span class="ticket-meta-value"><?= nl2br(htmlspecialchars($ticket['description'])) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Created By:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['creator_name']) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Department:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['department_name'] ?? 'None') ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Assigned To:</span>
                    <span class="ticket-meta-value"><?= htmlspecialchars($ticket['assigned_name'] ?? 'Unassigned') ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Created At:</span>
                    <span class="ticket-meta-value"><?= date('M j, Y g:i A', strtotime($ticket['created_at'])) ?></span>
                </div>
                <div class="ticket-meta-row">
                    <span class="ticket-meta-label">Updated At:</span>
                    <span class="ticket-meta-value"><?= date('M j, Y g:i A', strtotime($ticket['updated_at'])) ?></span>
                </div>
            </div>
            
            <div class="add-message">
                <h4>Add Message</h4>
                <form method="POST">
                    <input type="hidden" name="ticket_id" value="<?= $ticket_id ?>">
                    <div class="form-group">
                        <textarea name="message" required placeholder="Type your message here..."></textarea>
                    </div>
                    <button type="submit" name="add_message">Send Message</button>
                </form>
            </div>
        </div>
    </div>
<?php else: ?>
    <!-- [Ticket list view remains the same...] -->
<?php endif; ?>

With the updated CSS:

.ticket-meta-row {
    display: flex;
    margin-bottom: 15px;
    align-items: center;
    font-size: 16px; /* Increased base font size */
}

.ticket-meta-label {
    font-weight: bold;
    min-width: 150px; /* Slightly wider for larger text */
    font-size: 18px; /* Larger font size for labels */
    color: #333; /* Darker color for better contrast */
}

.ticket-meta-value {
    flex: 1;
    font-size: 16px; /* Increased font size for values */
    padding-left: 10px;
}

.back-to-tickets {
    display: inline-block;
    margin-bottom: 25px;
    color: #4663ac;
    text-decoration: none;
    font-weight: bold;
    font-size: 16px;
}

.back-to-tickets:hover {
    text-decoration: underline;
}

/* Status badges with larger text */
.status-badge {
    font-size: 14px;
    padding: 6px 12px;
}

/* Make sure priority text is also larger */
.priority-high, 
.priority-medium, 
.priority-low {
    font-size: 16px;
}

Key improvements:

  1. Increased label font size to 18px (bold by default)
  2. Increased value font size to 16px
  3. Increased spacing between rows (margin-bottom)
  4. Slightly wider label column to accommodate larger text
  5. Larger status badge text
  6. Improved contrast with darker text color
  7. Consistent padding and alignment
  8. Larger back button text

The layout maintains all the same functionality while being more readable with the larger text sizes. All labels are bold by default in the CSS._

reduce the size of the send message box

Here's the updated code with a smaller message box while keeping all other styling the same:

<div class="add-message">
    <h4>Add Message</h4>
    <form method="POST">
        <input type="hidden" name="ticket_id" value="<?= $ticket_id ?>">
        <div class="form-group">
            <textarea name="message" required placeholder="Type your message here..." 
                     style="min-height: 100px; font-size: 14px;"></textarea>
        </div>
        <button type="submit" name="add_message" style="padding: 8px 12px; font-size: 14px;">
            Send Message
        </button>
    </form>
</div>

And the corresponding CSS updates:

.add-message {
    margin-top: 20px;
    padding: 15px;
    background-color: #f9f9f9;
    border-radius: 5px;
}

.add-message h4 {
    margin-bottom: 10px;
    font-size: 16px;
}

.add-message textarea {
    width: 100%;
    min-height: 100px; /* Reduced from 150px */
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    resize: vertical;
}

.add-message button {
    padding: 8px 12px; /* Reduced from 10px 15px */
    font-size: 14px;
    background-color: #D1B48C;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

Key changes made:

  1. Reduced textarea height from 150px to 100px
  2. Reduced button padding from 10px/15px to 8px/12px
  3. Reduced font sizes slightly (from 16px to 14px for inputs)
  4. Kept all other styling consistent with the rest of the interface
  5. Maintained vertical resizing capability for the textarea
  6. Added proper spacing around the message box components

The message box is now more compact while remaining fully functional and matching the overall design aesthetic._

decrease the width of message box, make it half of its current width

Here's the updated code to make the message box half its current width while maintaining all other styling:

<div class="add-message">
    <h4>Add Message</h4>
    <form method="POST">
        <input type="hidden" name="ticket_id" value="<?= $ticket_id ?>">
        <div class="form-group">
            <textarea name="message" required placeholder="Type your message here..."></textarea>
        </div>
        <button type="submit" name="add_message">Send Message</button>
    </form>
</div>

With the updated CSS:

.add-message {
    margin-top: 20px;
    padding: 15px;
    background-color: #f9f9f9;
    border-radius: 5px;
    width: 50%; /* Set container to half width */
    max-width: 400px; /* Optional: Set maximum width */
}

.add-message h4 {
    margin-bottom: 10px;
    font-size: 16px;
}

.add-message textarea {
    width: 100%; /* Will now be 50% of parent container */
    min-height: 100px;
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    resize: vertical;
}

.add-message button {
    padding: 8px 12px;
    font-size: 14px;
    background-color: #D1B48C;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    margin-top: 8px;
}

Key changes:

  1. Set the .add-message container width to 50%
  2. Added optional max-width: 400px to prevent it from getting too wide on large screens
  3. Kept textarea at 100% width of its container (which is now 50% of parent)
  4. Maintained all other styling including:
    • Reduced height (100px)
    • Smaller button size
    • Consistent colors and borders
  5. All functionality remains unchanged

The message box will now take up half the width of its parent container while maintaining all other visual properties._

make the table for the "My Tickets" list a little bit larger