From 0afb2c0046b55c123eafb4ab9ee77efa68d12463 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sat, 06 Jun 2026 17:15:31 +0000
Subject: [PATCH] =Starting the Favourites.js setup, converting previous Northeh stuff to new Registrar, fixing up Square.php integration to match

---
 assets/js/admin.js |  394 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 306 insertions(+), 88 deletions(-)

diff --git a/assets/js/admin.js b/assets/js/admin.js
index 75bbd7f..7230dc8 100644
--- a/assets/js/admin.js
+++ b/assets/js/admin.js
@@ -1,102 +1,320 @@
 document.addEventListener("DOMContentLoaded", function(e) {
-	console.log('working');
-    // Tabs functionality for settings pages
-    let tabs = document.querySelectorAll('.jvb-settings-tab');
+	// Tabs functionality for settings pages
+	let tabs = document.querySelectorAll('.jvb-settings-tab');
 
-    tabs.forEach(tab => {
-        tab.addEventListener('click', (e) => {
-            removeActiveTab(tabs);
-            tab.classList.add('active');
-            setActiveSection(tab);
-        });
-    });
+	tabs.forEach(tab => {
+		tab.addEventListener('click', (e) => {
+			removeActiveTab(tabs);
+			tab.classList.add('active');
+			setActiveSection(tab);
+		});
+	});
 
-    // Check for hash in URL and activate corresponding tab
-    if (window.location.hash) {
-        var hash = window.location.hash.substring(1);
-        document.querySelector('.jvb-settings-tab[data-tab="' + hash + '"]')?.click();
-    } else {
-        // Activate first tab by default
-        document.querySelector('.jvb-settings-tab')?.click();
-    }
+	// Check for hash in URL and activate corresponding tab
+	if (window.location.hash) {
+		var hash = window.location.hash.substring(1);
+		document.querySelector('.jvb-settings-tab[data-tab="' + hash + '"]')?.click();
+	} else {
+		// Activate first tab by default
+		document.querySelector('.jvb-settings-tab')?.click();
+	}
 
-    let confirm = document.querySelector('.jvb-confirm-action');
-    if (confirm) {
-        confirm.addEventListener('click', (e) => {
-            if (!window.confirm(confirm.dataset.confirm || 'Are you sure?')) {
-                e.preventDefault();
-                return false;
-            }
-        });
-    }
+	let confirm = document.querySelector('.jvb-confirm-action');
+	if (confirm) {
+		confirm.addEventListener('click', (e) => {
+			if (!window.confirm(confirm.dataset.confirm || 'Are you sure?')) {
+				e.preventDefault();
+				return false;
+			}
+		});
+	}
 
-    // Admin action buttons
-    document.querySelectorAll('a[data-action]').forEach(action => {
-        action.addEventListener('click', (e) => {
-            e.preventDefault();
-            let loader = action.querySelector('.loader');
-            loader.classList.add('loading');
-
-            let a = action.dataset.action;
-
-            fetch(jvbSettings.api, {
-                method: 'POST',
-                headers: {
-                    'Content-Type': 'application/json',
-                    'X-WP-Nonce': jvbSettings.nonce,
-                    'action_nonce': jvbSettings.action
-                },
-                body: JSON.stringify({
-                    action: a
-                })
-            })
-                .then(response => {
-                    if (!response.ok) {
-                        throw new Error('Network response was not ok');
-                    }
-                    return response.json();
-                })
-                .then(data => {
-                    if (data.success === true) {
-                        loader.classList.remove('loading');
-                        loader.classList.add('loaded');
-                        setTimeout(() => {
-                            loader.classList.remove('loaded');
-                        }, 3000);
-                    } else {
-                        throw new Error(data.message || 'Action failed');
-                    }
-                })
-                .catch(error => {
-                    console.error('Error:', error);
-                    loader.classList.remove('loading');
-                    // You might want to add an error state class here
-                });
-        });
-    });
+	// Initialize admin actions
+	initAdminActions();
+	initCacheActions();
+	initIconActions();
 });
 
 function removeActiveTab(tabs) {
-    let active = document.querySelectorAll('.active');
-    active.forEach(tab => {
-        tab.classList.remove('active');
-        if (tab.dataset.tab) {
-            setActiveSection(tab, false);
-            window.location.hash = tab.dataset.tab;
-        }
-    });
+	let active = document.querySelectorAll('.active');
+	active.forEach(tab => {
+		tab.classList.remove('active');
+		if (tab.dataset.tab) {
+			setActiveSection(tab, false);
+			window.location.hash = tab.dataset.tab;
+		}
+	});
 }
 
 function setActiveSection(tab, set = true) {
-    let id = tab.dataset.tab;
-    if (!id) return;
+	let id = tab.dataset.tab;
+	if (!id) return;
 
-    let section = document.querySelector('#' + id);
-    if (!section) return;
+	let section = document.querySelector('#' + id);
+	if (!section) return;
 
-    if (set) {
-        section.classList.add('active');
-    } else {
-        section.classList.remove('active');
-    }
+	if (set) {
+		section.classList.add('active');
+	} else {
+		section.classList.remove('active');
+	}
+}
+
+/**
+ * Initialize admin action buttons (dashboard quick actions)
+ */
+function initAdminActions() {
+	document.querySelectorAll('a[data-action]').forEach(action => {
+		action.addEventListener('click', (e) => {
+			e.preventDefault();
+			let loader = action.querySelector('.loader');
+			loader.classList.add('loading');
+
+			let a = action.dataset.action;
+
+			makeAdminRequest('admin-action', { action: a })
+				.then(data => {
+					if (data.success === true) {
+						loader.classList.remove('loading');
+						loader.classList.add('loaded');
+						setTimeout(() => {
+							loader.classList.remove('loaded');
+						}, 3000);
+					} else {
+						throw new Error(data.message || 'Action failed');
+					}
+				})
+				.catch(error => {
+					console.error('Error:', error);
+					loader.classList.remove('loading');
+					alert('Error: ' + error.message);
+				});
+		});
+	});
+}
+
+/**
+ * Initialize cache management actions
+ */
+function initCacheActions() {
+	const flushAllBtn = document.querySelector('[data-cache-action="flush-all"]');
+	if (flushAllBtn) {
+		flushAllBtn.addEventListener('click', function() {
+			const originalText = this.innerHTML;
+			this.disabled = true;
+			this.innerHTML = 'Flushing...';
+
+			makeAdminRequest('admin-cache', { action: 'flush-all' })
+				.then(data => handleActionResponse(data, this, originalText))
+				.catch(error => handleActionError(error, this, originalText));
+		});
+	}
+
+	document.querySelectorAll('[data-cache-action="flush-cache"]').forEach(btn => {
+		btn.addEventListener('click', function() {
+			const group = this.getAttribute('data-group');
+			const originalText = this.innerHTML;
+			this.disabled = true;
+			this.innerHTML = 'Flushing...';
+
+			makeAdminRequest('admin-cache', { action: 'flush-cache', group: group })
+				.then(data => handleActionResponse(data, this, originalText))
+				.catch(error => handleActionError(error, this, originalText));
+		});
+	});
+}
+
+/**
+ * Initialize icon management actions
+ */
+function initIconActions() {
+	const currentSource = document.getElementById('icon-source-select')?.value || 'icons';
+
+	// Select all checkbox
+	const selectAll = document.getElementById('select-all-versions');
+	if (selectAll) {
+		selectAll.addEventListener('change', function() {
+			document.querySelectorAll('.version-checkbox').forEach(checkbox => {
+				checkbox.checked = this.checked;
+				checkbox.dispatchEvent(new Event('change'));
+			});
+		});
+	}
+
+	// Enable/disable merge button based on selection
+	document.querySelectorAll('.version-checkbox').forEach(checkbox => {
+		checkbox.addEventListener('change', updateMergeButtonState);
+	});
+
+	// Toggle icon list view
+	document.querySelectorAll('.view-icon-list-btn').forEach(btn => {
+		btn.addEventListener('click', function() {
+			const timestamp = this.getAttribute('data-timestamp');
+			const row = document.getElementById('icon-list-' + timestamp);
+			if (row) {
+				row.style.display = row.style.display === 'none' ? '' : 'none';
+				this.textContent = row.style.display === 'none' ? '(view)' : '(hide)';
+			}
+		});
+	});
+
+	// Force refresh button
+	const refreshBtn = document.querySelector('[data-icon-action="refresh-icons"]');
+	if (refreshBtn) {
+		refreshBtn.addEventListener('click', function() {
+			const originalText = this.innerHTML;
+			this.disabled = true;
+			this.innerHTML = 'Regenerating...';
+
+			const source = this.getAttribute('data-source') || currentSource;
+			makeAdminRequest('admin-icons', { action: 'refresh-icons', source: source })
+				.then(data => {
+					handleActionResponse(data, this, originalText);
+				})
+				.catch(error => {
+					handleActionError(error, this, originalText);
+				});
+
+		});
+	}
+
+	// Merge versions button
+	const mergeBtn = document.getElementById('merge-versions-btn');
+	if (mergeBtn) {
+		mergeBtn.addEventListener('click', function() {
+			const checkboxes = document.querySelectorAll('.version-checkbox:checked');
+			const timestamps = Array.from(checkboxes).map(cb => parseInt(cb.value));
+
+			if (timestamps.length < 2) {
+				alert('Please select at least 2 versions to merge');
+				return;
+			}
+
+			if (confirm(`Merge ${timestamps.length} versions? This will create a new CSS file with all unique icons.`)) {
+				const originalText = this.innerHTML;
+				this.disabled = true;
+				this.innerHTML = 'Merging...';
+
+				const source = this.getAttribute('data-source') || currentSource;
+				makeAdminRequest('admin-icons', {
+					action: 'merge-icon-versions',
+					source: source,
+					timestamps: timestamps
+				})
+					.then(data => {
+						handleActionResponse(data, this, originalText);
+					})
+					.catch(error => {
+						handleActionError(error, this, originalText);
+					});
+			}
+		});
+	}
+
+	// Restore version buttons
+	document.querySelectorAll('[data-icon-action="restore-icon-version"]').forEach(btn => {
+		btn.addEventListener('click', function() {
+			const timestamp = parseInt(this.getAttribute('data-timestamp'));
+			const source = this.getAttribute('data-source') || currentSource;
+
+			if (confirm('Restore this icon version? This will reload the page.')) {
+				const originalText = this.innerHTML;
+				this.disabled = true;
+				this.innerHTML = 'Restoring...';
+
+				makeAdminRequest('admin-icons', {
+					action: 'restore-icon-version',
+					source: source,
+					timestamp: timestamp
+				})
+					.then(data => {
+						handleActionResponse(data, this, originalText);
+					})
+					.catch(error => {
+						handleActionError(error, this, originalText);
+					});
+			}
+		});
+	});
+}
+
+/**
+ * Update merge button state based on selected checkboxes
+ */
+function updateMergeButtonState() {
+	const checkedCount = document.querySelectorAll('.version-checkbox:checked').length;
+	const mergeBtn = document.getElementById('merge-versions-btn');
+	if (mergeBtn) {
+		mergeBtn.disabled = checkedCount < 2;
+	}
+}
+
+/**
+ * Make an admin API request
+ * @param {string} endpoint - The API endpoint (without 'jvb/v1/')
+ * @param {object} data - The data to send
+ * @returns {Promise}
+ */
+function makeAdminRequest(endpoint, data = {}) {
+	if (typeof jvbSettings === 'undefined') {
+		console.error('jvbSettings is not defined');
+		return Promise.reject(new Error('jvbSettings is not defined. Scripts may not be loaded correctly.'));
+	}
+
+	console.log('Making request to:', jvbSettings.api + endpoint, 'with data:', data);
+
+	return fetch(jvbSettings.api + endpoint, {
+		method: 'POST',
+		headers: {
+			'Content-Type': 'application/json',
+			'X-WP-Nonce': jvbSettings.nonce,
+			'X-Action-Nonce': jvbSettings.action
+		},
+		body: JSON.stringify(data)
+	})
+		.then(response => {
+			console.log('Response status:', response.status);
+			if (!response.ok) {
+				return response.json().then(err => {
+					throw new Error(err.message || 'Network response was not ok');
+				});
+			}
+			return response.json();
+		})
+		.then(data => {
+			console.log('Response data:', data);
+			return data;
+		});
+}
+
+/**
+ * Handle successful action response
+ */
+function handleActionResponse(data, button = null, originalText = null) {
+	if (!data.success) {
+		throw new Error(data.message || 'Unknown error');
+	}
+
+	if (button && originalText) {
+		button.innerHTML = '✓ Success!';
+		setTimeout(() => {
+			button.disabled = false;
+			button.innerHTML = originalText;
+		}, 1500);
+	}
+}
+
+/**
+ * Handle action error
+ */
+function handleActionError(error, button = null, originalText = null) {
+	console.error('Error:', error);
+
+	if (button && originalText) {
+		button.innerHTML = '✗ ' + (error.message || 'Error');
+		setTimeout(() => {
+			button.disabled = false;
+			button.innerHTML = originalText;
+		}, 2000);
+	}
 }

--
Gitblit v1.10.0