// Frontend JavaScript with various technical debt examples // TODO: Move configuration to separate file const API_BASE_URL = "https://api.example.com"; const API_KEY = "abc123def456"; // FIXME: Should be in environment // Global variables - should be encapsulated var userCache = {}; var authToken = null; var currentUser = null; // HACK: Polyfill for older browsers - should use proper build system if (!String.prototype.includes) { String.prototype.includes = function(search) { return this.indexOf(search) !== -1; }; } class UserInterface { constructor() { this.components = {}; this.eventHandlers = []; // Long parameter list in constructor this.init(document, window, localStorage, sessionStorage, navigator, history, location); } // Function with too many parameters init(doc, win, localStorage, sessionStorage, nav, hist, loc) { this.document = doc; this.window = win; this.localStorage = localStorage; this.sessionStorage = sessionStorage; this.navigator = nav; this.history = hist; this.location = loc; // Deep nesting example if (this.localStorage) { if (this.localStorage.getItem('user')) { if (JSON.parse(this.localStorage.getItem('user'))) { if (JSON.parse(this.localStorage.getItem('user')).preferences) { if (JSON.parse(this.localStorage.getItem('user')).preferences.theme) { if (JSON.parse(this.localStorage.getItem('user')).preferences.theme === 'dark') { document.body.classList.add('dark-theme'); } else if (JSON.parse(this.localStorage.getItem('user')).preferences.theme === 'light') { document.body.classList.add('light-theme'); } else { document.body.classList.add('default-theme'); } } } } } } } // Large function that does too many things renderUserDashboard(userId, includeStats, includeRecent, includeNotifications, includeSettings, includeHelp) { let user = this.getUser(userId); if (!user) { console.log("User not found"); // Should use proper logging return; } let html = '
'; // Inline HTML generation - should use templates html += '
'; html += '

Welcome, ' + user.name + '

'; html += '
'; html += 'Avatar'; html += '
'; html += '
'; // Repeated validation pattern if (includeStats && includeStats === true) { html += '
'; html += '

Your Statistics

'; // Magic numbers everywhere if (user.loginCount > 100) { html += '
Frequent User (100+ logins)
'; } else if (user.loginCount > 50) { html += '
Regular User (50+ logins)
'; } else if (user.loginCount > 10) { html += '
Casual User (10+ logins)
'; } else { html += '
New User
'; } html += '
'; } if (includeRecent && includeRecent === true) { html += '
'; html += '

Recent Activity

'; // No error handling for API calls let recentActivity = this.fetchRecentActivity(userId); if (recentActivity && recentActivity.length > 0) { html += ''; } else { html += '

No recent activity

'; } html += '
'; } if (includeNotifications && includeNotifications === true) { html += '
'; html += '

Notifications

'; let notifications = this.getNotifications(userId); // Duplicate HTML generation pattern if (notifications && notifications.length > 0) { html += ''; } else { html += '

No notifications

'; } html += '
'; } html += '
'; // Direct DOM manipulation without cleanup document.getElementById('main-content').innerHTML = html; // Event handler attachment without cleanup let buttons = document.querySelectorAll('.action-button'); for (let i = 0; i < buttons.length; i++) { buttons[i].addEventListener('click', function(event) { // Nested event handlers - memory leak risk let buttonType = event.target.getAttribute('data-type'); if (buttonType === 'edit') { // Inline event handling - should be separate methods let modal = document.createElement('div'); modal.className = 'modal'; modal.innerHTML = ''; document.body.appendChild(modal); } else if (buttonType === 'delete') { if (confirm('Are you sure?')) { // Using confirm - poor UX // No error handling fetch(API_BASE_URL + '/users/' + userId, { method: 'DELETE', headers: {'Authorization': 'Bearer ' + authToken} }); } } else if (buttonType === 'share') { // Hardcoded share logic if (navigator.share) { navigator.share({ title: 'Check out my profile', url: window.location.href }); } else { // Fallback for browsers without Web Share API let shareUrl = 'https://twitter.com/intent/tweet?url=' + encodeURIComponent(window.location.href); window.open(shareUrl, '_blank'); } } }); } } // Duplicate code - similar to above but for admin dashboard renderAdminDashboard(adminId) { let admin = this.getUser(adminId); if (!admin) { console.log("Admin not found"); return; } let html = '
'; html += '
'; html += '

