// Global state management const state = { searchResults: [], recentSearches: [], user: null, isLoading: false, notifications: [] }; // Initialize the application document.addEventListener('DOMContentLoaded', function() { initializeApp(); setupEventListeners(); loadRecentSearches(); checkUserSession(); }); // Initialize application function initializeApp() { // Initialize tooltips initTooltips(); // Load saved preferences loadPreferences(); // Start activity monitoring startActivityMonitoring(); // Initialize web components initializeComponents(); } // Setup event listeners function setupEventListeners() { // Search form submission const searchForm = document.getElementById('searchForm'); if (searchForm) { searchForm.addEventListener('submit', handleSearchSubmit); } // Keyboard shortcuts document.addEventListener('keydown', handleKeyboardShortcuts); // Window resize handler window.addEventListener('resize', handleWindowResize); // Online/offline detection window.addEventListener('online', handleOnlineStatus); window.addEventListener('offline', handleOfflineStatus); } // Handle search form submission async function handleSearchSubmit(e) { e.preventDefault(); const formData = new FormData(e.target); const searchParams = { firstName: formData.get('firstName'), lastName: formData.get('lastName'), dob: formData.get('dob'), phone: formData.get('phone'), email: formData.get('email'), address: formData.get('address') }; // Validate required fields if (!searchParams.firstName && !searchParams.lastName && !searchParams.phone && !searchParams.email) { showNotification('Please enter at least one search parameter', 'warning'); return; } // Show loading state setLoadingState(true); try { // Perform search const results = await performSearch(searchParams); // Store results state.searchResults = results; // Add to recent searches addToRecentSearches(searchParams, results); // Show results modal displaySearchResults(results); // Show success notification showNotification(`Found ${results.length} result(s)`, 'success'); } catch (error) { console.error('Search error:', error); showNotification('Search failed. Please try again.', 'error'); } finally { setLoadingState(false); } } // Perform actual search async function performSearch(params) { // Simulate API call with mock data await new Promise(resolve => setTimeout(resolve, 1500)); // Generate mock results based on search parameters const mockResults = generateMockResults(params); // In a real implementation, this would be an actual API call: // const response = await fetch('/api/skip-trace/search', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify(params) // }); // return response.json(); return mockResults; } // Generate mock search results function generateMockResults(params) { const results = []; const numResults = Math.floor(Math.random() * 5) + 1; for (let i = 0; i < numResults; i++) { const confidence = Math.floor(Math.random() * 40) + 60; const hasAssets = Math.random() > 0.5; results.push({ id: `result-${Date.now()}-${i}`, fullName: `${params.firstName || 'John'} ${params.lastName || 'Doe'} ${i > 0 ? ` (${i + 1})` : ''}`, firstName: params.firstName || 'John', lastName: params.lastName || 'Doe', age: Math.floor(Math.random() * 50) + 25, confidence: confidence, confidenceLevel: confidence >= 85 ? 'high' : confidence >= 70 ? 'medium' : 'low', emails: [ `${(params.firstName || 'john').toLowerCase()}.${(params.lastName || 'doe').toLowerCase()}${i}@email.com`, `${(params.firstName || 'john').toLowerCase()}.${(params.lastName || 'doe').toLowerCase()}${i}@gmail.com` ], phones: [ `(${Math.floor(Math.random() * 900) + 100}) ${Math.floor(Math.random() * 900) + 100}-${Math.floor(Math.random() * 9000) + 1000}`, `+1 ${Math.floor(Math.random() * 900) + 100}-${Math.floor(Math.random() * 900) + 100}-${Math.floor(Math.random() * 9000) + 1000}` ], addresses: [ { street: `${Math.floor(Math.random() * 9999) + 1} Main St`, city: 'Los Angeles', state: 'CA', zip: `${Math.floor(Math.random() * 90000) + 10000}`, fullAddress: `${Math.floor(Math.random() * 9999) + 1} Main St, Los Angeles, CA ${Math.floor(Math.random() * 90000) + 10000}` } ], assets: hasAssets ? [ { type: 'Property', value: Math.floor(Math.random() * 1000000) + 200000, address: `${Math.floor(Math.random() * 9999) + 1} Oak Ave, Beverly Hills, CA`, description: 'Residential Property' }, { type: 'Vehicle', value: Math.floor(Math.random() * 50000) + 15000, description: `${['Honda', 'Toyota', 'Ford', 'BMW'][Math.floor(Math.random() * 4)]} ${2020 - Math.floor(Math.random() * 5)}` } ] : [], dataSources: ['Enformion', 'People Data Labs', 'Google'].slice(0, Math.floor(Math.random() * 3) + 1), lastUpdated: new Date().toISOString(), verified: confidence >= 85 }); } return results; } // Display search results in modal function displaySearchResults(results) { const searchModal = document.getElementById('searchModal'); const resultsContainer = document.getElementById('searchResults'); if (!searchModal || !resultsContainer) return; // Clear previous results resultsContainer.innerHTML = ''; if (results.length === 0) { resultsContainer.innerHTML = `

