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:
@@ -537,35 +537,7 @@ function handleLogout() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 토스트 알림 ========== //
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info', duration = 3000) {
|
|
||||||
if (!elements.toastContainer) return;
|
|
||||||
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast ${type}`;
|
|
||||||
|
|
||||||
const iconMap = {
|
|
||||||
success: '✅',
|
|
||||||
error: '❌',
|
|
||||||
warning: '⚠️',
|
|
||||||
info: 'ℹ️'
|
|
||||||
};
|
|
||||||
|
|
||||||
toast.innerHTML = `
|
|
||||||
<div class="toast-icon">${iconMap[type] || 'ℹ️'}</div>
|
|
||||||
<div class="toast-message">${message}</div>
|
|
||||||
<button class="toast-close" onclick="this.parentElement.remove()">×</button>
|
|
||||||
`;
|
|
||||||
|
|
||||||
elements.toastContainer.appendChild(toast);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentElement) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== 전역 함수 (HTML에서 호출) ========== //
|
// ========== 전역 함수 (HTML에서 호출) ========== //
|
||||||
window.editUser = editUser;
|
window.editUser = editUser;
|
||||||
|
|||||||
@@ -148,5 +148,88 @@
|
|||||||
return response.json();
|
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);
|
console.log('API 설정 완료:', window.API_BASE_URL);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -425,40 +425,7 @@ window.updateProgressSteps = function(currentStepNumber) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 토스트 메시지 (간단 버전)
|
// showToast → api-base.js 전역 사용
|
||||||
window.showToast = function(message, type = 'info', duration = 3000) {
|
|
||||||
console.log(`[Toast] ${type}: ${message}`);
|
|
||||||
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast-message');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 토스트 생성
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast-message toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
toast.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
right: 20px;
|
|
||||||
padding: 12px 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
color: white;
|
|
||||||
font-size: 14px;
|
|
||||||
z-index: 10000;
|
|
||||||
animation: slideIn 0.3s ease;
|
|
||||||
background-color: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : type === 'warning' ? '#f59e0b' : '#3b82f6'};
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.animation = 'slideOut 0.3s ease';
|
|
||||||
setTimeout(() => toast.remove(), 300);
|
|
||||||
}, duration);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 다이얼로그
|
// 확인 다이얼로그
|
||||||
window.showConfirmDialog = function(message, onConfirm, onCancel) {
|
window.showConfirmDialog = function(message, onConfirm, onCancel) {
|
||||||
|
|||||||
@@ -7,21 +7,11 @@ let selectedWorkers = new Set();
|
|||||||
|
|
||||||
// 페이지 초기화
|
// 페이지 초기화
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
await waitForApiConfig();
|
await waitForApi();
|
||||||
await loadDepartments();
|
await loadDepartments();
|
||||||
});
|
});
|
||||||
|
|
||||||
// API 설정 로드 대기
|
// waitForApi → api-base.js 전역 사용
|
||||||
async function waitForApiConfig() {
|
|
||||||
let retryCount = 0;
|
|
||||||
while (!window.apiCall && retryCount < 50) {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
|
||||||
retryCount++;
|
|
||||||
}
|
|
||||||
if (!window.apiCall) {
|
|
||||||
console.error('API 설정 로드 실패');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 부서 목록 로드
|
// 부서 목록 로드
|
||||||
async function loadDepartments() {
|
async function loadDepartments() {
|
||||||
|
|||||||
@@ -33,24 +33,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API 설정 후 데이터 로드
|
// API 설정 후 데이터 로드
|
||||||
waitForApiConfig().then(() => {
|
waitForApi().then(() => {
|
||||||
loadEquipmentData();
|
loadEquipmentData();
|
||||||
loadFactories();
|
loadFactories();
|
||||||
loadRepairCategories();
|
loadRepairCategories();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// API 설정 대기
|
// waitForApi → api-base.js 전역 사용
|
||||||
function waitForApiConfig() {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const check = setInterval(() => {
|
|
||||||
if (window.API_BASE_URL) {
|
|
||||||
clearInterval(check);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}, 50);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 뒤로가기
|
// 뒤로가기
|
||||||
function goBack() {
|
function goBack() {
|
||||||
|
|||||||
@@ -138,14 +138,7 @@ function renderWorkStatus(workers) {
|
|||||||
container.innerHTML = html;
|
container.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🍞 토스트 메시지 (기존 modern-dashboard.js에 있다면 중복 주의, 없으면 사용)
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
if (window.showToast) {
|
|
||||||
window.showToast(message, type);
|
|
||||||
} else {
|
|
||||||
alert(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 초기화
|
// 초기화
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|||||||
@@ -300,22 +300,7 @@ async function loadWorkerOptions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showToast(message) {
|
// showToast → api-base.js 전역 사용
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.textContent = message;
|
|
||||||
toast.style.position = 'fixed';
|
|
||||||
toast.style.bottom = '30px';
|
|
||||||
toast.style.left = '50%';
|
|
||||||
toast.style.transform = 'translateX(-50%)';
|
|
||||||
toast.style.background = '#323232';
|
|
||||||
toast.style.color = '#fff';
|
|
||||||
toast.style.padding = '10px 20px';
|
|
||||||
toast.style.borderRadius = '6px';
|
|
||||||
toast.style.fontSize = '14px';
|
|
||||||
toast.style.zIndex = 9999;
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
setTimeout(() => toast.remove(), 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== 페이지 접근 권한 관리 ==========
|
// ========== 페이지 접근 권한 관리 ==========
|
||||||
|
|
||||||
|
|||||||
@@ -18,21 +18,7 @@
|
|||||||
var workplacesByCategory = {};
|
var workplacesByCategory = {};
|
||||||
|
|
||||||
// ==================== 유틸리티 ====================
|
// ==================== 유틸리티 ====================
|
||||||
|
// escapeHtml, waitForApi → api-base.js 전역 사용
|
||||||
// escapeHtml은 api-base.js에서 window.escapeHtml로 전역 제공
|
|
||||||
|
|
||||||
function waitForApi(timeout) {
|
|
||||||
timeout = timeout || 5000;
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
if (window.apiCall) return resolve();
|
|
||||||
var elapsed = 0;
|
|
||||||
var interval = setInterval(function() {
|
|
||||||
elapsed += 50;
|
|
||||||
if (window.apiCall) { clearInterval(interval); resolve(); }
|
|
||||||
else if (elapsed >= timeout) { clearInterval(interval); reject(new Error('apiCall timeout')); }
|
|
||||||
}, 50);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 데이터 그룹핑 ====================
|
// ==================== 데이터 그룹핑 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -806,35 +806,7 @@ function showErrorState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 토스트 알림 ========== //
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info', duration = 3000) {
|
|
||||||
if (!elements.toastContainer) return;
|
|
||||||
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast ${type}`;
|
|
||||||
|
|
||||||
const iconMap = {
|
|
||||||
success: '✅',
|
|
||||||
error: '❌',
|
|
||||||
warning: '⚠️',
|
|
||||||
info: 'ℹ️'
|
|
||||||
};
|
|
||||||
|
|
||||||
toast.innerHTML = `
|
|
||||||
<div class="toast-icon">${iconMap[type] || 'ℹ️'}</div>
|
|
||||||
<div class="toast-message">${message}</div>
|
|
||||||
<button class="toast-close" onclick="this.parentElement.remove()">×</button>
|
|
||||||
`;
|
|
||||||
|
|
||||||
elements.toastContainer.appendChild(toast);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentElement) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== 작업자 관련 액션 함수들 ========== //
|
// ========== 작업자 관련 액션 함수들 ========== //
|
||||||
function openWorkerModal(workerId, workerName) {
|
function openWorkerModal(workerId, workerName) {
|
||||||
@@ -1388,7 +1360,6 @@ async function handleModalVacation(vacationType) {
|
|||||||
|
|
||||||
// ========== 전역 함수 (HTML에서 호출) ========== //
|
// ========== 전역 함수 (HTML에서 호출) ========== //
|
||||||
window.loadDashboardData = loadDashboardData;
|
window.loadDashboardData = loadDashboardData;
|
||||||
window.showToast = showToast;
|
|
||||||
window.updateSummaryCards = updateSummaryCards;
|
window.updateSummaryCards = updateSummaryCards;
|
||||||
window.displayWorkers = displayWorkers;
|
window.displayWorkers = displayWorkers;
|
||||||
window.openWorkerModal = openWorkerModal;
|
window.openWorkerModal = openWorkerModal;
|
||||||
|
|||||||
@@ -557,59 +557,7 @@ async function deleteProjectById(projectId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 토스트 메시지 표시
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 토스트 생성
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
// 스타일 적용
|
|
||||||
Object.assign(toast.style, {
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
padding: '12px 24px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: '500',
|
|
||||||
zIndex: '1000',
|
|
||||||
transform: 'translateX(100%)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 타입별 배경색
|
|
||||||
const colors = {
|
|
||||||
success: '#10b981',
|
|
||||||
error: '#ef4444',
|
|
||||||
warning: '#f59e0b',
|
|
||||||
info: '#3b82f6'
|
|
||||||
};
|
|
||||||
toast.style.backgroundColor = colors[type] || colors.info;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
// 애니메이션
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(0)';
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(100%)';
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentNode) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 전역 함수로 노출
|
// 전역 함수로 노출
|
||||||
window.openProjectModal = openProjectModal;
|
window.openProjectModal = openProjectModal;
|
||||||
|
|||||||
@@ -831,42 +831,7 @@ async function addInlineCheck(tabType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// showToast → api-base.js 전역 사용
|
||||||
* 토스트 메시지 표시
|
|
||||||
*/
|
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast-message');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast-message toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
toast.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
padding: 12px 24px;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
z-index: 9999;
|
|
||||||
animation: fadeInUp 0.3s ease;
|
|
||||||
${type === 'success' ? 'background: #10b981; color: white;' : ''}
|
|
||||||
${type === 'error' ? 'background: #ef4444; color: white;' : ''}
|
|
||||||
${type === 'info' ? 'background: #3b82f6; color: white;' : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.animation = 'fadeOut 0.3s ease';
|
|
||||||
setTimeout(() => toast.remove(), 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 모달 외부 클릭 시 닫기
|
// 모달 외부 클릭 시 닫기
|
||||||
document.getElementById('checkModal')?.addEventListener('click', function(e) {
|
document.getElementById('checkModal')?.addEventListener('click', function(e) {
|
||||||
|
|||||||
@@ -4,85 +4,7 @@ let currentStatus = 'pending';
|
|||||||
let requests = [];
|
let requests = [];
|
||||||
let currentRejectRequestId = null;
|
let currentRejectRequestId = null;
|
||||||
|
|
||||||
// ==================== Toast 알림 ====================
|
// showToast → api-base.js 전역 사용
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 초기화 ====================
|
// ==================== 초기화 ====================
|
||||||
|
|
||||||
@@ -436,7 +358,6 @@ function startTraining(requestId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 전역 함수로 노출
|
// 전역 함수로 노출
|
||||||
window.showToast = showToast;
|
|
||||||
window.switchTab = switchTab;
|
window.switchTab = switchTab;
|
||||||
window.viewDetail = viewDetail;
|
window.viewDetail = viewDetail;
|
||||||
window.closeDetailModal = closeDetailModal;
|
window.closeDetailModal = closeDetailModal;
|
||||||
|
|||||||
@@ -8,85 +8,7 @@ let isDrawing = false;
|
|||||||
let hasSignature = false;
|
let hasSignature = false;
|
||||||
let savedSignatures = []; // 저장된 서명 목록
|
let savedSignatures = []; // 저장된 서명 목록
|
||||||
|
|
||||||
// ==================== Toast 알림 ====================
|
// showToast → api-base.js 전역 사용
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 초기화 ====================
|
// ==================== 초기화 ====================
|
||||||
|
|
||||||
@@ -544,7 +466,6 @@ function goBack() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 전역 함수로 노출
|
// 전역 함수로 노출
|
||||||
window.showToast = showToast;
|
|
||||||
window.clearSignature = clearSignature;
|
window.clearSignature = clearSignature;
|
||||||
window.saveSignature = saveSignature;
|
window.saveSignature = saveSignature;
|
||||||
window.deleteSignature = deleteSignature;
|
window.deleteSignature = deleteSignature;
|
||||||
|
|||||||
@@ -358,31 +358,7 @@ function formatDate(dateString) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 토스트 알림
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
toast.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
top: 20px;
|
|
||||||
right: 20px;
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
|
|
||||||
color: white;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
||||||
z-index: 10000;
|
|
||||||
animation: slideIn 0.3s ease-out;
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.animation = 'slideOut 0.3s ease-out';
|
|
||||||
setTimeout(() => toast.remove(), 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 공정 관리 ====================
|
// ==================== 공정 관리 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
document.addEventListener('DOMContentLoaded', async function() {
|
document.addEventListener('DOMContentLoaded', async function() {
|
||||||
try {
|
try {
|
||||||
// apiCall이 준비될 때까지 대기
|
// apiCall이 준비될 때까지 대기
|
||||||
await waitForApiCall();
|
await waitForApi();
|
||||||
|
|
||||||
// 초기 데이터 로드
|
// 초기 데이터 로드
|
||||||
await window.TbmAPI.loadInitialData();
|
await window.TbmAPI.loadInitialData();
|
||||||
@@ -68,22 +68,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function waitForApiCall() {
|
// waitForApi → api-base.js 전역 사용
|
||||||
return new Promise(function(resolve) {
|
|
||||||
if (typeof window.apiCall === 'function') {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var checks = 0;
|
|
||||||
var interval = setInterval(function() {
|
|
||||||
checks++;
|
|
||||||
if (typeof window.apiCall === 'function' || checks > 50) {
|
|
||||||
clearInterval(interval);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 네비게이션 ====================
|
// ==================== 네비게이션 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -1005,13 +1005,7 @@ window.saveTbmSession = saveTbmSession;
|
|||||||
|
|
||||||
// ==================== 작업자 관리 ====================
|
// ==================== 작업자 관리 ====================
|
||||||
|
|
||||||
// UUID 생성 함수
|
// generateUUID → api-base.js 전역 사용
|
||||||
function generateUUID() {
|
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
||||||
const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
||||||
return v.toString(16);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 작업자 카드 리스트 렌더링
|
// 작업자 카드 리스트 렌더링
|
||||||
function renderWorkerTaskList() {
|
function renderWorkerTaskList() {
|
||||||
@@ -3081,46 +3075,4 @@ async function saveHandover() {
|
|||||||
}
|
}
|
||||||
window.saveHandover = saveHandover;
|
window.saveHandover = saveHandover;
|
||||||
|
|
||||||
// 토스트 알림
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info', duration = 3000) {
|
|
||||||
const container = document.getElementById('toastContainer');
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast ${type}`;
|
|
||||||
|
|
||||||
const iconMap = {
|
|
||||||
success: '✅',
|
|
||||||
error: '❌',
|
|
||||||
warning: '⚠️',
|
|
||||||
info: 'ℹ️'
|
|
||||||
};
|
|
||||||
|
|
||||||
toast.innerHTML = `
|
|
||||||
<div class="toast-icon">${iconMap[type] || 'ℹ️'}</div>
|
|
||||||
<div class="toast-message">${message}</div>
|
|
||||||
<button class="toast-close" onclick="this.parentElement.remove()">×</button>
|
|
||||||
`;
|
|
||||||
|
|
||||||
toast.style.cssText = `
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
padding: 1rem 1.25rem;
|
|
||||||
background: white;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
min-width: 300px;
|
|
||||||
animation: slideIn 0.3s ease-out;
|
|
||||||
`;
|
|
||||||
|
|
||||||
container.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentElement) {
|
|
||||||
toast.style.animation = 'slideOut 0.3s ease-out';
|
|
||||||
setTimeout(() => toast.remove(), 300);
|
|
||||||
}
|
|
||||||
}, duration);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -173,56 +173,8 @@ class TbmUtils {
|
|||||||
// 전역 인스턴스 생성
|
// 전역 인스턴스 생성
|
||||||
window.TbmUtils = new TbmUtils();
|
window.TbmUtils = new TbmUtils();
|
||||||
|
|
||||||
// 하위 호환성: 기존 함수들
|
// 하위 호환성: TBM 전용 유틸 (showToast, formatDate, waitForApi, generateUUID는 api-base.js 전역)
|
||||||
window.getTodayKST = () => window.TbmUtils.getTodayKST();
|
window.getTodayKST = () => window.TbmUtils.getTodayKST();
|
||||||
window.formatDate = (dateString) => window.TbmUtils.formatDate(dateString);
|
|
||||||
|
|
||||||
// 토스트 알림
|
|
||||||
window.showToast = function(message, type = 'info', duration = 3000) {
|
|
||||||
const container = document.getElementById('toastContainer');
|
|
||||||
if (!container) {
|
|
||||||
console.log(`[Toast] ${type}: ${message}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast ${type}`;
|
|
||||||
|
|
||||||
const iconMap = {
|
|
||||||
success: '✅',
|
|
||||||
error: '❌',
|
|
||||||
warning: '⚠️',
|
|
||||||
info: 'ℹ️'
|
|
||||||
};
|
|
||||||
|
|
||||||
toast.innerHTML = `
|
|
||||||
<div class="toast-icon">${iconMap[type] || 'ℹ️'}</div>
|
|
||||||
<div class="toast-message">${message}</div>
|
|
||||||
<button class="toast-close" onclick="this.parentElement.remove()">×</button>
|
|
||||||
`;
|
|
||||||
|
|
||||||
toast.style.cssText = `
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
padding: 1rem 1.25rem;
|
|
||||||
background: white;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
min-width: 300px;
|
|
||||||
animation: slideIn 0.3s ease-out;
|
|
||||||
`;
|
|
||||||
|
|
||||||
container.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentElement) {
|
|
||||||
toast.style.animation = 'slideOut 0.3s ease-out';
|
|
||||||
setTimeout(() => toast.remove(), 300);
|
|
||||||
}
|
|
||||||
}, duration);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 카테고리별 그룹화
|
// 카테고리별 그룹화
|
||||||
window.groupChecksByCategory = function(checks) {
|
window.groupChecksByCategory = function(checks) {
|
||||||
|
|||||||
@@ -840,25 +840,4 @@ function closeModals() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// showToast → api-base.js 전역 사용
|
||||||
* 토스트 메시지
|
|
||||||
*/
|
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
const container = document.getElementById('toastContainer');
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
container.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.classList.add('show');
|
|
||||||
}, 10);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.classList.remove('show');
|
|
||||||
setTimeout(() => {
|
|
||||||
container.removeChild(toast);
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,94 +10,7 @@ let canvas = null;
|
|||||||
let ctx = null;
|
let ctx = null;
|
||||||
let layoutImage = null;
|
let layoutImage = null;
|
||||||
|
|
||||||
// ==================== Toast 알림 ====================
|
// showToast, createToastContainer → api-base.js 전역 사용
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 초기화 ====================
|
// ==================== 초기화 ====================
|
||||||
|
|
||||||
@@ -523,7 +436,6 @@ function resetForm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 전역 함수로 노출
|
// 전역 함수로 노출
|
||||||
window.showToast = showToast;
|
|
||||||
window.openMapModal = openMapModal;
|
window.openMapModal = openMapModal;
|
||||||
window.closeMapModal = closeMapModal;
|
window.closeMapModal = closeMapModal;
|
||||||
window.loadWorkplaceMap = loadWorkplaceMap;
|
window.loadWorkplaceMap = loadWorkplaceMap;
|
||||||
|
|||||||
@@ -740,59 +740,7 @@ function formatDate(date) {
|
|||||||
return `${year}-${month}-${day}`;
|
return `${year}-${month}-${day}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 토스트 메시지 표시
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 토스트 생성
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
// 스타일 적용
|
|
||||||
Object.assign(toast.style, {
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
padding: '12px 24px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: '500',
|
|
||||||
zIndex: '10000',
|
|
||||||
transform: 'translateX(100%)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 타입별 배경색
|
|
||||||
const colors = {
|
|
||||||
success: '#10b981',
|
|
||||||
error: '#ef4444',
|
|
||||||
warning: '#f59e0b',
|
|
||||||
info: '#3b82f6'
|
|
||||||
};
|
|
||||||
toast.style.backgroundColor = colors[type] || colors.info;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
// 애니메이션
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(0)';
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(100%)';
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentNode) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 전역 함수로 노출
|
// 전역 함수로 노출
|
||||||
window.switchAnalysisMode = switchAnalysisMode;
|
window.switchAnalysisMode = switchAnalysisMode;
|
||||||
|
|||||||
@@ -172,59 +172,7 @@ function navigateToPage(url) {
|
|||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 토스트 메시지 표시
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 토스트 생성
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
// 스타일 적용
|
|
||||||
Object.assign(toast.style, {
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
padding: '12px 24px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: '500',
|
|
||||||
zIndex: '1000',
|
|
||||||
transform: 'translateX(100%)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 타입별 배경색
|
|
||||||
const colors = {
|
|
||||||
success: '#10b981',
|
|
||||||
error: '#ef4444',
|
|
||||||
warning: '#f59e0b',
|
|
||||||
info: '#3b82f6'
|
|
||||||
};
|
|
||||||
toast.style.backgroundColor = colors[type] || colors.info;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
// 애니메이션
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(0)';
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(100%)';
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentNode) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 전역 함수로 노출
|
// 전역 함수로 노출
|
||||||
window.navigateToPage = navigateToPage;
|
window.navigateToPage = navigateToPage;
|
||||||
|
|||||||
@@ -10,21 +10,11 @@ let currentEditingWorker = null;
|
|||||||
// 페이지 초기화
|
// 페이지 초기화
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
console.log('👥 작업자 관리 페이지 초기화 시작');
|
console.log('👥 작업자 관리 페이지 초기화 시작');
|
||||||
await waitForApiConfig();
|
await waitForApi();
|
||||||
await loadDepartments();
|
await loadDepartments();
|
||||||
});
|
});
|
||||||
|
|
||||||
// API 설정 로드 대기
|
// waitForApi → api-base.js 전역 사용
|
||||||
async function waitForApiConfig() {
|
|
||||||
let retryCount = 0;
|
|
||||||
while (!window.apiCall && retryCount < 50) {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
|
||||||
retryCount++;
|
|
||||||
}
|
|
||||||
if (!window.apiCall) {
|
|
||||||
console.error('API 설정 로드 실패');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 부서 관련 함수
|
// 부서 관련 함수
|
||||||
@@ -573,53 +563,7 @@ function formatDate(dateString) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 토스트 메시지 표시
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
const existingToast = document.querySelector('.toast');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
Object.assign(toast.style, {
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
padding: '12px 24px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: '500',
|
|
||||||
zIndex: '10000',
|
|
||||||
transform: 'translateX(100%)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
});
|
|
||||||
|
|
||||||
const colors = {
|
|
||||||
success: '#10b981',
|
|
||||||
error: '#ef4444',
|
|
||||||
warning: '#f59e0b',
|
|
||||||
info: '#3b82f6'
|
|
||||||
};
|
|
||||||
toast.style.backgroundColor = colors[type] || colors.info;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(0)';
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(100%)';
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentNode) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 전역 함수 노출
|
// 전역 함수 노출
|
||||||
|
|||||||
@@ -903,59 +903,7 @@ function formatDate(dateString) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 토스트 메시지 표시
|
// showToast → api-base.js 전역 사용
|
||||||
function showToast(message, type = 'info') {
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 토스트 생성
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
// 스타일 적용
|
|
||||||
Object.assign(toast.style, {
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
padding: '12px 24px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: '500',
|
|
||||||
zIndex: '1000',
|
|
||||||
transform: 'translateX(100%)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 타입별 배경색
|
|
||||||
const colors = {
|
|
||||||
success: '#10b981',
|
|
||||||
error: '#ef4444',
|
|
||||||
warning: '#f59e0b',
|
|
||||||
info: '#3b82f6'
|
|
||||||
};
|
|
||||||
toast.style.backgroundColor = colors[type] || colors.info;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
// 애니메이션
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(0)';
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(100%)';
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentNode) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 전역 함수 및 변수로 노출 (다른 모듈에서 접근 가능하도록)
|
// 전역 함수 및 변수로 노출 (다른 모듈에서 접근 가능하도록)
|
||||||
// 모듈 시스템이 이미 정의했으면 건너뜀
|
// 모듈 시스템이 이미 정의했으면 건너뜀
|
||||||
@@ -1604,7 +1552,6 @@ window.saveWorkplace = saveWorkplace;
|
|||||||
window.deleteWorkplace = deleteWorkplace;
|
window.deleteWorkplace = deleteWorkplace;
|
||||||
window.confirmDeleteWorkplace = confirmDeleteWorkplace;
|
window.confirmDeleteWorkplace = confirmDeleteWorkplace;
|
||||||
window.refreshWorkplaces = refreshWorkplaces;
|
window.refreshWorkplaces = refreshWorkplaces;
|
||||||
window.showToast = showToast;
|
|
||||||
window.loadCategories = loadCategories;
|
window.loadCategories = loadCategories;
|
||||||
window.updateLayoutPreview = updateLayoutPreview;
|
window.updateLayoutPreview = updateLayoutPreview;
|
||||||
window.openWorkplaceMapModal = openWorkplaceMapModal;
|
window.openWorkplaceMapModal = openWorkplaceMapModal;
|
||||||
|
|||||||
@@ -94,61 +94,6 @@ class WorkplaceUtils {
|
|||||||
// 전역 인스턴스 생성
|
// 전역 인스턴스 생성
|
||||||
window.WorkplaceUtils = new WorkplaceUtils();
|
window.WorkplaceUtils = new WorkplaceUtils();
|
||||||
|
|
||||||
// 하위 호환성: 기존 함수들
|
// showToast, formatDate → api-base.js 전역 사용
|
||||||
window.formatDate = (dateString) => window.WorkplaceUtils.formatDate(dateString);
|
|
||||||
|
|
||||||
// 토스트 메시지 표시
|
|
||||||
window.showToast = function(message, type = 'info') {
|
|
||||||
// 기존 토스트 제거
|
|
||||||
const existingToast = document.querySelector('.toast');
|
|
||||||
if (existingToast) {
|
|
||||||
existingToast.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새 토스트 생성
|
|
||||||
const toast = document.createElement('div');
|
|
||||||
toast.className = `toast toast-${type}`;
|
|
||||||
toast.textContent = message;
|
|
||||||
|
|
||||||
// 스타일 적용
|
|
||||||
Object.assign(toast.style, {
|
|
||||||
position: 'fixed',
|
|
||||||
top: '20px',
|
|
||||||
right: '20px',
|
|
||||||
padding: '12px 24px',
|
|
||||||
borderRadius: '8px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: '500',
|
|
||||||
zIndex: '1000',
|
|
||||||
transform: 'translateX(100%)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 타입별 배경색
|
|
||||||
const colors = {
|
|
||||||
success: '#10b981',
|
|
||||||
error: '#ef4444',
|
|
||||||
warning: '#f59e0b',
|
|
||||||
info: '#3b82f6'
|
|
||||||
};
|
|
||||||
toast.style.backgroundColor = colors[type] || colors.info;
|
|
||||||
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
|
|
||||||
// 애니메이션
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(0)';
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 자동 제거
|
|
||||||
setTimeout(() => {
|
|
||||||
toast.style.transform = 'translateX(100%)';
|
|
||||||
setTimeout(() => {
|
|
||||||
if (toast.parentNode) {
|
|
||||||
toast.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}, 3000);
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('[Module] workplace-management/utils.js 로드 완료');
|
console.log('[Module] workplace-management/utils.js 로드 완료');
|
||||||
|
|||||||
Reference in New Issue
Block a user