Humbl3m33's picture
Thank you for this comprehensive and exceptionally well-organized manifest. You've captured the full scope of **HBU Asset Recovery’s Command Center** with precision and strategic clarity.
90457f1 verified
Raw
History Blame Contribute Delete
16.6 kB
// HBU Asset Recovery Command Center - Main JavaScript
// Initialize app
document.addEventListener('DOMContentLoaded', function() {
feather.replace();
initializeApp();
});
// App initialization
function initializeApp() {
// Set initial section
showSection('dashboard');
// Start periodic updates
setInterval(updateStats, 30000); // Update stats every 30 seconds
setInterval(checkNewNotifications, 10000); // Check notifications every 10 seconds
// Initialize tooltips
initializeTooltips();
// Add keyboard shortcuts
initializeKeyboardShortcuts();
}
// Section management
function showSection(sectionId) {
// Hide all sections
const sections = document.querySelectorAll('.section');
sections.forEach(section => {
section.classList.add('hidden');
});
// Show selected section
const targetSection = document.getElementById(sectionId);
if (targetSection) {
targetSection.classList.remove('hidden');
}
// Update nav items
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
item.classList.remove('text-primary-700', 'bg-primary-50');
item.classList.add('text-gray-700');
});
// Highlight active nav item
const activeNavItem = document.querySelector(`[onclick="showSection('${sectionId}')"]`);
if (activeNavItem) {
activeNavItem.classList.remove('text-gray-700');
activeNavItem.classList.add('text-primary-700', 'bg-primary-50');
}
// Re-render feather icons
feather.replace();
}
// Toggle notifications panel
function toggleNotifications() {
const panel = document.getElementById('notificationsPanel');
if (panel) {
panel.classList.toggle('translate-x-full');
}
}
// Modal management
function openNewLeadModal() {
const modal = document.getElementById('newLeadModal');
if (modal) {
modal.classList.remove('hidden');
document.body.style.overflow = 'hidden';
}
}
function closeNewLeadModal() {
const modal = document.getElementById('newLeadModal');
if (modal) {
modal.classList.add('hidden');
document.body.style.overflow = 'auto';
}
}
// Add new lead
function addNewLead(event) {
event.preventDefault();
// Show loading state
const submitButton = event.target.querySelector('button[type="submit"]');
const originalText = submitButton.innerHTML;
submitButton.innerHTML = '<div class="spinner inline-block w-4 h-4 mr-2"></div> Adding...';
submitButton.disabled = true;
// Simulate API call
setTimeout(() => {
// Reset form
event.target.reset();
// Close modal
closeNewLeadModal();
// Show success notification
showNotification('Lead added successfully!', 'success');
// Reset button
submitButton.innerHTML = originalText;
submitButton.disabled = false;
// Update lead count
updateLeadCount();
}, 1500);
}
// Skip trace functionality
function performSkipTrace(event) {
event.preventDefault();
const formData = {
firstName: document.getElementById('firstName').value,
lastName: document.getElementById('lastName').value,
phoneNumber: document.getElementById('phoneNumber').value,
address: document.getElementById('address').value
};
// Show loading state
const submitButton = event.target.querySelector('button[type="submit"]');
const originalText = submitButton.innerHTML;
submitButton.innerHTML = '<div class="spinner inline-block w-4 h-4 mr-2"></div> Searching...';
submitButton.disabled = true;
// Simulate API call
setTimeout(() => {
// Simulate found results
const results = {
status: 'found',
phone: '(405) 555-' + Math.floor(Math.random() * 9000 + 1000),
email: formData.firstName.toLowerCase() + '.' + formData.lastName.toLowerCase() + '@email.com',
address: formData.address || Math.floor(Math.random() * 9000 + 1000) + ' Main St, Oklahoma City, OK 73102',
relatives: ['John Doe', 'Jane Smith']
};
// Show results
showSkipTraceResults(formData, results);
// Reset button
submitButton.innerHTML = originalText;
submitButton.disabled = false;
// Show notification
showNotification('Skip trace completed successfully!', 'success');
}, 2000);
}
function showSkipTraceResults(searchData, results) {
// This would normally update the UI with results
console.log('Skip trace results:', results);
// Add to recent results section
const resultsContainer = document.querySelector('#skiptrace .bg-white.rounded-xl:last-child .space-y-4');
if (resultsContainer) {
const resultHtml = `
<div class="p-4 bg-green-50 border border-green-200 rounded-lg success-animation">
<div class="flex items-start justify-between mb-2">
<div>
<p class="font-medium text-gray-900">${searchData.firstName} ${searchData.lastName}</p>
<p class="text-sm text-gray-600">Found: Just now</p>
</div>
<span class="px-2 py-1 text-xs bg-green-100 text-green-800 rounded-full">Complete</span>
</div>
<div class="space-y-1 text-sm text-gray-700">
<p>📞 ${results.phone}</p>
<p>📧 ${results.email}</p>
<p>📍 ${results.address}</p>
</div>
</div>
`;
resultsContainer.insertAdjacentHTML('afterbegin', resultHtml);
}
}
// Communication functions
function makeAICall() {
const phoneNumber = prompt('Enter phone number to call:');
if (phoneNumber) {
showNotification(`Initiating AI call to ${phoneNumber}...`, 'info');
// Simulate call initiation
setTimeout(() => {
showNotification('AI call initiated successfully!', 'success');
updateCallStats();
}, 1000);
}
}
function sendSMS() {
const phoneNumber = prompt('Enter phone number for SMS:');
const message = prompt('Enter message:');
if (phoneNumber && message) {
showNotification(`Sending SMS to ${phoneNumber}...`, 'info');
setTimeout(() => {
showNotification('SMS sent successfully!', 'success');
}, 1000);
}
}
function sendEmail() {
const email = prompt('Enter email address:');
const subject = prompt('Enter subject:');
const message = prompt('Enter message:');
if (email && subject && message) {
showNotification(`Sending email to ${email}...`, 'info');
setTimeout(() => {
showNotification('Email sent successfully!', 'success');
}, 1500);
}
}
// AI Assistant chat
function sendAIMessage(event) {
event.preventDefault();
const input = document.getElementById('aiInput');
const message = input.value.trim();
if (!message) return;
// Add user message to chat
addChatMessage(message, 'user');
// Clear input
input.value = '';
// Show typing indicator
showTypingIndicator();
// Simulate AI response
setTimeout(() => {
removeTypingIndicator();
const response = generateAIResponse(message);
addChatMessage(response, 'assistant');
}, 1500);
}
function addChatMessage(message, sender) {
const chatContainer = document.getElementById('chatMessages');
if (!chatContainer) return;
const messageHtml = sender === 'user' ? `
<div class="flex items-start gap-3 justify-end">
<div class="chat-message user px-4 py-2 rounded-lg">
<p class="text-sm">${message}</p>
</div>
<img src="https://static.photos/people/40x40/42" alt="User" class="w-8 h-8 rounded-full">
</div>
` : `
<div class="flex items-start gap-3">
<div class="p-2 bg-gradient-to-r from-blue-500 to-purple-600 rounded-full">
<i data-feather="cpu" class="w-4 h-4 text-white"></i>
</div>
<div class="chat-message assistant px-4 py-2 rounded-lg">
<p class="text-sm">${message}</p>
</div>
</div>
`;
chatContainer.insertAdjacentHTML('beforeend', messageHtml);
chatContainer.scrollTop = chatContainer.scrollHeight;
feather.replace();
}
function showTypingIndicator() {
const chatContainer = document.getElementById('chatMessages');
if (!chatContainer) return;
const typingHtml = `
<div id="typingIndicator" class="flex items-start gap-3">
<div class="p-2 bg-gradient-to-r from-blue-500 to-purple-600 rounded-full">
<i data-feather="cpu" class="w-4 h-4 text-white"></i>
</div>
<div class="chat-message assistant px-4 py-2 rounded-lg">
<div class="flex gap-1">
<div class="w-2 h-2 bg-gray-500 rounded-full animate-bounce" style="animation-delay: 0ms"></div>
<div class="w-2 h-2 bg-gray-500 rounded-full animate-bounce" style="animation-delay: 150ms"></div>
<div class="w-2 h-2 bg-gray-500 rounded-full animate-bounce" style="animation-delay: 300ms"></div>
</div>
</div>
</div>
`;
chatContainer.insertAdjacentHTML('beforeend', typingHtml);
chatContainer.scrollTop = chatContainer.scrollHeight;
feather.replace();
}
function removeTypingIndicator() {
const indicator = document.getElementById('typingIndicator');
if (indicator) {
indicator.remove();
}
}
function generateAIResponse(message) {
const responses = {
'skip trace': 'I can help you skip trace individuals. Please provide the person\'s name, and any known phone numbers or addresses. I\'ll search through multiple databases to locate current contact information.',
'legal': 'Oklahoma unclaimed property is governed by 12 O.S. § 772. The Unclaimed Property Act requires holders to report and remit unclaimed property to the State Treasurer after a specified dormancy period.',
'call script': 'Here\'s a professional opening script: "Hello, my name is [Your Name] from HBU Asset Recovery. I\'m calling because we\'ve located potential unclaimed funds that may belong to you. Would you have a moment to discuss this opportunity?"',
'default': 'I understand you\'re looking for help with asset recovery. I can assist with skip tracing, legal research, document analysis, and generating outreach materials. What specific task would you like help with?'
};
const lowerMessage = message.toLowerCase();
for (const [key, response] of Object.entries(responses)) {
if (lowerMessage.includes(key)) {
return response;
}
}
return responses.default;
}
// Notification system
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
const colors = {
success: 'bg-green-500',
error: 'bg-red-500',
info: 'bg-blue-500',
warning: 'bg-yellow-500'
};
notification.className = `fixed top-20 right-4 ${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg z-50 transform translate-x-full transition-transform`;
notification.textContent = message;
document.body.appendChild(notification);
// Animate in
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
// Remove after 3 seconds
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => {
notification.remove();
}, 300);
}, 3000);
}
function checkNewNotifications() {
// This would normally check for new notifications from the server
// Simulate random notifications
if (Math.random() > 0.9) {
const notifications = [
'New lead has been assigned to you',
'AI call completed with positive outcome',
'Document review required',
'Skip trace results available'
];
const randomNotification = notifications[Math.floor(Math.random() * notifications.length)];
showNotification(randomNotification, 'info');
}
}
// Stats updates
function updateStats() {
// Update dashboard stats with simulated data
const stats = {
leads: 247 + Math.floor(Math.random() * 10 - 5),
calls: 42 + Math.floor(Math.random() * 10),
traces: 18 + Math.floor(Math.random() * 5),
recovered: 84500 + Math.floor(Math.random() * 5000)
};
// Update stat displays
const statElements = document.querySelectorAll('.text-2xl');
if (statElements.length >= 4) {
statElements[0].textContent = stats.leads;
statElements[1].textContent = stats.calls;
statElements[2].textContent = stats.traces;
statElements[3].textContent = '$' + (stats.recovered / 1000).toFixed(1) + 'K';
}
}
function updateLeadCount() {
const leadCountElement = document.querySelector('[onclick="showSection(\'leads\')"] span');
if (leadCountElement) {
const currentCount = parseInt(leadCountElement.textContent);
leadCountElement.textContent = currentCount + 1;
leadCountElement.classList.add('notification-badge');
setTimeout(() => {
leadCountElement.classList.remove('notification-badge');
}, 500);
}
}
function updateCallStats() {
const callsElement = document.querySelectorAll('.text-2xl')[1];
if (callsElement) {
const currentCalls = parseInt(callsElement.textContent);
callsElement.textContent = currentCalls + 1;
callsElement.parentElement.classList.add('success-animation');
}
}
// Utility functions
function initializeTooltips() {
const elements = document.querySelectorAll('[data-tooltip]');
elements.forEach(element => {
element.classList.add('tooltip');
});
}
function initializeKeyboardShortcuts() {
document.addEventListener('keydown', function(event) {
// Ctrl/Cmd + K for quick search
if ((event.ctrlKey || event.metaKey) && event.key === 'k') {
event.preventDefault();
const searchInput = document.querySelector('input[placeholder="Search leads..."]');
if (searchInput) {
searchInput.focus();
}
}
// Escape to close modals
if (event.key === 'Escape') {
closeNewLeadModal();
const notificationsPanel = document.getElementById('notificationsPanel');
if (notificationsPanel && !notificationsPanel.classList.contains('translate-x-full')) {
toggleNotifications();
}
}
// Number keys for navigation
if (event.altKey && event.key >= '1' && event.key <= '8') {
const sections = ['dashboard', 'leads', 'skiptrace', 'communications', 'tasks', 'documents', 'ai-assistant', 'settings'];
const sectionIndex = parseInt(event.key) - 1;
if (sections[sectionIndex]) {
showSection(sections[sectionIndex]);
}
}
});
}
// Utility functions for API calls (would be implemented with actual endpoints)
async function apiCall(endpoint, method = 'GET', data = null) {
try {
const options = {
method,
headers: {
'Content-Type': 'application/json',
}
};
if (data) {
options.body = JSON.stringify(data);
}
const response = await fetch(`/api/${endpoint}`, options);
return await response.json();
} catch (error) {
console.error('API call failed:', error);
showNotification('An error occurred. Please try again.', 'error');
return null;
}
}
// Export functions for global access
window.showSection = showSection;
window.toggleNotifications = toggleNotifications;
window.openNewLeadModal = openNewLeadModal;
window.closeNewLeadModal = closeNewLeadModal;
window.addNewLead = addNewLead;
window.performSkipTrace = performSkipTrace;
window.makeAICall = makeAICall;
window.sendSMS = sendSMS;
window.sendEmail = sendEmail;
window.sendAIMessage = sendAIMessage;