File size: 10,352 Bytes
b8dbc9f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
// Main JavaScript functionality for Ticket Collection System

document.addEventListener('DOMContentLoaded', function() {
    initializeAdmin();
});

// Initialize admin dashboard functionality
function initializeAdmin() {
    if (window.location.pathname === '/admin') {
        initializeTableFeatures();
        initializeSearch();
        initializeFilters();
        updateLastUpdated();
    }
}

// Initialize table sorting and filtering features
function initializeTableFeatures() {
    const table = document.getElementById('ticketsTable');
    if (!table) return;

    // Store original table data for filtering
    window.originalTableData = Array.from(table.querySelectorAll('tbody tr'));
    updateShowingCount();
}

// Table sorting functionality
let sortDirection = {};
function sortTable(columnIndex) {
    const table = document.getElementById('ticketsTable');
    const tbody = table.querySelector('tbody');
    const rows = Array.from(tbody.querySelectorAll('tr'));
    
    // Determine sort direction
    const currentDir = sortDirection[columnIndex] || 'asc';
    const newDir = currentDir === 'asc' ? 'desc' : 'asc';
    sortDirection[columnIndex] = newDir;
    
    // Update sort icons
    updateSortIcons(columnIndex, newDir);
    
    // Sort rows
    rows.sort((a, b) => {
        const aText = a.cells[columnIndex].textContent.trim();
        const bText = b.cells[columnIndex].textContent.trim();
        
        // Handle numeric columns
        if (columnIndex === 3) { // Tickets column
            const aNum = parseInt(aText) || 0;
            const bNum = parseInt(bText) || 0;
            return newDir === 'asc' ? aNum - bNum : bNum - aNum;
        }
        
        // Handle date columns
        if (columnIndex === 7) { // Timestamp column
            const aDate = new Date(aText);
            const bDate = new Date(bText);
            return newDir === 'asc' ? aDate - bDate : bDate - aDate;
        }
        
        // Handle text columns
        const comparison = aText.localeCompare(bText);
        return newDir === 'asc' ? comparison : -comparison;
    });
    
    // Rebuild table
    rows.forEach(row => tbody.appendChild(row));
    updateShowingCount();
}

// Update sort direction icons
function updateSortIcons(activeColumn, direction) {
    const headers = document.querySelectorAll('#ticketsTable thead th');
    headers.forEach((header, index) => {
        const icon = header.querySelector('i.fa-sort, i.fa-sort-up, i.fa-sort-down');
        if (icon) {
            if (index === activeColumn) {
                icon.className = direction === 'asc' ? 'fas fa-sort-up' : 'fas fa-sort-down';
            } else {
                icon.className = 'fas fa-sort';
            }
        }
    });
}

// Search functionality
function initializeSearch() {
    const searchInput = document.getElementById('searchInput');
    if (!searchInput) return;
    
    searchInput.addEventListener('input', function() {
        const searchTerm = this.value.toLowerCase();
        filterTable();
    });
}

// Filter functionality
function initializeFilters() {
    const countryFilter = document.getElementById('countryFilter');
    if (!countryFilter) return;
    
    countryFilter.addEventListener('change', function() {
        filterTable();
    });
}

// Combined filter and search function
function filterTable() {
    if (!window.originalTableData) return;
    
    const searchTerm = document.getElementById('searchInput')?.value.toLowerCase() || '';
    const countryFilter = document.getElementById('countryFilter')?.value || '';
    const tbody = document.querySelector('#ticketsTable tbody');
    
    // Clear current table
    tbody.innerHTML = '';
    
    let visibleCount = 0;
    
    window.originalTableData.forEach(row => {
        const rowText = row.textContent.toLowerCase();
        const countryCell = row.cells[5].textContent.trim();
        
        const matchesSearch = searchTerm === '' || rowText.includes(searchTerm);
        const matchesCountry = countryFilter === '' || countryCell === countryFilter;
        
        if (matchesSearch && matchesCountry) {
            tbody.appendChild(row.cloneNode(true));
            visibleCount++;
        }
    });
    
    // Update showing count
    document.getElementById('showingCount').textContent = visibleCount;
    
    // Show empty state if no results
    if (visibleCount === 0) {
        showEmptySearchResults();
    }
}

// Show empty search results
function showEmptySearchResults() {
    const tbody = document.querySelector('#ticketsTable tbody');
    const emptyRow = document.createElement('tr');
    emptyRow.innerHTML = `
        <td colspan="9" class="text-center py-4">
            <i class="fas fa-search fa-2x text-muted mb-2"></i>
            <p class="text-muted mb-0">No tickets match your search criteria</p>
        </td>
    `;
    tbody.appendChild(emptyRow);
}

