diff --git a/src/add_comment.php b/add_comment.php similarity index 100% rename from src/add_comment.php rename to add_comment.php diff --git a/src/assets/css/dashboard.css b/assets/css/dashboard.css similarity index 100% rename from src/assets/css/dashboard.css rename to assets/css/dashboard.css diff --git a/src/assets/css/ticket.css b/assets/css/ticket.css similarity index 100% rename from src/assets/css/ticket.css rename to assets/css/ticket.css diff --git a/src/assets/images/favicon.png b/assets/images/favicon.png similarity index 100% rename from src/assets/images/favicon.png rename to assets/images/favicon.png diff --git a/src/assets/js/dashboard.js b/assets/js/dashboard.js similarity index 100% rename from src/assets/js/dashboard.js rename to assets/js/dashboard.js diff --git a/src/assets/js/ticket.js b/assets/js/ticket.js similarity index 100% rename from src/assets/js/ticket.js rename to assets/js/ticket.js diff --git a/src/create_ticket_api.php b/create_ticket_api.php similarity index 100% rename from src/create_ticket_api.php rename to create_ticket_api.php diff --git a/src/dashboard.php b/dashboard.php similarity index 100% rename from src/dashboard.php rename to dashboard.php diff --git a/src/logo.svg b/logo.svg similarity index 100% rename from src/logo.svg rename to logo.svg diff --git a/src/new_ticket.php b/new_ticket.php similarity index 100% rename from src/new_ticket.php rename to new_ticket.php diff --git a/src_backup/add_comment.php b/src_backup/add_comment.php deleted file mode 100644 index cfcbae6..0000000 --- a/src_backup/add_comment.php +++ /dev/null @@ -1,50 +0,0 @@ -prepare($sql); - -// Convert markdown_enabled to integer for database -$markdownEnabled = $data['markdown_enabled'] ? 1 : 0; - -$stmt->bind_param("sssi", - $data['ticket_id'], - $username, - $data['comment_text'], - $markdownEnabled -); - -if ($stmt->execute()) { - header('Content-Type: application/json'); - echo json_encode([ - 'success' => true, - 'user_name' => $username, - 'created_at' => date('M d, Y H:i'), - 'markdown_enabled' => $markdownEnabled - ]); -} else { - echo json_encode([ - 'success' => false, - 'error' => $conn->error - ]); -} - -$stmt->close(); -$conn->close(); diff --git a/src_backup/assets/css/dashboard.css b/src_backup/assets/css/dashboard.css deleted file mode 100644 index d68e1f0..0000000 --- a/src_backup/assets/css/dashboard.css +++ /dev/null @@ -1,553 +0,0 @@ -/* Variables */ -:root { - --bg-primary: #f5f7fa; - --bg-secondary: #ffffff; - --text-primary: #2c3e50; - --text-secondary: #4a5568; - --border-color: #eee; - --shadow: 0 2px 4px rgba(0,0,0,0.1); - --hover-bg: #f8f9fa; - --priority-1: #ff4d4d; - --priority-2: #ffa726; - --priority-3: #42a5f5; - --priority-4: #66bb6a; - - /* Spacing */ - --spacing-xs: 0.5rem; - --spacing-sm: 1rem; - --spacing-md: 1.5rem; - --spacing-lg: 2rem; - - /* Transitions */ - --transition-default: all 0.3s ease; -} - -/* Dark theme */ -[data-theme="dark"] { - --bg-primary: #1a202c; - --bg-secondary: #2d3748; - --text-primary: #f7fafc; - --text-secondary: #e2e8f0; - --border-color: #4a5568; - --shadow: 0 2px 4px rgba(0,0,0,0.3); - --hover-bg: #374151; - --priority-1: #7f1d1d; - --priority-2: #854d0e; - --priority-3: #075985; - --priority-4: #166534; -} - -/* Base Elements */ -body { - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - margin: 0; - padding: var(--spacing-md); - background-color: var(--bg-primary); - color: var(--text-primary); - transition: var(--transition-default); -} - -/* Reusable Components */ -.card-base { - background: var(--bg-secondary); - border-radius: 12px; - box-shadow: var(--shadow); - padding: var(--spacing-md); -} - -.btn-base { - padding: var(--spacing-sm) var(--spacing-md); - border-radius: 6px; - border: none; - cursor: pointer; - transition: var(--transition-default); -} - -.btn-primary { - background: #3b82f6; - color: white; -} - -/* Layout Components */ -.dashboard-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: var(--spacing-md); - margin-left: 3.75rem; -} - -.ticket-container { - max-width: 800px; - margin: var(--spacing-lg) auto; - border-left: 6px solid; - transition: var(--transition-default); -} - -.flex-row { - display: flex; - gap: var(--spacing-sm); -} - -.flex-between { - justify-content: space-between; - align-items: center; -} - -/* Table Styles */ -.table-base { - width: 100%; - border-collapse: separate; - border-spacing: 0; - overflow: hidden; -} - -.table-cell { - padding: var(--spacing-md); - text-align: left; - border-bottom: 1px solid var(--border-color); -} - -/* Priority Styles */ -.priority-indicator { - font-weight: bold; - font-family: 'Courier New', monospace; - padding: var(--spacing-xs) var(--spacing-sm); - border-radius: 4px; - display: inline-block; -} - -.priority-1 { color: var(--priority-1); } -.priority-2 { color: var(--priority-2); } -.priority-3 { color: var(--priority-3); } -.priority-4 { color: var(--priority-4); } - -/* Status Styles */ -.status-base { - font-weight: bold; - padding: var(--spacing-xs) var(--spacing-sm); - border-radius: 4px; -} - -.status-Open { - color: #10b981; - background: rgba(16, 185, 129, 0.1); -} - -.status-Closed { - color: #ef4444; - background: rgba(239, 68, 68, 0.1); -} - -/*UNCHECKED BELOW*/ - -body.menu-open { - padding-left: 260px; -} - -.create-ticket { - background: #3b82f6; - color: white; - padding: 0.625rem 1.25rem; - border-radius: 0.375rem; - border: none; - cursor: pointer; - font-weight: 500; - transition: background-color 0.3s ease; - margin-right: 3.75rem; -} - -.create-ticket:hover { - background: #2563eb; -} - -h1 { - color: var(--text-primary); - margin: 0; -} - -table { - width: 100%; - border-collapse: separate; - border-spacing: 0; - background: var(--bg-secondary); - border-radius: 12px; - box-shadow: var(--shadow); - overflow: hidden; -} - -th, td { - padding: 16px; - text-align: left; - border-bottom: 1px solid var(--border-color); - color: var(--text-primary); -} - -th { - background-color: var(--bg-secondary); - font-weight: 600; - text-transform: uppercase; - font-size: 0.9em; - letter-spacing: 0.05em; -} - -tr:hover { - background-color: var(--hover-bg); -} - -tbody tr td:first-child { - border-left: 6px solid; -} - -tbody tr.priority-1 td:first-child { border-left-color: var(--priority-1); } -tbody tr.priority-2 td:first-child { border-left-color: var(--priority-2); } -tbody tr.priority-3 td:first-child { border-left-color: var(--priority-3); } -tbody tr.priority-4 td:first-child { border-left-color: var(--priority-4); } - -/* Priority number styling */ -td:nth-child(2) { - text-align: center; -} - -td:nth-child(2) span { - font-weight: bold; - font-family: 'Courier New', monospace; - padding: 4px 8px; - border-radius: 4px; - display: inline-block; - background: var(--hover-bg); -} - -.priority-1 td:nth-child(2) { color: var(--priority-1); } -.priority-2 td:nth-child(2) { color: var(--priority-2); } -.priority-3 td:nth-child(2) { color: var(--priority-3); } -.priority-4 td:nth-child(2) { color: var(--priority-4); } - -.search-box { - padding: 0.5rem 0.75rem; - border: 1px solid var(--border-color); - border-radius: 0.375rem; - background: var(--bg-secondary); - color: var(--text-primary); - margin-left: 1.25rem; - width: 40%; -} - -.status-filter { - padding: 0.5rem 0.75rem; - border: 1px solid var(--border-color); - border-radius: 0.375rem; - background: var(--bg-secondary); - color: var(--text-primary); - cursor: pointer; - min-width: 120px; - margin-right: 1rem; -} - -.search-box:focus, -.status-filter:focus { - outline: none; - border-color: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); -} - -.theme-toggle { - position: absolute; - top: 20px; - right: 20px; - z-index: 100; - padding: 12px; - border-radius: 50%; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - cursor: pointer; - box-shadow: var(--shadow); - font-size: 1.2em; - transition: transform 0.3s ease; -} - -.theme-toggle:hover { - transform: scale(1.1); -} - -.table-controls { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 15px; - padding: 10px; - background: var(--bg-secondary); - border-radius: 8px; - box-shadow: var(--shadow); -} - -.ticket-count { - font-weight: 500; - color: var(--text-secondary); -} - -.table-actions { - display: flex; - gap: 15px; - align-items: center; -} -.pagination { - display: flex; - gap: 0.5rem; - align-items: center; -} - -.pagination button { - padding: 0.5rem 0.75rem; - border: 1px solid var(--border-color); - background: var(--bg-secondary); - color: var(--text-primary); - border-radius: 0.375rem; - cursor: pointer; - transition: all 0.2s ease; -} - -.pagination button:hover { - background: var(--hover-bg); -} - -.pagination button.active { - background: #3b82f6; - color: white; - border-color: #3b82f6; -} - -.settings-icon { - cursor: pointer; - padding: 8px; - border-radius: 4px; - transition: background-color 0.2s; -} - -.settings-icon:hover { - background: var(--hover-bg); -} - -/* Settings Modal Styles */ -.settings-modal-backdrop { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; -} - -.settings-modal { - background: var(--bg-secondary); - border-radius: 12px; - width: 500px; - max-width: 90%; - box-shadow: var(--shadow); - padding: 20px; -} - -.settings-modal-header { - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid var(--border-color); - padding-bottom: 15px; - margin-bottom: 15px; -} - -.settings-modal-header h2 { - margin: 0; - color: var(--text-primary); -} - -.close-modal { - background: none; - border: none; - font-size: 24px; - cursor: pointer; - color: var(--text-secondary); -} - -.setting-group { - margin-bottom: 15px; -} - -.setting-group label { - display: block; - margin-bottom: 8px; - color: var(--text-primary); -} - -.setting-group select { - width: 100%; - padding: 10px; - border: 1px solid var(--border-color); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-primary); -} - -.settings-modal-footer { - display: flex; - justify-content: flex-end; - gap: 10px; - border-top: 1px solid var(--border-color); - padding-top: 15px; -} - -.save-settings, .cancel-settings { - padding: 10px 20px; - border-radius: 6px; - border: none; - cursor: pointer; - transition: background-color 0.3s ease; -} - -.save-settings { - background: #3b82f6; - color: white; -} - -.cancel-settings { - background: var(--hover-bg); - color: var(--text-primary); -} - -/* Sorting indicator styles */ -th { - position: relative; /* Ensure proper positioning of arrows */ - cursor: pointer; /* Show it's clickable */ -} - -th::after { - content: ''; - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - width: 0; - height: 0; - border-left: 5px solid transparent; - border-right: 5px solid transparent; - opacity: 0.5; /* Make arrows less prominent when not active */ -} - -th.sort-asc::after { - border-bottom: 7px solid var(--text-primary); - opacity: 1; -} - -th.sort-desc::after { - border-top: 7px solid var(--text-primary); - opacity: 1; -} -/* Column toggle styles */ -.column-toggles { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 10px; -} - -.column-toggles label { - display: flex; - align-items: center; - gap: 8px; -} - -.hamburger-menu { - position: absolute; - top: 20px; - left: 20px; - z-index: 100; -} - -.hamburger-icon { - cursor: pointer; - font-size: 24px; - background: var(--bg-secondary); - padding: 10px; - border-radius: 4px; - box-shadow: var(--shadow); -} - -.hamburger-content { - position: fixed; - top: 0; - left: -250px; - width: 200px; - height: 100%; - background: var(--bg-secondary); - box-shadow: 2px 0 5px rgba(0,0,0,0.1); - transition: left 0.3s ease, margin-left 0.3s ease; - padding: 40px 20px 20px; - overflow-y: auto; - z-index: 99; -} - -.hamburger-content.open { - left: 0; -} - -.close-hamburger { - position: absolute; - top: 10px; - right: 10px; - cursor: pointer; - font-size: 24px; - background: var(--bg-secondary); - padding: 10px; - border-radius: 4px; - box-shadow: var(--shadow); -} - -.filter-section { - margin-bottom: 20px; -} - -.filter-section label { - display: block; - margin-bottom: 10px; -} - -.filter-actions { - display: flex; - gap: 10px; -} - -.filter-actions button { - flex: 1; - padding: 10px; - border: none; - border-radius: 4px; - cursor: pointer; -} - -#apply-filters { - background: #3b82f6; - color: white; -} - -#clear-filters { - background: var(--hover-bg); - color: var(--text-primary); -} - -.ticket-link { - font-family: 'Courier New', monospace; - font-weight: bold; - color: var(--text-primary) !important; - text-decoration: none; - background: var(--hover-bg); - padding: 4px 8px; - border-radius: 4px; - display: inline-block; -} - -.ticket-link:hover { - background: var(--border-color); -} diff --git a/src_backup/assets/css/ticket.css b/src_backup/assets/css/ticket.css deleted file mode 100644 index b980f8e..0000000 --- a/src_backup/assets/css/ticket.css +++ /dev/null @@ -1,413 +0,0 @@ -/* Base Layout Components */ -.ticket-container { - max-width: 800px; - margin: 40px auto; - padding: 20px; - background: var(--bg-secondary); - border-radius: 12px; - box-shadow: var(--shadow); - border-left: 6px solid; - transition: border-color 0.3s ease; -} - -.full-width { - grid-column: 1 / -1; -} -/* Header Components */ -.ticket-header { - display: flex; - flex-direction: column; - margin-bottom: 30px; -} - -.ticket-subheader { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 10px; -} - -.header-controls { - display: flex; - gap: 15px; - align-items: center; -} - -.ticket-id { - font-family: 'Courier New', monospace; - margin-right: 20px; -} - -h1 { - margin: 0; - padding: 0; - width: 100%; - display: block; -} - -/* Title Input Styles */ -.title-input { - font-size: 1em; - font-weight: bold; - width: 100%; - border: 2px solid transparent; - border-radius: 4px; - padding: 4px; - margin: -4px; - word-break: break-word; - white-space: normal; - display: block; -}.title-input:not(:disabled) { - border-color: var(--border-color); - background: var(--bg-primary); -} - -.title-input:not(:disabled):hover { - border-color: #3b82f6; -} - -.title-input:disabled { - color: var(--text-primary); - border: none; - background: transparent; -} - -/* Form Elements */ -.detail-group { - margin-bottom: 20px; -} - -.detail-group label { - display: block; - margin-bottom: 8px; - color: var(--text-secondary); - font-weight: 500; -} - -.editable { - padding: 10px; - border: 1px solid var(--border-color); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-primary); -} - -input.editable { - width: calc(100% - 20px); - box-sizing: border-box; -} - -textarea.editable { - width: calc(100% - 20px); - min-height: 150px; - resize: vertical; - box-sizing: border-box; -} - -.editable:disabled { - background: var(--bg-secondary); - cursor: default; - border-color: transparent; -} - -/* Button Styles */ -.btn { - padding: 10px 20px; - border: none; - border-radius: 6px; - cursor: pointer; - font-weight: 500; - background: var(--bg-primary); - color: var(--text-primary); -} - -.btn.primary { - background: #3b82f6; - color: white; -} - -.btn.active { - background: #3b82f6; - color: white; -} - -/* Status and Priority Styles */ -.status-priority-row { - display: flex; - gap: 20px; -} - -.detail-half { - flex: 1; -} - -.status-priority-group { - display: flex; - gap: 10px; - align-items: center; - margin-right: 15px; -} - -.priority-indicator { - padding: 4px 8px; - border-radius: 4px; - font-weight: bold; -} - -/* Priority Select Styles */ -select[data-field="priority"] { - border-left: 4px solid; -} - -select[data-field="priority"] option { - padding: 10px; -} - -select[data-field="priority"] option[value="1"] { - background-color: var(--priority-1); -} -select[data-field="priority"] option[value="2"] { - background-color: var(--priority-2); -} -select[data-field="priority"] option[value="3"] { - background-color: var(--priority-3); -} -select[data-field="priority"] option[value="4"] { - background-color: var(--priority-4); -} - -select[data-field="priority"][value="1"] { - border-left-color: var(--priority-1); -} -select[data-field="priority"][value="2"] { - border-left-color: var(--priority-2); -} -select[data-field="priority"][value="3"] { - border-left-color: var(--priority-3); -} -select[data-field="priority"][value="4"] { - border-left-color: var(--priority-4); -} - -select[data-field="priority"] option[value="1"]:hover { - background-color: #ffc9c9; - color: var(--text-primary); -} - -select[data-field="priority"] option[value="2"]:hover { - background-color: #ffe0b2; - color: var(--text-primary); -} - -select[data-field="priority"] option[value="3"]:hover { - background-color: #bbdefb; - color: var(--text-primary); -} - -select[data-field="priority"] option[value="4"]:hover { - background-color: #c8e6c9; - color: var(--text-primary); -} - -[data-priority="1"] { border-color: var(--priority-1); } -[data-priority="2"] { border-color: var(--priority-2); } -[data-priority="3"] { border-color: var(--priority-3); } -[data-priority="4"] { border-color: var(--priority-4); } - -/* Comments Section */ -.comments-section { - margin-top: 30px; - padding-top: 20px; - border-top: 1px solid var(--border-color); -} - -.comment-form { - margin-bottom: 20px; -} - -.comment-form textarea { - width: calc(100% - 20px); - min-height: 80px; - margin-bottom: 10px; - padding: 10px; - border-radius: 6px; - border: 1px solid var(--border-color); - background: var(--bg-primary); - color: var(--text-primary); -} - -.comment { - background: var(--bg-primary); - padding: 15px; - border-radius: 6px; - margin-bottom: 10px; -} - -.comment-header { - display: flex; - justify-content: space-between; - margin-bottom: 8px; - font-size: 0.9em; -} - -.comment-user { - font-weight: bold; - color: var(--text-primary); -} - -.comment-date { - color: var(--text-secondary); -} - -.comment-text { - color: var(--text-primary); - line-height: 1.4; -} - -.comment-controls { - display: flex; - justify-content: space-between; - align-items: center; - margin: 10px 0; -} - -/* Comment Tabs */ -.ticket-tabs { - display: flex; - gap: 10px; - margin: 20px 0; -} - -.tab-btn { - padding: 10px 20px; - border: 1px solid var(--border-color); - background: var(--bg-secondary); - border-radius: 6px; - cursor: pointer; - font-weight: 500; -} - -.tab-btn.active { - background: #3b82f6; - color: white; - border-color: #3b82f6; -} - -.tab-content { - display: none; -} - -.tab-content.active { - display: block; -} - -/* Markdown Styles */ -.markdown-preview { - min-height: 100px; - padding: 10px; - border: 1px solid var(--border-color); - border-radius: 6px; - background: var(--bg-primary); -} - -.markdown-preview h1, -.markdown-preview h2, -.markdown-preview h3 { - margin-top: 0; -} - -.markdown-preview code { - background: var(--bg-secondary); - padding: 2px 4px; - border-radius: 4px; -} - -.markdown-preview pre { - background: var(--bg-secondary); - padding: 10px; - border-radius: 6px; - overflow-x: auto; -} - -.markdown-toggles { - display: flex; - gap: 20px; -} - -/* Toggle Switch */ -.switch { - position: relative; - display: inline-block; - width: 50px; - height: 24px; -} - -.switch input { - opacity: 0; - width: 0; - height: 0; -} - -.slider { - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: var(--bg-secondary); - transition: .4s; -} - -.slider:before { - position: absolute; - content: ""; - height: 16px; - width: 16px; - left: 4px; - bottom: 4px; - background-color: white; - transition: .4s; -} - -.slider.round { - border-radius: 24px; -} - -.slider.round:before { - border-radius: 50%; -} - -input:checked + .slider { - background-color: #3b82f6; -} - -input:checked + .slider:before { - transform: translateX(26px); -} - -.switch input:disabled + .slider { - opacity: 0.5; - cursor: not-allowed; -} - -/* Footer */ -.ticket-footer { - margin-top: 30px; - padding-top: 20px; - border-top: 1px solid var(--border-color); -} - -.back-btn { - background: var(--bg-secondary); - color: var(--text-primary); - padding: 10px 20px; - border-radius: 6px; - border: 1px solid var(--border-color); - cursor: pointer; - transition: background-color 0.3s ease; -} - -.back-btn:hover { - background: var(--border-color); -} \ No newline at end of file diff --git a/src_backup/assets/images/favicon.png b/src_backup/assets/images/favicon.png deleted file mode 100644 index 2a27167..0000000 Binary files a/src_backup/assets/images/favicon.png and /dev/null differ diff --git a/src_backup/assets/js/dashboard.js b/src_backup/assets/js/dashboard.js deleted file mode 100644 index b1ebc23..0000000 --- a/src_backup/assets/js/dashboard.js +++ /dev/null @@ -1,487 +0,0 @@ -document.addEventListener('DOMContentLoaded', function() { - // Only initialize filters if we're on the dashboard - if (document.querySelector('table')) { - initSearch(); - initStatusFilter(); - } - - // Keep theme toggle for all pages - initThemeToggle(); - - // Load saved theme preference - const savedTheme = localStorage.getItem('theme') || 'light'; - document.documentElement.setAttribute('data-theme', savedTheme); - - // Add sorting functionality - const tableHeaders = document.querySelectorAll('th'); - tableHeaders.forEach(header => { - header.addEventListener('click', () => { - const table = header.closest('table'); - const index = Array.from(header.parentElement.children).indexOf(header); - sortTable(table, index); - }); - }); - - // Add settings modal functionality - const settingsIcon = document.querySelector('.settings-icon'); - if (settingsIcon) { - settingsIcon.addEventListener('click', function(e) { - e.preventDefault(); - createSettingsModal(); - }); - } -}); - -function sortTable(table, column) { - // Remove existing sort indicators from all headers - const headers = table.querySelectorAll('th'); - headers.forEach(header => { - header.classList.remove('sort-asc', 'sort-desc'); - }); - - const rows = Array.from(table.querySelectorAll('tbody tr')); - - // Determine current sort direction - const currentDirection = table.dataset.sortColumn === column - ? (table.dataset.sortDirection === 'asc' ? 'desc' : 'asc') - : 'asc'; - - // Store current sorting column and direction - table.dataset.sortColumn = column; - table.dataset.sortDirection = currentDirection; - - rows.sort((a, b) => { - const aValue = a.children[column].textContent.trim(); - const bValue = b.children[column].textContent.trim(); - - // Try numeric sorting first, fallback to string comparison - const numA = parseFloat(aValue); - const numB = parseFloat(bValue); - - if (!isNaN(numA) && !isNaN(numB)) { - return currentDirection === 'asc' ? numA - numB : numB - numA; - } - - // String comparison - return currentDirection === 'asc' - ? aValue.localeCompare(bValue) - : bValue.localeCompare(aValue); - }); - - // Add sort indicator to the current header - const currentHeader = headers[column]; - currentHeader.classList.add(currentDirection === 'asc' ? 'sort-asc' : 'sort-desc'); - - // Reorder rows in the tbody - const tbody = table.querySelector('tbody'); - rows.forEach(row => tbody.appendChild(row)); -} - -// Add this to the DOMContentLoaded event listener to persist sorting on page load -document.addEventListener('DOMContentLoaded', function() { - const table = document.querySelector('table'); - if (table) { - const savedSortColumn = localStorage.getItem('sortColumn'); - const savedSortDirection = localStorage.getItem('sortDirection'); - - if (savedSortColumn !== null && savedSortDirection !== null) { - const headers = table.querySelectorAll('th'); - const columnIndex = Array.from(headers).findIndex(header => - header.textContent.toLowerCase().replace(' ', '_') === savedSortColumn - ); - - if (columnIndex !== -1) { - table.dataset.sortColumn = columnIndex; - table.dataset.sortDirection = savedSortDirection; - - const header = headers[columnIndex]; - header.classList.add(savedSortDirection === 'asc' ? 'sort-asc' : 'sort-desc'); - } - } - } -}); - -// Modify the existing event listeners for table headers -document.addEventListener('DOMContentLoaded', function() { - const tableHeaders = document.querySelectorAll('th'); - tableHeaders.forEach((header, index) => { - header.addEventListener('click', () => { - const table = header.closest('table'); - sortTable(table, index); - - // Save sorting preferences - const columnName = header.textContent.toLowerCase().replace(' ', '_'); - localStorage.setItem('sortColumn', columnName); - localStorage.setItem('sortDirection', table.dataset.sortDirection); - }); - }); -}); -function createSettingsModal() { - // Create modal backdrop - const backdrop = document.createElement('div'); - backdrop.className = 'settings-modal-backdrop'; - backdrop.innerHTML = ` -
-
-