No results found

`; } else { results.forEach((result, index) => { const resultElement = createResultElement(result, index); resultsContainer.appendChild(resultElement); }); } // Show modal searchModal.classList.remove('hidden'); // Re-initialize feather icons feather.replace(); } // Create result element function createResultElement(result, index) { const div = document.createElement('div'); div.className = 'search-result-item fade-in'; div.style.animationDelay = `${index * 0.1}s`; const confidenceClass = `confidence-${result.confidenceLevel}`; const confidenceColor = result.confidenceLevel === 'high' ? 'green' : result.confidenceLevel === 'medium' ? 'yellow' : 'red'; div.innerHTML = `

${result.fullName}

Age: ${result.age} • ID: ${result.id}

${result.confidence}% confidence ${result.verified ? '' : ''}

Contact Information

${result.emails.map(email => `
${email}
`).join('')} ${result.phones.map(phone => `
${phone}
`).join('')}

Address

${result.addresses.map(addr => `
${addr.fullAddress}
`).join('')}
${result.assets.length > 0 ? `

Discovered Assets

${result.assets.map(asset => `

${asset.type}: $${asset.value.toLocaleString()}

${asset.description}

`).join('')}
` : ''}
${result.dataSources.map(source => ` ${source} `).join('')}
`; return div; } // Modal functions function showSearchModal() { const modal = document.getElementById('searchModal'); if (modal) modal.classList.remove('hidden'); } function closeSearchModal() { const modal = document.getElementById('searchModal'); if (modal) modal.classList.add('hidden'); } function showBatchUpload() { const modal = document.getElementById('batchModal'); if (modal) modal.classList.remove('hidden'); } function closeBatchModal() { const modal = document.getElementById('batchModal'); if (modal) modal.classList.add('hidden'); } function showAnalytics() { const modal = document.getElementById('analyticsModal'); if (modal) modal.classList.remove('hidden'); } function closeAnalyticsModal() { const modal = document.getElementById('analyticsModal'); if (modal) modal.classList.add('hidden'); } function showAdvancedFilters() { showNotification('Advanced filters coming soon!', 'info'); } // Utility functions function clearForm() { const form = document.getElementById('searchForm'); if (form) form.reset(); } function downloadTemplate() { const csvContent = 'first_name,last_name,dob,phone,email,address\nJohn,Doe,1980-01-01,555-1234,john@example.com,123 Main St, City, State ZIP'; const blob = new Blob([csvContent], { type: 'text/csv' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'skip-trace-template.csv'; a.click(); URL.revokeObjectURL(url); showNotification('Template downloaded successfully', 'success'); } function exportResults() { if (state.searchResults.length === 0) { showNotification('No results to export', 'warning'); return; } // Create CSV content const headers = ['Name', 'Confidence', 'Emails', 'Phones', 'Addresses', 'Assets']; const rows = state.searchResults.map(result => [ result.fullName, `${result.confidence}%`, result.emails.join('; '), result.phones.join('; '), result.addresses.map(a => a.fullAddress).join('; '), result.assets.map(a => `${a.type}: $${a.value}`).join('; ') ]); const csvContent = [headers, ...rows].map(row => row.map(cell => `"${cell}"`).join(',')).join('\n'); // Download CSV const blob = new Blob([csvContent], { type: 'text/csv' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `skip-trace-results-${new Date().toISOString().split('T')[0]}.csv`; a.click(); URL.revokeObjectURL(url); showNotification('Results exported successfully', 'success'); } function exportSingleResult(resultId) { const result = state.searchResults.find(r => r.id === resultId); if (!result) return; // Similar to exportResults but for single result showNotification(`Exporting result for ${result.fullName}`, 'info'); } function viewFullReport(resultId) { const result = state.searchResults.find(r => r.id === resultId); if (!result) return; showNotification(`Generating full report for ${result.fullName}`, 'info'); // In a real implementation, this would generate a detailed PDF report } // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = 'notification'; const colors = { success: 'text-green-400 border-green-500', error: 'text-red-400 border-red-500', warning: 'text-yellow-400 border-yellow-500', info: 'text-blue-400 border-blue-500' }; const icons = { success: 'check-circle', error: 'x-circle', warning: 'alert-triangle', info: 'info' }; notification.innerHTML = `
${message}
`; document.body.appendChild(notification); // Re-initialize feather icons feather.replace(); // Auto remove after 5 seconds setTimeout(() => { notification.style.animation = 'slideOutRight 0.3s ease-out'; setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 300); }, 5000); } // Loading state management function setLoadingState(loading) { state.isLoading = loading; const submitButton = document.querySelector('button[type="submit"]'); if (submitButton) { if (loading) { submitButton.disabled = true; submitButton.innerHTML = '
Searching...'; } else { submitButton.disabled = false; submitButton.innerHTML = 'Search'; feather.replace(); } } } // Recent searches management function addToRecentSearches(params, results) { const search = { params, resultCount: results.length, timestamp: new Date().toISOString(), id: Date.now().toString() }; state.recentSearches.unshift(search); state.recentSearches = state.recentSearches.slice(0, 10); // Keep only last 10 saveRecentSearches(); updateRecentSearchesUI(); } function loadRecentSearches() { const saved = localStorage.getItem('recentSearches'); if (saved) { state.recentSearches = JSON.parse(saved); updateRecentSearchesUI(); } } function saveRecentSearches() { localStorage.setItem('recentSearches', JSON.stringify(state.recentSearches)); } function updateRecentSearchesUI() { const container = document.getElementById('recentSearches'); if (!container) return; if (state.recentSearches.length === 0) { container.innerHTML = '

No recent searches

'; return; } container.innerHTML = state.recentSearches.slice(0, 3).map(search => { const timeAgo = getTimeAgo(new Date(search.timestamp)); const name = search.params.firstName || search.params.lastName || search.params.email || search.params.phone || 'Unknown'; return `

