From 2b90e3f5676b996917146515989557a167661681 Mon Sep 17 00:00:00 2001
From: Rim <info@rimmyscorner.com>
Date: Tue, 1 Apr 2025 21:35:28 -0400
Subject: [PATCH] refactor: migrate frontend code -- backend.js -> frontend.js

---
 app.js             |   1 +
 src/index.html     |   1 +
 src/js/backend.js  | 411 +++------------------------------------------
 src/js/frontend.js | 380 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 407 insertions(+), 386 deletions(-)
 create mode 100644 src/js/frontend.js

diff --git a/app.js b/app.js
index 47aaeed..64685b3 100644
--- a/app.js
+++ b/app.js
@@ -895,6 +895,7 @@ app.post("/api/search", async (req, res) => {
   }
 });
 
+
 // Improved logging endpoint
 app.post('/api/log', (req, res) => {
   const clientIP = req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress;
diff --git a/src/index.html b/src/index.html
index 11ef4cb..9a4d62a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -32,6 +32,7 @@
   <link rel="stylesheet" type="text/css" href="./src/css/styles.css">
   <link rel="icon" type="image/x-icon" href="./src/images/favicon.ico">
   <script src="./src/js/backend.js" defer></script>
+  <script src="./src/js/frontend.js" defer></script>
   <script src="./src/js/localStorage.js" defer></script>
 </head>
 
diff --git a/src/js/backend.js b/src/js/backend.js
index a0aa20a..d252000 100644
--- a/src/js/backend.js
+++ b/src/js/backend.js
@@ -1,184 +1,20 @@
-let tutorialDismissed = false;
-let currentData = null;
-let outputFormat = "json";
+// Export the functions that frontend.js needs to call
+window.backendAPI = {
+  fetchData,
+  jsonToYAML,
+  formatDuration,
+  formatEpochTime,
+  processTimestamps
+};
+
+window.appState = {
+  currentData: null,
+  outputFormat: "json",
+  tutorialDismissed: false
+};
 
-// Initialize once DOM is loaded
 document.addEventListener("DOMContentLoaded", function() {
-  initTabSwitching();
-  addEnterKeyListeners();
-  setupDownloadButton();
-  setupFormatSelector();
-  setupProcessingOptions();
-  setupTimeOptions();
-  addSyncListeners();
-});
-
-// Tab switching logic
-function initTabSwitching() {
-  document.querySelectorAll(".tab").forEach((tab) => {
-    tab.addEventListener("click", () => {
-      document
-        .querySelectorAll(".tab")
-        .forEach((t) => t.classList.remove("active"));
-      document
-        .querySelectorAll(".tab-content")
-        .forEach((c) => c.classList.remove("active"));
-
-      tab.classList.add("active");
-      const tabId = tab.getAttribute("data-tab");
-      document.getElementById(`${tabId}-tab`).classList.add("active");
-    });
-  });
-}
-
-// Setup processing options (sanitize/replace)
-function setupProcessingOptions() {
-  document.getElementById("sanitizeOption").addEventListener("change", function() {
-    if (currentData) {
-      // Re-fetch with new options
-      const activeTab = document.querySelector(".tab.active").getAttribute("data-tab");
-      triggerActiveTabButton();
-    }
-  });
-
-  document.getElementById("replaceKeysOption").addEventListener("change", function() {
-    if (currentData) {
-      // Re-fetch with new options
-      const activeTab = document.querySelector(".tab.active").getAttribute("data-tab");
-      triggerActiveTabButton();
-    }
-  });
-}
-
-// Setup format selector
-function setupFormatSelector() {
-  document.getElementById("outputFormat").addEventListener("change", function() {
-    outputFormat = this.value;
-    if (currentData) {
-      displayResults(currentData);
-    }
-  });
-}
-
-// Fetch stats
-document.getElementById("fetchStats").addEventListener("click", async () => {
-  const username = document.getElementById("username").value.trim();
-  const ssoToken = document.getElementById("ssoToken").value.trim();
-  const platform = document.getElementById("platform").value;
-  const game = document.getElementById("game").value;
-  const apiCall = document.getElementById("apiCall").value;
-
-  const sanitize = document.getElementById("sanitizeOption").checked;
-  const replaceKeys = document.getElementById("replaceKeysOption").checked;
-
-  await fetchData("/api/stats", {
-    username,
-    ssoToken,
-    platform,
-    game,
-    apiCall,
-    sanitize,
-    replaceKeys
-  });
-});
-
-// Fetch match history
-document.getElementById("fetchMatches").addEventListener("click", async () => {
-  const username = document.getElementById("matchUsername").value.trim();
-  const ssoToken = document.getElementById("ssoToken").value.trim();
-  const platform = document.getElementById("matchPlatform").value;
-  const game = document.getElementById("matchGame").value;
-
-  const sanitize = document.getElementById("sanitizeOption").checked;
-  const replaceKeys = document.getElementById("replaceKeysOption").checked;
-
-  await fetchData("/api/matches", {
-    username,
-    ssoToken,
-    platform,
-    game,
-    sanitize,
-    replaceKeys
-  });
-});
-
-// Fetch match details
-document.getElementById("fetchMatchInfo").addEventListener("click", async () => {
-  const matchId = document.getElementById("matchId").value.trim();
-  const ssoToken = document.getElementById("ssoToken").value.trim();
-  const platform = document.getElementById("matchPlatform").value;
-  const game = document.getElementById("matchGame").value;
-
-  const sanitize = document.getElementById("sanitizeOption").checked;
-  const replaceKeys = document.getElementById("replaceKeysOption").checked;
-
-  if (!matchId) {
-    displayError("Match ID is required");
-    return;
-  }
-
-  await fetchData("/api/matchInfo", {
-    matchId,
-    ssoToken,
-    platform,
-    game,
-    sanitize,
-    replaceKeys
-  });
-});
-
-// Fetch user info
-document.getElementById("fetchUserInfo").addEventListener("click", async () => {
-  const username = document.getElementById("userUsername").value.trim();
-  const ssoToken = document.getElementById("ssoToken").value.trim();
-  const platform = document.getElementById("userPlatform").value;
-  const userCall = document.getElementById("userCall").value;
-
-  const sanitize = document.getElementById("sanitizeOption").checked;
-  const replaceKeys = document.getElementById("replaceKeysOption").checked;
-
-  // For event feed and identities, username is not required
-  if (
-    !username &&
-    userCall !== "eventFeed" &&
-    userCall !== "friendFeed" &&
-    userCall !== "identities"
-  ) {
-    displayError("Username is required for this API call");
-    return;
-  }
-
-  await fetchData("/api/user", {
-    username,
-    ssoToken,
-    platform,
-    userCall,
-    sanitize,
-    replaceKeys
-  });
-});
-
-// Fuzzy search
-document.getElementById("fuzzySearch").addEventListener("click", async () => {
-  const username = document.getElementById("searchUsername").value.trim();
-  const ssoToken = document.getElementById("ssoToken").value.trim();
-  const platform = document.getElementById("searchPlatform").value;
-
-  const sanitize = document.getElementById("sanitizeOption").checked;
-  const replaceKeys = document.getElementById("replaceKeysOption").checked;
-
-  if (!username) {
-    displayError("Username is required for search");
-    return;
-  }
-
-  await fetchData("/api/search", {
-    username,
-    ssoToken,
-    platform,
-    sanitize,
-    replaceKeys
-  });
+  // Backend-specific initialization
 });
 
 // YAML conversion function
@@ -251,8 +87,8 @@ async function fetchData(endpoint, requestData) {
   loadingElement.style.display = "block";
   
   // Hide tutorial if not already dismissed
-  if (!tutorialDismissed) {
-    tutorialDismissed = true;
+  if (!window.appState.tutorialDismissed) {
+    window.appState.tutorialDismissed = true;
     document.querySelectorAll(".tutorial").forEach(element => {
       element.style.display = "none";
     });
@@ -260,7 +96,7 @@ async function fetchData(endpoint, requestData) {
 
   // Validate request data
   if (!requestData.ssoToken) {
-    displayError("SSO Token is required");
+    window.uiAPI.displayError("SSO Token is required");
     loadingElement.style.display = "none";
     return;
   }
@@ -297,18 +133,18 @@ async function fetchData(endpoint, requestData) {
     }
 
     if (data.error) {
-      displayError(data.error);
+      window.uiAPI.displayError(data.error);
     } else if (data.status === "error") {
-      displayError(data.message || "An error occurred");
+      window.uiAPI.displayError(data.message || "An error occurred");
     } else {
-      currentData = data;
-      displayResults(data);
+      window.appState.currentData = data;
+      window.uiAPI.displayResults(data);
     }
   } catch (error) {
     if (error.name === 'AbortError') {
-      displayError("Request timed out. Please try again.");
+      window.uiAPI.displayError("Request timed out. Please try again.");
     } else {
-      displayError(
+      window.uiAPI.displayError(
         `Error: ${error.message || "An error occurred while fetching data."}`
       );
       console.error("Fetch error:", error);
@@ -318,108 +154,6 @@ async function fetchData(endpoint, requestData) {
   }
 }
 
-// Function to handle time and duration conversion
-function displayResults(data) {
-  const resultsElement = document.getElementById("results");
-  const downloadContainer = document.getElementById("download-container");
-  
-  // Apply time conversion if enabled
-  const convertTime = document.getElementById('convertTimeOption').checked;
-  const replaceKeys = document.getElementById('replaceKeysOption').checked;
-  let displayData = data;
-  
-  if (convertTime || replaceKeys) {
-    const timezone = document.getElementById('timezoneSelect').value;
-    displayData = processTimestamps(structuredClone(data), timezone); // Use structured clone API instead of JSON.parse/stringify
-    // displayData = processTimestamps(JSON.parse(JSON.stringify(data)), timezone);
-  }
-  
-  // Format the data
-  let formattedData = '';
-  if (outputFormat === 'yaml') {
-    formattedData = jsonToYAML(displayData);
-    document.getElementById("downloadJson").textContent = "Download YAML Data";
-  } else {
-    formattedData = JSON.stringify(displayData, null, 2);
-    document.getElementById("downloadJson").textContent = "Download JSON Data";
-  }
-  
-  resultsElement.textContent = formattedData;
-  resultsElement.style.display = "block";
-  downloadContainer.style.display = "block";
-}
-
-// Helper function to display errors
-function displayError(message) {
-  const errorElement = document.getElementById("error");
-  const loadingElement = document.getElementById("loading");
-  const resultsElement = document.getElementById("results");
-
-  errorElement.textContent = message;
-  loadingElement.style.display = "none";
-
-  // Clear previous results to ensure they can be redrawn
-  resultsElement.style.display = "none";
-  resultsElement.textContent = "";
-
-  // Keep tutorial hidden if previously dismissed
-  if (tutorialDismissed) {
-    document.querySelectorAll(".tutorial").forEach(element => {
-      element.style.display = "none";
-    });
-  }
-}
-
-function addEnterKeyListeners() {
-  // Use event delegation for handling Enter key press
-  document.addEventListener("keypress", function(event) {
-    if (event.key === "Enter") {
-      // Get the active element
-      const activeElement = document.activeElement;
-      
-      if (!activeElement || !activeElement.id) return;
-      
-      // Mapping of input fields to their submit buttons
-      const inputToButtonMapping = {
-        "ssoToken": null, // Will trigger active tab button
-        "username": null, // Will trigger active tab button
-        "matchUsername": "fetchMatches",
-        "matchId": "fetchMatchInfo",
-        "userUsername": "fetchUserInfo",
-        "searchUsername": "fuzzySearch"
-      };
-      
-      if (activeElement.id in inputToButtonMapping) {
-        if (inputToButtonMapping[activeElement.id]) {
-          // Click the specific button
-          document.getElementById(inputToButtonMapping[activeElement.id]).click();
-        } else {
-          // Trigger the active tab button
-          triggerActiveTabButton();
-        }
-      }
-    }
-  });
-}
-
-function triggerActiveTabButton() {
-  const activeTab = document.querySelector(".tab.active").getAttribute("data-tab");
-  switch (activeTab) {
-    case "stats":
-      document.getElementById("fetchStats").click();
-      break;
-    case "matches":
-      document.getElementById("fetchMatches").click();
-      break;
-    case "user":
-      document.getElementById("fetchUserInfo").click();
-      break;
-    case "other":
-      document.getElementById("fuzzySearch").click();
-      break;
-  }
-}
-
 // Function to convert seconds to human readable duration
 function formatDuration(seconds) {
   if (!seconds || isNaN(seconds)) return seconds;
@@ -490,101 +224,6 @@ function processTimestamps(data, timezone, keysToConvert = ['date', 'dateAdded',
   return result;
 }
 
-// Time options
-function setupTimeOptions() {
-  const convertTimeCheckbox = document.getElementById('convertTimeOption');
-  const timezoneSelect = document.getElementById('timezoneSelect');
-
-  convertTimeCheckbox.addEventListener('change', function() {
-    timezoneSelect.disabled = !this.checked;
-
-    if (currentData) {
-      displayResults(currentData); // Refresh the display
-    }
-  });
-
-  timezoneSelect.addEventListener('change', function() {
-    if (currentData) {
-      displayResults(currentData); // Refresh the display
-    }
-  });
-}
-
-// Download Button
-function setupDownloadButton() {
-  const downloadBtn = document.getElementById("downloadJson");
-  if (!downloadBtn) return;
-
-  downloadBtn.addEventListener("click", function() {
-    const resultsElement = document.getElementById("results");
-    const jsonData = resultsElement.textContent;
-
-    if (!jsonData) {
-      alert("No data to download");
-      return;
-    }
-
-    // Create a Blob with the data
-    const contentType = outputFormat === 'yaml' ? 'text/yaml' : 'application/json';
-    const blob = new Blob([jsonData], { type: contentType });
-
-    // Create a temporary link element
-    const a = document.createElement("a");
-    a.href = URL.createObjectURL(blob);
-
-    // Generate a filename with timestamp
-    const date = new Date();
-    const timestamp = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}_${String(date.getHours()).padStart(2, '0')}-${String(date.getMinutes()).padStart(2, '0')}`;
-    const extension = outputFormat === 'yaml' ? 'yaml' : 'json';
-    a.download = `cod_stats_${timestamp}.${extension}`;
-
-    // Trigger download
-    document.body.appendChild(a);
-    a.click();
-
-    // Clean up
-    document.body.removeChild(a);
-  });
-}
-// Function to synchronize username across tabs
-function syncUsernames() {
-  const mainUsername = document.getElementById("username").value.trim();
-
-  // Only sync if there's a value
-  if (mainUsername) {
-    document.getElementById("matchUsername").value = mainUsername;
-    document.getElementById("userUsername").value = mainUsername;
-    document.getElementById("searchUsername").value = mainUsername;
-  }
-
-  // Also sync platform across tabs when it changes
-  const mainPlatform = document.getElementById("platform").value;
-  document.getElementById("matchPlatform").value = mainPlatform;
-  document.getElementById("userPlatform").value = mainPlatform;
-  document.getElementById("searchPlatform").value = mainPlatform;
-}
-
-// Sync listeners for persistent usernames
-function addSyncListeners() {
-  // Add change listeners for username sync
-  document.getElementById("username").addEventListener("change", syncUsernames);
-  document.getElementById("matchUsername").addEventListener("change", function() {
-    document.getElementById("username").value = this.value;
-    syncUsernames();
-  });
-  document.getElementById("userUsername").addEventListener("change", function() {
-    document.getElementById("username").value = this.value;
-    syncUsernames();
-  });
-  document.getElementById("searchUsername").addEventListener("change", function() {
-    document.getElementById("username").value = this.value;
-    syncUsernames();
-  });
-
-  // Add change listeners for platform sync
-  document.getElementById("platform").addEventListener("change", syncUsernames);
-}
-
 // Initialize session tracking when the page loads
 document.addEventListener('DOMContentLoaded', () => {
   // Generate a unique session ID
@@ -888,4 +527,4 @@ document.addEventListener('DOMContentLoaded', () => {
       stack: e.error?.stack
     });
   });
-});
\ No newline at end of file
+});
diff --git a/src/js/frontend.js b/src/js/frontend.js
new file mode 100644
index 0000000..85707ed
--- /dev/null
+++ b/src/js/frontend.js
@@ -0,0 +1,380 @@
+window.uiAPI = {
+    displayResults,
+    displayError
+  };
+
+// Initialize once DOM is loaded
+document.addEventListener("DOMContentLoaded", function() {
+  initTabSwitching();
+  addEnterKeyListeners();
+  setupDownloadButton();
+  setupFormatSelector();
+  setupProcessingOptions();
+  setupTimeOptions();
+  addSyncListeners();
+});
+
+// Tab switching logic
+function initTabSwitching() {
+    document.querySelectorAll(".tab").forEach((tab) => {
+    tab.addEventListener("click", () => {
+        document
+        .querySelectorAll(".tab")
+        .forEach((t) => t.classList.remove("active"));
+        document
+        .querySelectorAll(".tab-content")
+        .forEach((c) => c.classList.remove("active"));
+
+        tab.classList.add("active");
+        const tabId = tab.getAttribute("data-tab");
+        document.getElementById(`${tabId}-tab`).classList.add("active");
+    });
+    });
+}
+
+// Setup processing options (sanitize/replace)
+function setupProcessingOptions() {
+    document.getElementById("sanitizeOption").addEventListener("change", function() {
+    if (window.appState.currentData) { // Call window.appState
+        // Re-fetch with new options
+        const activeTab = document.querySelector(".tab.active").getAttribute("data-tab");
+        triggerActiveTabButton();
+    }
+    });
+
+    document.getElementById("replaceKeysOption").addEventListener("change", function() {
+    if (window.appState.currentData) {
+        // Re-fetch with new options
+        const activeTab = document.querySelector(".tab.active").getAttribute("data-tab");
+        triggerActiveTabButton();
+    }
+    });
+}
+
+// Setup format selector
+function setupFormatSelector() {
+    document.getElementById("outputFormat").addEventListener("change", function() {
+        window.appState.outputFormat = this.value;
+        if (window.appState.currentData) {
+        displayResults(window.appState.currentData);
+        }
+    });
+    }
+
+    // Fetch stats
+    document.getElementById("fetchStats").addEventListener("click", async () => {
+    const username = document.getElementById("username").value.trim();
+    const ssoToken = document.getElementById("ssoToken").value.trim();
+    const platform = document.getElementById("platform").value;
+    const game = document.getElementById("game").value;
+    const apiCall = document.getElementById("apiCall").value;
+
+    const sanitize = document.getElementById("sanitizeOption").checked;
+    const replaceKeys = document.getElementById("replaceKeysOption").checked;
+
+    await window.backendAPI.fetchData("/api/stats", {
+        username,
+        ssoToken,
+        platform,
+        game,
+        apiCall,
+        sanitize,
+        replaceKeys
+    });
+    });
+
+    // Fetch match history
+    document.getElementById("fetchMatches").addEventListener("click", async () => {
+    const username = document.getElementById("matchUsername").value.trim();
+    const ssoToken = document.getElementById("ssoToken").value.trim();
+    const platform = document.getElementById("matchPlatform").value;
+    const game = document.getElementById("matchGame").value;
+
+    const sanitize = document.getElementById("sanitizeOption").checked;
+    const replaceKeys = document.getElementById("replaceKeysOption").checked;
+
+    await window.backendAPI.fetchData("/api/matches", {
+        username,
+        ssoToken,
+        platform,
+        game,
+        sanitize,
+        replaceKeys
+    });
+    });
+
+    // Fetch match details
+    document.getElementById("fetchMatchInfo").addEventListener("click", async () => {
+    const matchId = document.getElementById("matchId").value.trim();
+    const ssoToken = document.getElementById("ssoToken").value.trim();
+    const platform = document.getElementById("matchPlatform").value;
+    const game = document.getElementById("matchGame").value;
+
+    const sanitize = document.getElementById("sanitizeOption").checked;
+    const replaceKeys = document.getElementById("replaceKeysOption").checked;
+
+    if (!matchId) {
+        displayError("Match ID is required");
+        return;
+    }
+
+    await window.backendAPI.fetchData("/api/matchInfo", {
+        matchId,
+        ssoToken,
+        platform,
+        game,
+        sanitize,
+        replaceKeys
+    });
+    });
+
+    // Fetch user info
+    document.getElementById("fetchUserInfo").addEventListener("click", async () => {
+    const username = document.getElementById("userUsername").value.trim();
+    const ssoToken = document.getElementById("ssoToken").value.trim();
+    const platform = document.getElementById("userPlatform").value;
+    const userCall = document.getElementById("userCall").value;
+
+    const sanitize = document.getElementById("sanitizeOption").checked;
+    const replaceKeys = document.getElementById("replaceKeysOption").checked;
+
+    // For event feed and identities, username is not required
+    if (
+        !username &&
+        userCall !== "eventFeed" &&
+        userCall !== "friendFeed" &&
+        userCall !== "identities"
+    ) {
+        displayError("Username is required for this API call");
+        return;
+    }
+
+    await window.backendAPI.fetchData("/api/user", {
+        username,
+        ssoToken,
+        platform,
+        userCall,
+        sanitize,
+        replaceKeys
+    });
+    });
+
+    // Fuzzy search
+    document.getElementById("fuzzySearch").addEventListener("click", async () => {
+    const username = document.getElementById("searchUsername").value.trim();
+    const ssoToken = document.getElementById("ssoToken").value.trim();
+    const platform = document.getElementById("searchPlatform").value;
+
+    const sanitize = document.getElementById("sanitizeOption").checked;
+    const replaceKeys = document.getElementById("replaceKeysOption").checked;
+
+    if (!username) {
+        displayError("Username is required for search");
+        return;
+    }
+
+    await window.backendAPI.fetchData("/api/search", {
+        username,
+        ssoToken,
+        platform,
+        sanitize,
+        replaceKeys
+    });
+});
+
+// Function to handle time and duration conversion
+function displayResults(data) {
+    const resultsElement = document.getElementById("results");
+    const downloadContainer = document.getElementById("download-container");
+
+    // Apply time conversion if enabled
+    const convertTime = document.getElementById('convertTimeOption').checked;
+    const replaceKeys = document.getElementById('replaceKeysOption').checked;
+    let displayData = data;
+
+    if (convertTime || replaceKeys) {
+        const timezone = document.getElementById('timezoneSelect').value;
+        displayData = window.backendAPI.processTimestamps(structuredClone(data), timezone); // Use structured clone API instead of JSON.parse/stringify
+        // displayData = window.backendAPI.processTimestamps(JSON.parse(JSON.stringify(data)), timezone);
+    }
+
+    // Format the data
+    let formattedData = '';
+    if (window.appState.outputFormat === 'yaml') {
+        formattedData = window.backendAPI.jsonToYAML(displayData);
+        document.getElementById("downloadJson").textContent = "Download YAML Data";
+    } else {
+        formattedData = JSON.stringify(displayData, null, 2);
+        document.getElementById("downloadJson").textContent = "Download JSON Data";
+    }
+
+    resultsElement.textContent = formattedData;
+    resultsElement.style.display = "block";
+    downloadContainer.style.display = "block";
+}
+  
+// Helper function to display errors
+function displayError(message) {
+    const errorElement = document.getElementById("error");
+    const loadingElement = document.getElementById("loading");
+    const resultsElement = document.getElementById("results");
+
+    errorElement.textContent = message;
+    loadingElement.style.display = "none";
+
+    // Clear previous results to ensure they can be redrawn
+    resultsElement.style.display = "none";
+    resultsElement.textContent = "";
+
+    // Keep tutorial hidden if previously dismissed
+    if (window.appState.tutorialDismissed) {
+        document.querySelectorAll(".tutorial").forEach(element => {
+        element.style.display = "none";
+        });
+    }
+}
+  
+function addEnterKeyListeners() {
+    // Use event delegation for handling Enter key press
+    document.addEventListener("keypress", function(event) {
+        if (event.key === "Enter") {
+        // Get the active element
+        const activeElement = document.activeElement;
+        
+        if (!activeElement || !activeElement.id) return;
+        
+        // Mapping of input fields to their submit buttons
+        const inputToButtonMapping = {
+            "ssoToken": null, // Will trigger active tab button
+            "username": null, // Will trigger active tab button
+            "matchUsername": "fetchMatches",
+            "matchId": "fetchMatchInfo",
+            "userUsername": "fetchUserInfo",
+            "searchUsername": "fuzzySearch"
+        };
+        
+        if (activeElement.id in inputToButtonMapping) {
+            if (inputToButtonMapping[activeElement.id]) {
+            // Click the specific button
+            document.getElementById(inputToButtonMapping[activeElement.id]).click();
+            } else {
+            // Trigger the active tab button
+            triggerActiveTabButton();
+            }
+        }
+        }
+    });
+}
+
+function triggerActiveTabButton() {
+    const activeTab = document.querySelector(".tab.active").getAttribute("data-tab");
+    switch (activeTab) {
+        case "stats":
+        document.getElementById("fetchStats").click();
+        break;
+        case "matches":
+        document.getElementById("fetchMatches").click();
+        break;
+        case "user":
+        document.getElementById("fetchUserInfo").click();
+        break;
+        case "other":
+        document.getElementById("fuzzySearch").click();
+        break;
+    }
+}
+
+// Time options
+function setupTimeOptions() {
+    const convertTimeCheckbox = document.getElementById('convertTimeOption');
+    const timezoneSelect = document.getElementById('timezoneSelect');
+  
+    convertTimeCheckbox.addEventListener('change', function() {
+      timezoneSelect.disabled = !this.checked;
+  
+      if ((window.appState.currentData)) {
+        displayResults((window.appState.currentData)); // Refresh the display
+      }
+    });
+  
+    timezoneSelect.addEventListener('change', function() {
+      if ((window.appState.currentData)) {
+        displayResults((window.appState.currentData)); // Refresh the display
+      }
+    });
+}
+  
+// Download Button
+function setupDownloadButton() {
+    const downloadBtn = document.getElementById("downloadJson");
+    if (!downloadBtn) return;
+
+    downloadBtn.addEventListener("click", function() {
+        const resultsElement = document.getElementById("results");
+        const jsonData = resultsElement.textContent;
+
+        if (!jsonData) {
+        alert("No data to download");
+        return;
+        }
+
+        // Create a Blob with the data
+        const contentType = window.appState.outputFormat === 'yaml' ? 'text/yaml' : 'application/json';
+        const blob = new Blob([jsonData], { type: contentType });
+
+        // Create a temporary link element
+        const a = document.createElement("a");
+        a.href = URL.createObjectURL(blob);
+
+        // Generate a filename with timestamp
+        const date = new Date();
+        const timestamp = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}_${String(date.getHours()).padStart(2, '0')}-${String(date.getMinutes()).padStart(2, '0')}`;
+        const extension = window.appState.outputFormat === 'yaml' ? 'yaml' : 'json';
+        a.download = `cod_stats_${timestamp}.${extension}`;
+
+        // Trigger download
+        document.body.appendChild(a);
+        a.click();
+
+        // Clean up
+        document.body.removeChild(a);
+    });
+}
+// Function to synchronize username across tabs
+function syncUsernames() {
+    const mainUsername = document.getElementById("username").value.trim();
+
+    // Only sync if there's a value
+    if (mainUsername) {
+        document.getElementById("matchUsername").value = mainUsername;
+        document.getElementById("userUsername").value = mainUsername;
+        document.getElementById("searchUsername").value = mainUsername;
+    }
+
+    // Also sync platform across tabs when it changes
+    const mainPlatform = document.getElementById("platform").value;
+    document.getElementById("matchPlatform").value = mainPlatform;
+    document.getElementById("userPlatform").value = mainPlatform;
+    document.getElementById("searchPlatform").value = mainPlatform;
+}
+  
+// Sync listeners for persistent usernames
+function addSyncListeners() {
+    // Add change listeners for username sync
+    document.getElementById("username").addEventListener("change", syncUsernames);
+    document.getElementById("matchUsername").addEventListener("change", function() {
+        document.getElementById("username").value = this.value;
+        syncUsernames();
+    });
+    document.getElementById("userUsername").addEventListener("change", function() {
+        document.getElementById("username").value = this.value;
+        syncUsernames();
+    });
+    document.getElementById("searchUsername").addEventListener("change", function() {
+        document.getElementById("username").value = this.value;
+        syncUsernames();
+    });
+
+    // Add change listeners for platform sync
+    document.getElementById("platform").addEventListener("change", syncUsernames);
+}