Dashboard Settings

- -
-
-
-

Toggle Columns

-
- - - - - - - - -
-
-
-

Rows per Page

- -
-
- -
- `; - - // Add to body - document.body.appendChild(backdrop); - - // Load saved column visibility settings - const savedColumnSettings = JSON.parse(localStorage.getItem('columnVisibility') || '{}'); - const checkboxes = backdrop.querySelectorAll('.column-toggles input'); - checkboxes.forEach(checkbox => { - checkbox.checked = savedColumnSettings[checkbox.value] !== false; - }); - - // Load saved rows per page setting - const savedRowsPerPage = localStorage.getItem('ticketsPerPage') || '5'; - const rowsPerPageSelect = backdrop.querySelector('#rows-per-page'); - rowsPerPageSelect.value = savedRowsPerPage; - - // Close modal events - backdrop.querySelector('.close-modal').addEventListener('click', closeSettingsModal); - backdrop.querySelector('.cancel-settings').addEventListener('click', closeSettingsModal); - backdrop.querySelector('.save-settings').addEventListener('click', saveSettings); - - // Close modal on backdrop click - backdrop.addEventListener('click', (e) => { - if (e.target === backdrop) { - closeSettingsModal(); - } - }); -} - -function closeSettingsModal() { - const backdrop = document.querySelector('.settings-modal-backdrop'); - if (backdrop) { - backdrop.remove(); - } -} - -function saveSettings() { - // Save column visibility - const checkboxes = document.querySelectorAll('.column-toggles input'); - const columnVisibility = {}; - - checkboxes.forEach(checkbox => { - columnVisibility[checkbox.value] = checkbox.checked; - }); - localStorage.setItem('columnVisibility', JSON.stringify(columnVisibility)); - - // Save rows per page - const rowsPerPage = document.querySelector('#rows-per-page').value; - localStorage.setItem('ticketsPerPage', rowsPerPage); - - // Set cookie for PHP to read - document.cookie = `ticketsPerPage=${rowsPerPage}; path=/`; - - // Apply column visibility - applyColumnVisibility(); - - // Reload page to apply pagination changes - window.location.reload(); - - // Close modal - closeSettingsModal(); -} - -function applyColumnVisibility() { - const savedColumnSettings = JSON.parse(localStorage.getItem('columnVisibility') || '{}'); - const table = document.querySelector('table'); - - if (table) { - const headers = table.querySelectorAll('th'); - const rows = table.querySelectorAll('tbody tr'); - - headers.forEach((header, index) => { - const columnValue = header.textContent.toLowerCase().replace(' ', '_'); - const isVisible = savedColumnSettings[columnValue] !== false; - - header.style.display = isVisible ? '' : 'none'; - - rows.forEach(row => { - row.children[index].style.display = isVisible ? '' : 'none'; - }); - }); - } -} - -// Apply column visibility on page load -document.addEventListener('DOMContentLoaded', applyColumnVisibility); -// Dark mode toggle -function initThemeToggle() { - const toggle = document.createElement('button'); - toggle.className = 'theme-toggle'; - toggle.innerHTML = '🌓'; - toggle.onclick = () => { - document.documentElement.setAttribute('data-theme', - document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark' - ); - localStorage.setItem('theme', document.documentElement.getAttribute('data-theme')); - }; - document.body.appendChild(toggle); -} - -// Search functionality -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); -} - -// Filter by status -function initStatusFilter() { - const filter = document.createElement('select'); - filter.innerHTML = ` - - - - `; - filter.className = 'status-filter'; - filter.onchange = (e) => { - const status = e.target.value; - const rows = document.querySelectorAll('tbody tr'); - rows.forEach(row => { - if (!status || row.querySelector('.status-' + status)) { - row.style.display = ''; - } else { - row.style.display = 'none'; - } - }); - }; - document.querySelector('.table-controls .table-actions').prepend(filter); -} - -function sortTable(table, column) { - const headers = table.querySelectorAll('th'); - headers.forEach(header => { - header.classList.remove('sort-asc', 'sort-desc'); - }); - - const rows = Array.from(table.querySelectorAll('tbody tr')); - const currentDirection = table.dataset.sortColumn == column - ? (table.dataset.sortDirection === 'asc' ? 'desc' : 'asc') - : 'asc'; - - table.dataset.sortColumn = column; - table.dataset.sortDirection = currentDirection; - - rows.sort((a, b) => { - const aValue = a.children[column].textContent.trim(); - const bValue = b.children[column].textContent.trim(); - - // Check if this is a date column (Created or Updated) - const headerText = headers[column].textContent.toLowerCase(); - if (headerText === 'created' || headerText === 'updated') { - const dateA = new Date(aValue); - const dateB = new Date(bValue); - return currentDirection === 'asc' ? dateA - dateB : dateB - dateA; - } - - // Existing numeric and string comparison logic - const numA = parseFloat(aValue); - const numB = parseFloat(bValue); - - if (!isNaN(numA) && !isNaN(numB)) { - return currentDirection === 'asc' ? numA - numB : numB - numA; - } - - return currentDirection === 'asc' - ? aValue.localeCompare(bValue) - : bValue.localeCompare(aValue); - }); - - const currentHeader = headers[column]; - currentHeader.classList.add(currentDirection === 'asc' ? 'sort-asc' : 'sort-desc'); - - const tbody = table.querySelector('tbody'); - rows.forEach(row => tbody.appendChild(row)); -} - -// Modify the CSS to ensure arrows are more visible -document.addEventListener('DOMContentLoaded', function() { - const tableHeaders = document.querySelectorAll('th'); - tableHeaders.forEach((header, index) => { - header.style.cursor = 'pointer'; // Make headers look clickable - header.addEventListener('click', () => { - const table = header.closest('table'); - sortTable(table, index); - }); - }); -}); - -function createHamburgerMenu() { - // Create hamburger menu container - const hamburgerMenu = document.createElement('div'); - hamburgerMenu.className = 'hamburger-menu'; - hamburgerMenu.innerHTML = ` -
-
-
-

Filters

-
-

Categories

-
-
-
-

Types

-
-
-
- - -
-
- `; - - // Populate categories and types from data attributes - const categoriesContainer = hamburgerMenu.querySelector('#category-filters'); - const typesContainer = hamburgerMenu.querySelector('#type-filters'); - - const categories = JSON.parse(document.body.dataset.categories || '[]'); - const types = JSON.parse(document.body.dataset.types || '[]'); - - // Create checkboxes for categories - categories.forEach(category => { - const label = document.createElement('label'); - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.value = category; - checkbox.name = 'category'; - label.appendChild(checkbox); - label.appendChild(document.createTextNode(category)); - categoriesContainer.appendChild(label); - }); - - // Create checkboxes for types - types.forEach(type => { - const label = document.createElement('label'); - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.value = type; - checkbox.name = 'type'; - label.appendChild(checkbox); - label.appendChild(document.createTextNode(type)); - typesContainer.appendChild(label); - }); - - // Toggle hamburger menu - const hamburgerIcon = hamburgerMenu.querySelector('.hamburger-icon'); - const hamburgerContent = hamburgerMenu.querySelector('.hamburger-content'); - hamburgerIcon.addEventListener('click', () => { - hamburgerContent.classList.toggle('open'); - document.body.classList.toggle('menu-open'); - }); - - // Apply filters - const applyFiltersBtn = hamburgerMenu.querySelector('#apply-filters'); - applyFiltersBtn.addEventListener('click', () => { - const selectedCategories = Array.from( - categoriesContainer.querySelectorAll('input:checked') - ).map(cb => cb.value); - - const selectedTypes = Array.from( - typesContainer.querySelectorAll('input:checked') - ).map(cb => cb.value); - - // Construct URL with filters - const params = new URLSearchParams(window.location.search); - - if (selectedCategories.length > 0) { - params.set('category', selectedCategories.join(',')); - } else { - params.delete('category'); - } - - if (selectedTypes.length > 0) { - params.set('type', selectedTypes.join(',')); - } else { - params.delete('type'); - } - - // Reload with new filters - window.location.search = params.toString(); - }); - - // Clear filters - const clearFiltersBtn = hamburgerMenu.querySelector('#clear-filters'); - clearFiltersBtn.addEventListener('click', () => { - const params = new URLSearchParams(window.location.search); - params.delete('category'); - params.delete('type'); - window.location.search = params.toString(); - }); - - // Add to body - document.body.appendChild(hamburgerMenu); - - // Close hamburger menu - const closeButton = hamburgerMenu.querySelector('.close-hamburger'); - closeButton.addEventListener('click', () => { - hamburgerContent.classList.remove('open'); - document.body.classList.remove('menu-open'); - }); -} - -// Add to DOMContentLoaded -document.addEventListener('DOMContentLoaded', createHamburgerMenu); diff --git a/src_backup/assets/js/ticket.js b/src_backup/assets/js/ticket.js deleted file mode 100644 index 8a70795..0000000 --- a/src_backup/assets/js/ticket.js +++ /dev/null @@ -1,184 +0,0 @@ -function saveTicket() { - const editables = document.querySelectorAll('.editable'); - const data = {}; - const ticketId = window.location.href.split('id=')[1]; - - editables.forEach(field => { - if (field.dataset.field) { - data[field.dataset.field] = field.value; - } - }); - - fetch('update_ticket.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - ticket_id: ticketId, - ...data - }) - }) - .then(response => response.json()) - .then(data => { - if(data.success) { - const statusDisplay = document.getElementById('statusDisplay'); - statusDisplay.className = `status-${data.status}`; - statusDisplay.textContent = data.status; - } - }); -} - -function toggleEditMode() { - const editButton = document.getElementById('editButton'); - const editables = document.querySelectorAll('.editable'); - const isEditing = editButton.classList.contains('active'); - - if (!isEditing) { - // Enable editing - editButton.textContent = 'Save Changes'; - editButton.classList.add('active'); - editables.forEach(field => { - field.disabled = false; - if (field.classList.contains('title-input')) { - field.focus(); - } - }); - } else { - // Save changes and disable editing - saveTicket(); - editButton.textContent = 'Edit Ticket'; - editButton.classList.remove('active'); - editables.forEach(field => { - field.disabled = true; - }); - } -} -function addComment() { - const commentText = document.getElementById('newComment').value; - const ticketId = window.location.href.split('id=')[1]; - - fetch('add_comment.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - ticket_id: ticketId, - comment_text: commentText - }) - }) - .then(response => response.json()) - .then(data => { - if(data.success) { - // Clear the comment box - document.getElementById('newComment').value = ''; - - // Add new comment to the list - const commentsList = document.querySelector('.comments-list'); - const newComment = ` -
-
- ${data.user_name} - ${data.created_at} -
-
${commentText}
-
- `; - commentsList.insertAdjacentHTML('afterbegin', newComment); - } - }); -} - -function togglePreview() { - const preview = document.getElementById('markdownPreview'); - const textarea = document.getElementById('newComment'); - const isPreviewEnabled = document.getElementById('markdownToggle').checked; - - preview.style.display = isPreviewEnabled ? 'block' : 'none'; - - if (isPreviewEnabled) { - preview.innerHTML = marked.parse(textarea.value); - textarea.addEventListener('input', updatePreview); - } else { - textarea.removeEventListener('input', updatePreview); - } -} - -function updatePreview() { - const preview = document.getElementById('markdownPreview'); - const textarea = document.getElementById('newComment'); - preview.innerHTML = marked.parse(textarea.value); -} - -function toggleMarkdownMode() { - const previewToggle = document.getElementById('markdownToggle'); - const isMasterEnabled = document.getElementById('markdownMaster').checked; - - previewToggle.disabled = !isMasterEnabled; - if (!isMasterEnabled) { - previewToggle.checked = false; - document.getElementById('markdownPreview').style.display = 'none'; - } -} - -function addComment() { - const commentText = document.getElementById('newComment').value; - const isMarkdownEnabled = document.getElementById('markdownMaster').checked; - const ticketId = window.location.href.split('id=')[1]; - - fetch('add_comment.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - ticket_id: ticketId, - comment_text: commentText, - markdown_enabled: isMarkdownEnabled - }) - }) - .then(response => response.json()) - .then(data => { - if(data.success) { - const commentsList = document.querySelector('.comments-list'); - const newCommentHtml = ` -
-
- ${data.user_name} - ${data.created_at} -
-
- ${isMarkdownEnabled ? marked.parse(commentText) : commentText} -
-
- `; - commentsList.insertAdjacentHTML('afterbegin', newCommentHtml); - document.getElementById('newComment').value = ''; - } - }); -} - -document.addEventListener('DOMContentLoaded', function() { - // Show description tab by default - showTab('description'); -}); - -function showTab(tabName) { - // Hide all tab contents - const descriptionTab = document.getElementById('description-tab'); - const commentsTab = document.getElementById('comments-tab'); - - // Hide both tabs - descriptionTab.style.display = 'none'; - commentsTab.style.display = 'none'; - - // Remove active class from all buttons - document.querySelectorAll('.tab-btn').forEach(btn => { - btn.classList.remove('active'); - }); - - // Show selected tab and activate its button - document.getElementById(`${tabName}-tab`).style.display = 'block'; - document.querySelector(`[onclick="showTab('${tabName}')"]`).classList.add('active'); -} diff --git a/src_backup/create_ticket_api.php b/src_backup/create_ticket_api.php deleted file mode 100644 index d956e25..0000000 --- a/src_backup/create_ticket_api.php +++ /dev/null @@ -1,84 +0,0 @@ - false, - 'error' => 'Configuration file not found' - ]); - exit; -} - -$envVars = parse_ini_file($envFile); -if (!$envVars) { - echo json_encode([ - 'success' => false, - 'error' => 'Invalid configuration file' - ]); - exit; -} - -// Database connection with detailed error handling -$conn = new mysqli( - $envVars['REACT_APP_DB_HOST'], - $envVars['REACT_APP_DB_USER'], - $envVars['REACT_APP_DB_PASS'], - $envVars['REACT_APP_DB_NAME'] -); - -if ($conn->connect_error) { - echo json_encode([ - 'success' => false, - 'error' => 'Database connection failed: ' . $conn->connect_error - ]); - exit; -} - -// Get POST data -$data = json_decode(file_get_contents('php://input'), true); - -// Generate ticket ID (9-digit format with leading zeros) -$ticket_id = sprintf('%09d', mt_rand(1, 999999999)); - -// Prepare insert query -$sql = "INSERT INTO tickets (ticket_id, title, description, status, priority, category, type) - VALUES (?, ?, ?, ?, ?, ?, ?)"; - -$stmt = $conn->prepare($sql); -// First, store all values in variables -$title = $data['title']; -$description = $data['description']; -$status = $data['status'] ?? 'Open'; -$priority = $data['priority'] ?? '4'; -$category = $data['category'] ?? 'General'; -$type = $data['type'] ?? 'Issue'; - -// Then use the variables in bind_param -$stmt->bind_param( - "sssssss", - $ticket_id, - $title, - $description, - $status, - $priority, - $category, - $type -); - -if ($stmt->execute()) { - echo json_encode([ - 'success' => true, - 'ticket_id' => $ticket_id, - 'message' => 'Ticket created successfully' - ]); -} else { - echo json_encode([ - 'success' => false, - 'error' => $conn->error - ]); -} - -$stmt->close(); -$conn->close(); diff --git a/src_backup/dashboard.php b/src_backup/dashboard.php deleted file mode 100755 index 4c29e5c..0000000 --- a/src_backup/dashboard.php +++ /dev/null @@ -1,149 +0,0 @@ -connect_error) { - die("Connection failed: " . $conn->connect_error); -} - -// Pagination settings from localStorage or defaults -$page = isset($_GET['page']) ? (int)$_GET['page'] : 1; -$limit = isset($_COOKIE['ticketsPerPage']) ? (int)$_COOKIE['ticketsPerPage'] : 15; -$defaultSortColumn = isset($_COOKIE['defaultSortColumn']) ? $_COOKIE['defaultSortColumn'] : 'ticket_id'; -$sortDirection = isset($_COOKIE['sortDirection']) ? $_COOKIE['sortDirection'] : 'desc'; -$offset = ($page - 1) * $limit; - -// Get total number of tickets -$totalTicketsQuery = "SELECT COUNT(*) as total FROM tickets"; -$totalTicketsResult = $conn->query($totalTicketsQuery); -$totalTickets = $totalTicketsResult->fetch_assoc()['total']; -$totalPages = ceil($totalTickets / $limit); - -// Modify SQL to use these settings -$sql = "SELECT * FROM tickets ORDER BY $defaultSortColumn $sortDirection LIMIT $limit OFFSET $offset"; -$result = $conn->query($sql); -?> - - - - - - - Ticket Dashboard - - - - - -
-

Tinker Tickets

- -
- -
-
- Total Tickets: -
-
- -
- - - - -
-
-
- - - - - - - - - - - - - - - - num_rows > 0) { - while($row = $result->fetch_assoc()) { - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - } else { - echo ""; - } - ?> - -
Ticket IDPriorityTitleCategoryTypeStatusCreatedUpdated
{$row['ticket_id']}{$row['priority']}{$row['title']}{$row['category']}{$row['type']}{$row['status']}" . date('Y-m-d H:i', strtotime($row['created_at'])) . "" . date('Y-m-d H:i', strtotime($row['updated_at'])) . "
No tickets found
- - close(); ?> - - - - diff --git a/src_backup/logo.svg b/src_backup/logo.svg deleted file mode 100755 index 9dfc1c0..0000000 --- a/src_backup/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src_backup/new_ticket.php b/src_backup/new_ticket.php deleted file mode 100644 index 3f5ef8d..0000000 --- a/src_backup/new_ticket.php +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - Create New Ticket - - - - - - -
-
-

Create New Ticket

-
- -
-
- - -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - -
- -
- - -
-
-
- - - - diff --git a/src_backup/ticket.php b/src_backup/ticket.php deleted file mode 100644 index eaaceb3..0000000 --- a/src_backup/ticket.php +++ /dev/null @@ -1,196 +0,0 @@ -prepare($sql); -$stmt->bind_param("i", $ticket_id); -$stmt->execute(); -$result = $stmt->get_result(); -$ticket = $result->fetch_assoc(); -?> - - - - - - - Ticket #<?php echo $ticket_id; ?> - - - - - - - - -
"> -
-

" data-field="title" disabled>

-
-
UUID
-
-
- "> - ">P -
- -
-
-
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
- -
-
- - -
-
- -
-
-

Comments

-
- -
-
-
- - Enable Markdown -
-
- - Preview Markdown -
-
- -
- -
-
-
- prepare($commentsSql); - $stmt->bind_param("s", $ticket_id); - $stmt->execute(); - $comments = $stmt->get_result(); - - while($comment = $comments->fetch_assoc()) { - echo "
"; - echo "
"; - echo "{$comment['user_name']}"; - echo "" . date('M d, Y H:i', strtotime($comment['created_at'])) . ""; - echo "
"; - echo "
"; - if ($comment['markdown_enabled']) { - echo ""; - } else { - echo htmlspecialchars($comment['comment_text']); - } - echo "
"; - echo "
"; - } - ?> -
-
-
- -
- - diff --git a/src_backup/update_ticket.php b/src_backup/update_ticket.php deleted file mode 100644 index 49dd054..0000000 --- a/src_backup/update_ticket.php +++ /dev/null @@ -1,56 +0,0 @@ -prepare($sql); -$stmt->bind_param( - "sisssss", - $data['title'], - $data['priority'], - $data['status'], - $data['description'], - $data['category'], - $data['type'], - $data['ticket_id'] -); - -// After successful update -if ($stmt->execute()) { - header('Content-Type: application/json'); - echo json_encode([ - 'success' => true, - 'status' => $data['status'] // Send back the new status - ]); -} else { - header('Content-Type: application/json'); - echo json_encode([ - 'success' => false, - 'error' => $conn->error - ]); -} - -$stmt->close(); -$conn->close(); diff --git a/src/ticket.php b/ticket.php similarity index 100% rename from src/ticket.php rename to ticket.php diff --git a/src/update_ticket.php b/update_ticket.php similarity index 100% rename from src/update_ticket.php rename to update_ticket.php