-
@@ -361,27 +430,42 @@ class ModernContactsManager {
this.showBulkDeleteConfirmation();
});
- const contactsTable = document.querySelector('.table-responsive table');
- if (contactsTable) {
- contactsTable.addEventListener('change', (e) => {
- if (e.target.id === 'contacts-select-all') {
- const checked = e.target.checked;
+ const listPanel = document.getElementById('contacts-list-panel');
+ if (listPanel) {
+ listPanel.addEventListener('change', (e) => {
+ const t = e.target;
+ if (t.id === 'contacts-select-all' || t.id === 'contacts-select-all-mobile') {
+ const checked = t.checked;
this.filteredData.forEach(c => {
if (checked) this.selectedContactIds.add(c.user_id);
else this.selectedContactIds.delete(c.user_id);
});
- contactsTable.querySelectorAll('.contact-row-checkbox').forEach(cb => cb.checked = checked);
+ listPanel.querySelectorAll('.contact-row-checkbox').forEach(cb => { cb.checked = checked; });
this.updateBulkDeleteButton();
this.updateSelectAllCheckbox();
- } else if (e.target.classList.contains('contact-row-checkbox')) {
- const userId = e.target.dataset.userId;
- if (e.target.checked) this.selectedContactIds.add(userId);
+ } else if (t.classList.contains('contact-row-checkbox')) {
+ const userId = t.dataset.userId;
+ if (t.checked) this.selectedContactIds.add(userId);
else this.selectedContactIds.delete(userId);
this.updateBulkDeleteButton();
this.updateSelectAllCheckbox();
}
});
}
+
+ const mobileSort = document.getElementById('contacts-mobile-sort');
+ if (mobileSort) {
+ mobileSort.addEventListener('change', () => {
+ const v = mobileSort.value.split('|');
+ if (v.length === 2) {
+ this.sortColumn = v[0];
+ this.sortDirection = v[1];
+ this.applySort();
+ this.renderContactsData();
+ this.updateSortIcons();
+ }
+ });
+ }
// Add click handlers for sortable columns
document.querySelectorAll('.sortable').forEach(header => {
@@ -495,6 +579,16 @@ class ModernContactsManager {
icon.className = this.sortDirection === 'asc' ? 'fas fa-sort-up' : 'fas fa-sort-down';
}
}
+ this.syncMobileSortSelect();
+ }
+
+ syncMobileSortSelect() {
+ const sel = document.getElementById('contacts-mobile-sort');
+ if (!sel) return;
+ const val = `${this.sortColumn}|${this.sortDirection}`;
+ if ([...sel.options].some(o => o.value === val)) {
+ sel.value = val;
+ }
}
applySearch() {
@@ -527,12 +621,67 @@ class ModernContactsManager {
});
}
+ renderContactCardHtml(contact) {
+ const uidEsc = this.escapeHtml(contact.user_id);
+ const uidJs = contact.user_id.replace(/'/g, "\\'");
+ const nameJs = (contact.username || 'Unknown').replace(/'/g, "\\'");
+ const checked = this.selectedContactIds.has(contact.user_id) ? 'checked' : '';
+ const hasGeo = !!(contact.latitude && contact.longitude && contact.latitude !== 0 && contact.longitude !== 0);
+ const starLabel = contact.is_starred ? 'Unstar contact' : 'Star contact';
+ const geoMenuItem = hasGeo
+ ? `
`
+ : '';
+ return `
+
+ `;
+ }
+
renderContactsData() {
const tbody = document.getElementById('contacts-table-body');
-
+ const mobileStack = document.getElementById('contacts-mobile-stack');
+
if (this.filteredData.length === 0) {
- const message = this.searchTerm ?
- `No contacts match "${this.searchTerm}"` :
+ const message = this.searchTerm ?
+ `No contacts match "${this.searchTerm}"` :
'No contacts data available';
tbody.innerHTML = `
@@ -541,11 +690,14 @@ class ModernContactsManager {
`;
+ if (mobileStack) {
+ mobileStack.innerHTML = `
${message}
`;
+ }
this.updateBulkDeleteButton();
this.updateSelectAllCheckbox();
return;
}
-
+
tbody.innerHTML = this.filteredData.map(contact => `
|
@@ -585,7 +737,11 @@ class ModernContactsManager {
|
`).join('');
-
+
+ if (mobileStack) {
+ mobileStack.innerHTML = this.filteredData.map(contact => this.renderContactCardHtml(contact)).join('');
+ }
+
// Setup path tooltips after rendering
this.setupPathTooltips();
this.updateBulkDeleteButton();
@@ -609,12 +765,17 @@ class ModernContactsManager {
updateSelectAllCheckbox() {
const selectAll = document.getElementById('contacts-select-all');
- if (!selectAll) return;
+ const selectAllMobile = document.getElementById('contacts-select-all-mobile');
const visibleIds = new Set(this.filteredData.map(c => c.user_id));
const allSelected = visibleIds.size > 0 && [...visibleIds].every(id => this.selectedContactIds.has(id));
const someSelected = [...visibleIds].some(id => this.selectedContactIds.has(id));
- selectAll.checked = allSelected;
- selectAll.indeterminate = someSelected && !allSelected;
+ const sync = (el) => {
+ if (!el) return;
+ el.checked = allSelected;
+ el.indeterminate = someSelected && !allSelected;
+ };
+ sync(selectAll);
+ sync(selectAllMobile);
}
updateStatistics() {