Admin Panel - Welcome, ' + admin.name + '

'; html += '
'; html += 'Avatar'; html += '
'; html += '
'; // Same pattern repeated html += '
'; html += '

System Statistics

'; let stats = this.getSystemStats(); if (stats) { html += '
'; html += '
Total Users: ' + stats.totalUsers + '
'; html += '
Active Users: ' + stats.activeUsers + '
'; html += '
New Today: ' + stats.newToday + '
'; html += '
'; } html += '
'; html += '
'; document.getElementById('main-content').innerHTML = html; } getUser(userId) { // Check cache first - but cache never expires if (userCache[userId]) { return userCache[userId]; } // Synchronous AJAX - blocks UI let xhr = new XMLHttpRequest(); xhr.open('GET', API_BASE_URL + '/users/' + userId, false); xhr.setRequestHeader('Authorization', 'Bearer ' + authToken); xhr.send(); if (xhr.status === 200) { let user = JSON.parse(xhr.responseText); userCache[userId] = user; return user; } else { // Generic error handling console.error('Failed to fetch user'); return null; } } fetchRecentActivity(userId) { // Another synchronous call try { let xhr = new XMLHttpRequest(); xhr.open('GET', API_BASE_URL + '/users/' + userId + '/activity', false); xhr.setRequestHeader('Authorization', 'Bearer ' + authToken); xhr.send(); if (xhr.status === 200) { return JSON.parse(xhr.responseText); } else { return []; } } catch (error) { // Swallowing errors return []; } } getNotifications(userId) { // Yet another sync call - should be async let xhr = new XMLHttpRequest(); xhr.open('GET', API_BASE_URL + '/users/' + userId + '/notifications', false); xhr.setRequestHeader('Authorization', 'Bearer ' + authToken); xhr.send(); if (xhr.status === 200) { return JSON.parse(xhr.responseText); } else { return []; } } formatTime(timestamp) { // Basic time formatting - should use proper library let date = new Date(timestamp); return date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear(); } // XXX: This method is never used formatCurrency(amount, currency) { if (currency === 'USD') { return '$' + amount.toFixed(2); } else if (currency === 'EUR') { return '€' + amount.toFixed(2); } else { return amount.toFixed(2) + ' ' + currency; } } getSystemStats() { // Hardcoded test data - should come from API return { totalUsers: 12534, activeUsers: 8765, newToday: 23 }; } } // Global functions - should be methods or modules function closeModal() { // Assumes modal exists - no error checking document.querySelector('.modal').remove(); } function validateEmail(email) { // Regex without explanation - magic pattern return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } function validatePassword(password) { // Duplicate validation logic from backend if (password.length < 8) return false; if (!/[A-Z]/.test(password)) return false; if (!/[a-z]/.test(password)) return false; if (!/\d/.test(password)) return false; return true; } // jQuery-style utility - reinventing the wheel function $(selector) { return document.querySelector(selector); } function $all(selector) { return document.querySelectorAll(selector); } // Global event handlers - should be encapsulated document.addEventListener('DOMContentLoaded', function() { // Inline anonymous function let ui = new UserInterface(); // Event delegation would be better document.body.addEventListener('click', function(event) { if (event.target.classList.contains('login-button')) { // Inline login logic let username = $('#username').value; let password = $('#password').value; if (!username || !password) { alert('Please enter username and password'); // Poor UX return; } // No CSRF protection fetch(API_BASE_URL + '/auth/login', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({username: username, password: password}) }) .then(response => response.json()) .then(data => { if (data.success) { authToken = data.token; currentUser = data.user; localStorage.setItem('authToken', authToken); // Storing sensitive data localStorage.setItem('currentUser', JSON.stringify(currentUser)); window.location.reload(); // Poor navigation } else { alert('Login failed: ' + data.error); } }) .catch(error => { console.error('Login error:', error); alert('Login failed'); }); } }); }); // // Old code left as comments - should be removed // function oldRenderFunction() { // var html = '
Old implementation
'; // document.body.innerHTML = html; // } // Commented out feature - should be removed or implemented // function darkModeToggle() { // if (document.body.classList.contains('dark-theme')) { // document.body.classList.remove('dark-theme'); // document.body.classList.add('light-theme'); // } else { // document.body.classList.remove('light-theme'); // document.body.classList.add('dark-theme'); // } // }