|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const AppUtils = { |
|
|
|
|
|
addSystemNotification: function(message) { |
|
|
console.log(`[μμ€ν
μλ¦Ό] ${message}`); |
|
|
|
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.classList.add('message', 'system'); |
|
|
|
|
|
const contentDiv = document.createElement('div'); |
|
|
contentDiv.classList.add('message-content'); |
|
|
|
|
|
const messageP = document.createElement('p'); |
|
|
messageP.innerHTML = `<i class="fas fa-info-circle"></i> ${message}`; |
|
|
contentDiv.appendChild(messageP); |
|
|
|
|
|
messageDiv.appendChild(contentDiv); |
|
|
|
|
|
|
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
if (chatMessages) { |
|
|
chatMessages.appendChild(messageDiv); |
|
|
|
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
addErrorMessage: function(errorText) { |
|
|
console.error(`[μ€λ₯] ${errorText}`); |
|
|
|
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.classList.add('message', 'system'); |
|
|
|
|
|
const contentDiv = document.createElement('div'); |
|
|
contentDiv.classList.add('message-content'); |
|
|
contentDiv.style.backgroundColor = 'rgba(239, 68, 68, 0.1)'; |
|
|
contentDiv.style.color = 'var(--error-color)'; |
|
|
|
|
|
const errorP = document.createElement('p'); |
|
|
errorP.innerHTML = `<i class="fas fa-exclamation-circle"></i> ${errorText}`; |
|
|
contentDiv.appendChild(errorP); |
|
|
|
|
|
messageDiv.appendChild(contentDiv); |
|
|
|
|
|
|
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
if (chatMessages) { |
|
|
chatMessages.appendChild(messageDiv); |
|
|
|
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
fetchWithTimeout: async function(url, options = {}, timeout = 30000) { |
|
|
console.log(`API μμ²: ${options.method || 'GET'} ${url}`); |
|
|
|
|
|
const controller = new AbortController(); |
|
|
const id = setTimeout(() => controller.abort(), timeout); |
|
|
|
|
|
try { |
|
|
const response = await fetch(url, { |
|
|
...options, |
|
|
signal: controller.signal |
|
|
}); |
|
|
clearTimeout(id); |
|
|
console.log(`API μλ΅ μν: ${response.status}`); |
|
|
return response; |
|
|
} catch (error) { |
|
|
clearTimeout(id); |
|
|
if (error.name === 'AbortError') { |
|
|
console.error(`API μμ² νμμμ: ${url}`); |
|
|
throw new Error('μμ² μκ°μ΄ μ΄κ³Όλμμ΅λλ€.'); |
|
|
} |
|
|
console.error(`API μμ² μ€ν¨: ${url}`, error); |
|
|
throw error; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
createLoadingSpinner: function() { |
|
|
return '<div class="loading-spinner"></div>'; |
|
|
}, |
|
|
|
|
|
|
|
|
formatDate: function(date) { |
|
|
return new Date(date).toLocaleString('ko-KR', { |
|
|
year: 'numeric', |
|
|
month: '2-digit', |
|
|
day: '2-digit', |
|
|
hour: '2-digit', |
|
|
minute: '2-digit' |
|
|
}); |
|
|
}, |
|
|
|
|
|
|
|
|
escapeHtml: function(html) { |
|
|
const div = document.createElement('div'); |
|
|
div.textContent = html; |
|
|
return div.innerHTML; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
console.log('μ± μ½μ΄ λͺ¨λ μ΄κΈ°ν μλ£'); |
|
|
}); |
|
|
|