diff --git a/assets/css/dashboard.css b/assets/css/dashboard.css index 5cf3b3f..e866b7b 100644 --- a/assets/css/dashboard.css +++ b/assets/css/dashboard.css @@ -227,6 +227,71 @@ td:nth-child(2) span { box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); } +.search-container { + margin: 20px 0; + padding: 0 20px; +} + +.search-form { + display: flex; + gap: 10px; + align-items: center; + flex-wrap: wrap; +} + +.search-box { + flex: 1; + min-width: 300px; + padding: 10px 15px; + border: 2px solid #ddd; + border-radius: 5px; + font-size: 16px; + transition: border-color 0.3s; +} + +.search-box:focus { + outline: none; + border-color: #007cba; +} + +.search-btn { + padding: 10px 20px; + background-color: #007cba; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + font-size: 16px; + transition: background-color 0.3s; +} + +.search-btn:hover { + background-color: #005a87; +} + +.clear-search-btn { + padding: 10px 15px; + background-color: #6c757d; + color: white; + text-decoration: none; + border-radius: 5px; + font-size: 14px; + transition: background-color 0.3s; +} + +.clear-search-btn:hover { + background-color: #545b62; +} + +/* Show search results info */ +.search-results-info { + margin: 10px 0; + padding: 10px; + background-color: #e7f3ff; + border-left: 4px solid #007cba; + border-radius: 4px; +} + /* Status Filter Dropdown */ .status-filter-container { position: relative; diff --git a/assets/js/dashboard.js b/assets/js/dashboard.js index 62da745..06c0708 100644 --- a/assets/js/dashboard.js +++ b/assets/js/dashboard.js @@ -15,7 +15,6 @@ document.addEventListener('DOMContentLoaded', function() { if (isDashboard) { // Dashboard-specific initialization - initSearch(); initStatusFilter(); initTableSorting(); @@ -192,22 +191,6 @@ function initThemeToggle() { document.body.appendChild(toggle); } -function initSearch() { - const searchBox = document.createElement('input'); - searchBox.type = 'text'; - searchBox.placeholder = 'Search tickets...'; - searchBox.className = 'search-box'; - searchBox.oninput = (e) => { - const searchTerm = e.target.value.toLowerCase(); - const rows = document.querySelectorAll('tbody tr'); - rows.forEach(row => { - const text = row.textContent.toLowerCase(); - row.style.display = text.includes(searchTerm) ? '' : 'none'; - }); - }; - document.querySelector('h1').after(searchBox); -} - function initStatusFilter() { const filterContainer = document.createElement('div'); filterContainer.className = 'status-filter-container'; diff --git a/controllers/DashboardController.php b/controllers/DashboardController.php index b0c7dd9..9d02e78 100644 --- a/controllers/DashboardController.php +++ b/controllers/DashboardController.php @@ -18,6 +18,7 @@ class DashboardController { $sortDirection = isset($_GET['dir']) ? $_GET['dir'] : 'desc'; $category = isset($_GET['category']) ? $_GET['category'] : null; $type = isset($_GET['type']) ? $_GET['type'] : null; + $search = isset($_GET['search']) ? trim($_GET['search']) : null; // ADD THIS LINE // Handle status filtering $status = null; @@ -29,8 +30,8 @@ class DashboardController { } // If $_GET['show_all'] exists or no status param with show_all, show all tickets (status = null) - // Get tickets with pagination and sorting - $result = $this->ticketModel->getAllTickets($page, $limit, $status, $sortColumn, $sortDirection, $category, $type); + // Get tickets with pagination, sorting, and search + $result = $this->ticketModel->getAllTickets($page, $limit, $status, $sortColumn, $sortDirection, $category, $type, $search); // Get categories and types for filters $categories = $this->getCategories(); diff --git a/models/TicketModel.php b/models/TicketModel.php index 4bb1e2e..cd4e9e8 100644 --- a/models/TicketModel.php +++ b/models/TicketModel.php @@ -35,7 +35,7 @@ class TicketModel { return $comments; } - public function getAllTickets($page = 1, $limit = 15, $status = 'Open', $sortColumn = 'ticket_id', $sortDirection = 'desc', $category = null, $type = null) { + public function getAllTickets($page = 1, $limit = 15, $status = 'Open', $sortColumn = 'ticket_id', $sortDirection = 'desc', $category = null, $type = null, $search = null) { // Calculate offset $offset = ($page - 1) * $limit; @@ -71,6 +71,14 @@ class TicketModel { $paramTypes .= str_repeat('s', count($types)); } + // Search Functionality + if ($search && !empty($search)) { + $whereConditions[] = "(title LIKE ? OR description LIKE ? OR ticket_id LIKE ? OR category LIKE ? OR type LIKE ?)"; + $searchTerm = "%$search%"; + $params = array_merge($params, [$searchTerm, $searchTerm, $searchTerm, $searchTerm, $searchTerm]); + $paramTypes .= 'sssss'; + } + $whereClause = ''; if (!empty($whereConditions)) { $whereClause = 'WHERE ' . implode(' AND ', $whereConditions); diff --git a/views/CreateTicketView.php b/views/CreateTicketView.php index 8a4e88f..2d9544e 100644 --- a/views/CreateTicketView.php +++ b/views/CreateTicketView.php @@ -76,7 +76,7 @@ diff --git a/views/DashboardView.php b/views/DashboardView.php index 0bfe6f7..f24a4ea 100644 --- a/views/DashboardView.php +++ b/views/DashboardView.php @@ -17,7 +17,45 @@

Tinker Tickets

- +
+
+ + + + + + + + + + + + + + + + + + + + + + + + Clear + +
+
+ +
+ Showing results for: "" + ( ticket found) +
+
Total Tickets: