Changed Client-side Search to Server-side Search
This commit is contained in:
@ -227,6 +227,71 @@ td:nth-child(2) span {
|
|||||||
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
|
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 Dropdown */
|
||||||
.status-filter-container {
|
.status-filter-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@ -15,7 +15,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
if (isDashboard) {
|
if (isDashboard) {
|
||||||
// Dashboard-specific initialization
|
// Dashboard-specific initialization
|
||||||
initSearch();
|
|
||||||
initStatusFilter();
|
initStatusFilter();
|
||||||
initTableSorting();
|
initTableSorting();
|
||||||
|
|
||||||
@ -192,22 +191,6 @@ function initThemeToggle() {
|
|||||||
document.body.appendChild(toggle);
|
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() {
|
function initStatusFilter() {
|
||||||
const filterContainer = document.createElement('div');
|
const filterContainer = document.createElement('div');
|
||||||
filterContainer.className = 'status-filter-container';
|
filterContainer.className = 'status-filter-container';
|
||||||
|
|||||||
@ -18,6 +18,7 @@ class DashboardController {
|
|||||||
$sortDirection = isset($_GET['dir']) ? $_GET['dir'] : 'desc';
|
$sortDirection = isset($_GET['dir']) ? $_GET['dir'] : 'desc';
|
||||||
$category = isset($_GET['category']) ? $_GET['category'] : null;
|
$category = isset($_GET['category']) ? $_GET['category'] : null;
|
||||||
$type = isset($_GET['type']) ? $_GET['type'] : null;
|
$type = isset($_GET['type']) ? $_GET['type'] : null;
|
||||||
|
$search = isset($_GET['search']) ? trim($_GET['search']) : null; // ADD THIS LINE
|
||||||
|
|
||||||
// Handle status filtering
|
// Handle status filtering
|
||||||
$status = null;
|
$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)
|
// If $_GET['show_all'] exists or no status param with show_all, show all tickets (status = null)
|
||||||
|
|
||||||
// Get tickets with pagination and sorting
|
// Get tickets with pagination, sorting, and search
|
||||||
$result = $this->ticketModel->getAllTickets($page, $limit, $status, $sortColumn, $sortDirection, $category, $type);
|
$result = $this->ticketModel->getAllTickets($page, $limit, $status, $sortColumn, $sortDirection, $category, $type, $search);
|
||||||
|
|
||||||
// Get categories and types for filters
|
// Get categories and types for filters
|
||||||
$categories = $this->getCategories();
|
$categories = $this->getCategories();
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class TicketModel {
|
|||||||
return $comments;
|
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
|
// Calculate offset
|
||||||
$offset = ($page - 1) * $limit;
|
$offset = ($page - 1) * $limit;
|
||||||
|
|
||||||
@ -71,6 +71,14 @@ class TicketModel {
|
|||||||
$paramTypes .= str_repeat('s', count($types));
|
$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 = '';
|
$whereClause = '';
|
||||||
if (!empty($whereConditions)) {
|
if (!empty($whereConditions)) {
|
||||||
$whereClause = 'WHERE ' . implode(' AND ', $whereConditions);
|
$whereClause = 'WHERE ' . implode(' AND ', $whereConditions);
|
||||||
|
|||||||
@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
<div class="ticket-footer">
|
<div class="ticket-footer">
|
||||||
<button type="submit" class="btn primary">Create Ticket</button>
|
<button type="submit" class="btn primary">Create Ticket</button>
|
||||||
<button type="button" onclick="window.location.href='<?php echo $GLOBALS['config']['BASE_URL']; ?>'" class="btn back-btn">Cancel</button>
|
<button type="button" onclick="window.location.href='<?php echo $GLOBALS['config']['BASE_URL']; ?>/'" class="btn back-btn">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,7 +17,45 @@
|
|||||||
<h1>Tinker Tickets</h1>
|
<h1>Tinker Tickets</h1>
|
||||||
<button onclick="window.location.href='/ticket/create'" class="btn create-ticket">New Ticket</button>
|
<button onclick="window.location.href='/ticket/create'" class="btn create-ticket">New Ticket</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search-container">
|
||||||
|
<form method="GET" action="" class="search-form">
|
||||||
|
<!-- Preserve existing parameters -->
|
||||||
|
<?php if (isset($_GET['status'])): ?>
|
||||||
|
<input type="hidden" name="status" value="<?php echo htmlspecialchars($_GET['status']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['show_all'])): ?>
|
||||||
|
<input type="hidden" name="show_all" value="<?php echo htmlspecialchars($_GET['show_all']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['category'])): ?>
|
||||||
|
<input type="hidden" name="category" value="<?php echo htmlspecialchars($_GET['category']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['type'])): ?>
|
||||||
|
<input type="hidden" name="type" value="<?php echo htmlspecialchars($_GET['type']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['sort'])): ?>
|
||||||
|
<input type="hidden" name="sort" value="<?php echo htmlspecialchars($_GET['sort']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['dir'])): ?>
|
||||||
|
<input type="hidden" name="dir" value="<?php echo htmlspecialchars($_GET['dir']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<input type="text"
|
||||||
|
name="search"
|
||||||
|
placeholder="Search tickets..."
|
||||||
|
class="search-box"
|
||||||
|
value="<?php echo isset($_GET['search']) ? htmlspecialchars($_GET['search']) : ''; ?>">
|
||||||
|
<button type="submit" class="search-btn">Search</button>
|
||||||
|
<?php if (isset($_GET['search']) && !empty($_GET['search'])): ?>
|
||||||
|
<a href="?" class="clear-search-btn">Clear</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<?php if (isset($_GET['search']) && !empty($_GET['search'])): ?>
|
||||||
|
<div class="search-results-info">
|
||||||
|
Showing results for: "<strong><?php echo htmlspecialchars($_GET['search']); ?></strong>"
|
||||||
|
(<?php echo $totalTickets; ?> ticket<?php echo $totalTickets != 1 ? 's' : ''; ?> found)
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="table-controls">
|
<div class="table-controls">
|
||||||
<div class="ticket-count">
|
<div class="ticket-count">
|
||||||
Total Tickets: <?php echo $totalTickets; ?>
|
Total Tickets: <?php echo $totalTickets; ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user