// Update showing count
function updateShowingCount() {
    const tbody = document.querySelector('#ticketsTable tbody');
    if (!tbody) return;
    
    const visibleRows = tbody.querySelectorAll('tr').length;
    const showingElement = document.getElementById('showingCount');
    if (showingElement) {
        showingElement.textContent = visibleRows;
    }
}

// Refresh data function
function refreshData() {
    const refreshBtn = document.querySelector('button[onclick="refreshData()"]');
    if (refreshBtn) {
        refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i> Refreshing...';
        refreshBtn.disabled = true;
    }
    
    // Simulate refresh delay
    setTimeout(() => {
        location.reload();
    }, 500);
}

// Export visible data function
function exportVisible() {
    const table = document.getElementById('ticketsTable');
    if (!table) return;
    
    const visibleRows = Array.from(table.querySelectorAll('tbody tr'));
    if (visibleRows.length === 0) {
        alert('No data to export');
        return;
    }
    
    // Create CSV content
    let csvContent = 'Email,Phone,Name,Tickets,Ticket Number,Country,Region,Timestamp\n';
    
    visibleRows.forEach(row => {
        const cells = Array.from(row.cells).slice(0, 8); // Exclude actions column
        const rowData = cells.map(cell => {
            let text = cell.textContent.trim();
            // Clean up badge text
            if (cell.querySelector('.badge')) {
                text = cell.querySelector('.badge').textContent.trim();
            }
            // Clean up code text
            if (cell.querySelector('code')) {
                text = cell.querySelector('code').textContent.trim();
            }
            // Escape quotes and commas
            if (text.includes(',') || text.includes('"')) {
                text = '"' + text.replace(/"/g, '""') + '"';
            }
            return text;
        });
        csvContent += rowData.join(',') + '\n';
    });
    
    // Download CSV
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    if (link.download !== undefined) {
        const url = URL.createObjectURL(blob);
        link.setAttribute('href', url);
        link.setAttribute('download', `ticket_data_filtered_${new Date().toISOString().split('T')[0]}.csv`);
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }
}

// Update last updated timestamp
function updateLastUpdated() {
    const element = document.getElementById('lastUpdated');
    if (element) {
        const now = new Date();
        element.textContent = now.toISOString().slice(0, 19).replace('T', ' ');
    }
}

// Utility function to show notifications
function showNotification(message, type = 'info') {
    const alertDiv = document.createElement('div');
    alertDiv.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
    alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
    alertDiv.innerHTML = `
        ${message}
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    `;
    
    document.body.appendChild(alertDiv);
    
    // Auto-remove after 5 seconds
    setTimeout(() => {
        if (alertDiv.parentNode) {
            alertDiv.parentNode.removeChild(alertDiv);
        }
    }, 5000);
}

// Handle form submissions with loading states
document.addEventListener('submit', function(e) {
    const form = e.target;
    if (form.tagName === 'FORM') {
        const submitBtn = form.querySelector('button[type="submit"]');
        if (submitBtn) {
            submitBtn.disabled = true;
            const originalHtml = submitBtn.innerHTML;
            submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i> Processing...';
            
            // Re-enable after 3 seconds (fallback)
            setTimeout(() => {
                submitBtn.disabled = false;
                submitBtn.innerHTML = originalHtml;
            }, 3000);
        }
    }
});

// Add keyboard shortcuts
document.addEventListener('keydown', function(e) {
    // Ctrl+R or F5 for refresh
    if ((e.ctrlKey && e.key === 'r') || e.key === 'F5') {
        if (window.location.pathname === '/admin') {
            e.preventDefault();
            refreshData();
        }
    }
    
    // Ctrl+F for search focus
    if (e.ctrlKey && e.key === 'f') {
        const searchInput = document.getElementById('searchInput');
        if (searchInput) {
            e.preventDefault();
            searchInput.focus();
            searchInput.select();
        }
    }
    
    // Escape to clear search
    if (e.key === 'Escape') {
        const searchInput = document.getElementById('searchInput');
        if (searchInput && searchInput.value) {
            searchInput.value = '';
            filterTable();
        }
    }
});

// Add smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function (e) {
        e.preventDefault();
        const target = document.querySelector(this.getAttribute('href'));
        if (target) {
            target.scrollIntoView({
                behavior: 'smooth',
                block: 'start'
            });
        }
    });
});