${name}

${timeAgo} • ${search.resultCount} results

`; }).join(''); feather.replace(); } function repeatSearch(searchId) { const search = state.recentSearches.find(s => s.id === searchId); if (!search) return; // Populate form with previous search parameters Object.entries(search.params).forEach(([key, value]) => { const input = document.getElementById(key); if (input) input.value = value || ''; }); // Trigger search document.getElementById('searchForm').dispatchEvent(new Event('submit')); } // Utility functions function getTimeAgo(date) { const seconds = Math.floor((new Date() - date) / 1000); let interval = seconds / 31536000; if (interval > 1) return Math.floor(interval) + ' years ago'; interval = seconds / 2592000; if (interval > 1) return Math.floor(interval) + ' months ago'; interval = seconds / 86400; if (interval > 1) return Math.floor(interval) + ' days ago'; interval = seconds / 3600; if (interval > 1) return Math.floor(interval) + ' hours ago'; interval = seconds / 60; if (interval > 1) return Math.floor(interval) + ' minutes ago'; return 'Just now'; } // Keyboard shortcuts function handleKeyboardShortcuts(e) { // Ctrl/Cmd + K for search if ((e.ctrlKey || e.metaKey) && e.key === 'k') { e.preventDefault(); document.getElementById('firstName')?.focus(); } // Escape to close modals if (e.key === 'Escape') { closeSearchModal(); closeBatchModal(); closeAnalyticsModal(); } } // Window resize handler function handleWindowResize() { // Handle responsive layout adjustments if (window.innerWidth < 768) { // Mobile adjustments } } // Online/offline handlers function handleOnlineStatus() { showNotification('Connection restored', 'success'); } function handleOfflineStatus() { showNotification('Connection lost. Some features may be unavailable.', 'warning'); } // User session management function checkUserSession() { const token = localStorage.getItem('authToken'); if (!token) { // Redirect to login or show guest mode console.log('No user session found'); } } // Activity monitoring function startActivityMonitoring() { let lastActivity = Date.now(); ['mousedown', 'keydown', 'scroll', 'touchstart'].forEach(event => { document.addEventListener(event, () => { lastActivity = Date.now(); }); }); // Check for inactivity every minute setInterval(() => { if (Date.now() - lastActivity > 30 * 60 * 1000) { // 30 minutes showNotification('Session about to expire due to inactivity', 'warning'); } }, 60000); } // Preferences management function loadPreferences() { const preferences = localStorage.getItem('userPreferences'); if (preferences) { const prefs = JSON.parse(preferences); // Apply preferences if (prefs.theme) { document.documentElement.className = prefs.theme; } } } // Tooltip initialization function initTooltips() { // Initialize tooltips if using a tooltip library console.log('Tooltips initialized'); } // Web component initialization function initializeComponents() { // Initialize any web components console.log('Web components initialized'); } // Export functions for global access window.showSearchModal = showSearchModal; window.closeSearchModal = closeSearchModal; window.showBatchUpload = showBatchUpload; window.closeBatchModal = closeBatchModal; window.showAnalytics = showAnalytics; window.closeAnalyticsModal = closeAnalyticsModal; window.showAdvancedFilters = showAdvancedFilters; window.clearForm = clearForm; window.downloadTemplate = downloadTemplate; window.exportResults = exportResults; window.exportSingleResult = exportSingleResult; window.viewFullReport = viewFullReport; window.repeatSearch = repeatSearch;