refactor: 프론트엔드 유틸리티 함수 통합 (showToast, waitForApi, generateUUID)

- api-base.js에 4개 전역 유틸리티 추가 (showToast, formatDate, waitForApi, generateUUID)
- 24개 파일에서 중복 정의 제거 (-932줄)
- showToast: 18곳 중복 → 1곳 통합 (자동 컨테이너/스타일 생성)
- waitForApi/waitForApiConfig/waitForApiCall: 5곳 → 1곳 통합
- generateUUID: tbm.js 중복 제거
- tbm/utils.js, workplace-management/utils.js: window 재정의 제거

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-02-25 08:45:55 +09:00
parent 64e3c1227d
commit 4581cddbc0
24 changed files with 112 additions and 932 deletions

View File

@@ -10,94 +10,7 @@ let canvas = null;
let ctx = null;
let layoutImage = null;
// ==================== Toast 알림 ====================
/**
* Toast 메시지 표시
*/
function showToast(message, type = 'info', duration = 3000) {
const toastContainer = document.getElementById('toastContainer') || createToastContainer();
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
const iconMap = {
success: '✅',
error: '❌',
warning: '⚠️',
info: ''
};
toast.innerHTML = `
<span class="toast-icon">${iconMap[type] || ''}</span>
<span class="toast-message">${message}</span>
`;
toastContainer.appendChild(toast);
// 애니메이션
setTimeout(() => toast.classList.add('show'), 10);
// 자동 제거
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => toast.remove(), 300);
}, duration);
}
/**
* Toast 컨테이너 생성
*/
function createToastContainer() {
const container = document.createElement('div');
container.id = 'toastContainer';
container.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 10px;
`;
document.body.appendChild(container);
// Toast 스타일 추가
if (!document.getElementById('toastStyles')) {
const style = document.createElement('style');
style.id = 'toastStyles';
style.textContent = `
.toast {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 20px;
background: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
opacity: 0;
transform: translateX(100px);
transition: all 0.3s ease;
min-width: 250px;
max-width: 400px;
}
.toast.show {
opacity: 1;
transform: translateX(0);
}
.toast-success { border-left: 4px solid #10b981; }
.toast-error { border-left: 4px solid #ef4444; }
.toast-warning { border-left: 4px solid #f59e0b; }
.toast-info { border-left: 4px solid #3b82f6; }
.toast-icon { font-size: 20px; }
.toast-message { font-size: 14px; color: #374151; }
`;
document.head.appendChild(style);
}
return container;
}
// showToast, createToastContainer → api-base.js 전역 사용
// ==================== 초기화 ====================
@@ -523,7 +436,6 @@ function resetForm() {
}
// 전역 함수로 노출
window.showToast = showToast;
window.openMapModal = openMapModal;
window.closeMapModal = closeMapModal;
window.loadWorkplaceMap = loadWorkplaceMap;