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

@@ -148,5 +148,88 @@
return response.json();
};
// ==================== 공통 유틸리티 ====================
/**
* Toast 알림 표시
*/
window.showToast = function(message, type, duration) {
type = type || 'info';
duration = duration || 3000;
var container = document.getElementById('toastContainer');
if (!container) {
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);
}
if (!document.getElementById('toastStyles')) {
var style = document.createElement('style');
style.id = 'toastStyles';
style.textContent =
'.toast{display:flex;align-items:center;gap:12px;padding:12px 20px;background:#fff;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15);opacity:0;transform:translateX(100px);transition:all .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);
}
var iconMap = { success: '\u2705', error: '\u274C', warning: '\u26A0\uFE0F', info: '\u2139\uFE0F' };
var toast = document.createElement('div');
toast.className = 'toast toast-' + type;
toast.innerHTML = '<span class="toast-icon">' + (iconMap[type] || '\u2139\uFE0F') + '</span><span class="toast-message">' + message + '</span>';
container.appendChild(toast);
setTimeout(function() { toast.classList.add('show'); }, 10);
setTimeout(function() {
toast.classList.remove('show');
setTimeout(function() { toast.remove(); }, 300);
}, duration);
};
/**
* 날짜를 YYYY-MM-DD 형식으로 변환
*/
window.formatDate = function(dateString) {
if (!dateString) return '';
if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) return dateString;
var d = new Date(dateString);
if (isNaN(d.getTime())) return '';
var y = d.getFullYear();
var m = String(d.getMonth() + 1).padStart(2, '0');
var day = String(d.getDate()).padStart(2, '0');
return y + '-' + m + '-' + day;
};
/**
* apiCall이 로드될 때까지 대기
*/
window.waitForApi = function(timeout) {
timeout = timeout || 5000;
return new Promise(function(resolve, reject) {
if (window.apiCall) return resolve();
var elapsed = 0;
var iv = setInterval(function() {
elapsed += 50;
if (window.apiCall) { clearInterval(iv); resolve(); }
else if (elapsed >= timeout) { clearInterval(iv); reject(new Error('apiCall timeout')); }
}, 50);
});
};
/**
* UUID v4 생성
*/
window.generateUUID = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0;
var v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
console.log('API 설정 완료:', window.API_BASE_URL);
})();