refactor: 코드 관리 페이지 삭제 및 프론트엔드 모듈화
- codes.html, code-management.js 삭제 (tasks.html에서 동일 기능 제공) - 사이드바에서 코드 관리 링크 제거 - daily-work-report, tbm, workplace-management JS 모듈 분리 - common/security.js 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
489
web-ui/js/tbm/api.js
Normal file
489
web-ui/js/tbm/api.js
Normal file
@@ -0,0 +1,489 @@
|
||||
/**
|
||||
* TBM - API Client
|
||||
* TBM 관련 모든 API 호출을 관리
|
||||
*/
|
||||
|
||||
class TbmAPI {
|
||||
constructor() {
|
||||
this.state = window.TbmState;
|
||||
this.utils = window.TbmUtils;
|
||||
console.log('[TbmAPI] 초기화 완료');
|
||||
}
|
||||
|
||||
/**
|
||||
* 초기 데이터 로드 (작업자, 프로젝트, 안전 체크리스트, 공정, 작업, 작업장)
|
||||
*/
|
||||
async loadInitialData() {
|
||||
try {
|
||||
// 현재 로그인한 사용자 정보 가져오기
|
||||
const userInfo = JSON.parse(localStorage.getItem('user') || '{}');
|
||||
this.state.currentUser = userInfo;
|
||||
console.log('👤 로그인 사용자:', this.state.currentUser, 'worker_id:', this.state.currentUser?.worker_id);
|
||||
|
||||
// 병렬로 데이터 로드
|
||||
await Promise.all([
|
||||
this.loadWorkers(),
|
||||
this.loadProjects(),
|
||||
this.loadSafetyChecks(),
|
||||
this.loadWorkTypes(),
|
||||
this.loadTasks(),
|
||||
this.loadWorkplaces(),
|
||||
this.loadWorkplaceCategories()
|
||||
]);
|
||||
|
||||
console.log('✅ 초기 데이터 로드 완료');
|
||||
} catch (error) {
|
||||
console.error('❌ 초기 데이터 로드 오류:', error);
|
||||
window.showToast?.('데이터를 불러오는 중 오류가 발생했습니다.', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업자 목록 로드 (생산팀 소속만)
|
||||
*/
|
||||
async loadWorkers() {
|
||||
try {
|
||||
const response = await window.apiCall('/workers?limit=1000&department_id=1');
|
||||
if (response) {
|
||||
let workers = Array.isArray(response) ? response : (response.data || []);
|
||||
// 활성 상태인 작업자만 필터링
|
||||
workers = workers.filter(w => w.status === 'active' && w.employment_status === 'employed');
|
||||
this.state.allWorkers = workers;
|
||||
console.log('✅ 작업자 목록 로드:', workers.length + '명');
|
||||
return workers;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 작업자 로딩 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 프로젝트 목록 로드 (활성 프로젝트만)
|
||||
*/
|
||||
async loadProjects() {
|
||||
try {
|
||||
const response = await window.apiCall('/projects?is_active=1');
|
||||
if (response) {
|
||||
const projects = Array.isArray(response) ? response : (response.data || []);
|
||||
this.state.allProjects = projects.filter(p =>
|
||||
p.is_active === 1 || p.is_active === true || p.is_active === '1'
|
||||
);
|
||||
console.log('✅ 프로젝트 목록 로드:', this.state.allProjects.length + '개 (활성)');
|
||||
return this.state.allProjects;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 프로젝트 로딩 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 안전 체크리스트 로드
|
||||
*/
|
||||
async loadSafetyChecks() {
|
||||
try {
|
||||
const response = await window.apiCall('/tbm/safety-checks');
|
||||
if (response && response.success) {
|
||||
this.state.allSafetyChecks = response.data;
|
||||
console.log('✅ 안전 체크리스트 로드:', this.state.allSafetyChecks.length + '개');
|
||||
return this.state.allSafetyChecks;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 안전 체크리스트 로딩 오류:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 공정(Work Types) 목록 로드
|
||||
*/
|
||||
async loadWorkTypes() {
|
||||
try {
|
||||
const response = await window.apiCall('/daily-work-reports/work-types');
|
||||
if (response && response.success) {
|
||||
this.state.allWorkTypes = response.data || [];
|
||||
console.log('✅ 공정 목록 로드:', this.state.allWorkTypes.length + '개');
|
||||
return this.state.allWorkTypes;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 공정 로딩 오류:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업(Tasks) 목록 로드
|
||||
*/
|
||||
async loadTasks() {
|
||||
try {
|
||||
const response = await window.apiCall('/tasks/active/list');
|
||||
if (response && response.success) {
|
||||
this.state.allTasks = response.data || [];
|
||||
console.log('✅ 작업 목록 로드:', this.state.allTasks.length + '개');
|
||||
return this.state.allTasks;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 작업 로딩 오류:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업장 목록 로드
|
||||
*/
|
||||
async loadWorkplaces() {
|
||||
try {
|
||||
const response = await window.apiCall('/workplaces?is_active=true');
|
||||
if (response && response.success) {
|
||||
this.state.allWorkplaces = response.data || [];
|
||||
console.log('✅ 작업장 목록 로드:', this.state.allWorkplaces.length + '개');
|
||||
return this.state.allWorkplaces;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 작업장 로딩 오류:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업장 카테고리 로드
|
||||
*/
|
||||
async loadWorkplaceCategories() {
|
||||
try {
|
||||
const response = await window.apiCall('/workplaces/categories/active/list');
|
||||
if (response && response.success) {
|
||||
this.state.allWorkplaceCategories = response.data || [];
|
||||
console.log('✅ 작업장 카테고리 로드:', this.state.allWorkplaceCategories.length + '개');
|
||||
return this.state.allWorkplaceCategories;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 작업장 카테고리 로딩 오류:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 오늘의 TBM만 로드 (TBM 입력 탭용)
|
||||
*/
|
||||
async loadTodayOnlyTbm() {
|
||||
const today = this.utils.getTodayKST();
|
||||
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/date/${today}`);
|
||||
|
||||
if (response && response.success) {
|
||||
this.state.todaySessions = response.data || [];
|
||||
} else {
|
||||
this.state.todaySessions = [];
|
||||
}
|
||||
console.log('✅ 오늘 TBM 로드:', this.state.todaySessions.length + '건');
|
||||
return this.state.todaySessions;
|
||||
} catch (error) {
|
||||
console.error('❌ 오늘 TBM 조회 오류:', error);
|
||||
window.showToast?.('오늘 TBM을 불러오는 중 오류가 발생했습니다.', 'error');
|
||||
this.state.todaySessions = [];
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 TBM을 날짜별로 그룹화하여 로드
|
||||
*/
|
||||
async loadRecentTbmGroupedByDate() {
|
||||
try {
|
||||
const today = new Date();
|
||||
const dates = [];
|
||||
|
||||
// 최근 N일의 날짜 생성
|
||||
for (let i = 0; i < this.state.loadedDaysCount; i++) {
|
||||
const date = new Date(today);
|
||||
date.setDate(date.getDate() - i);
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
dates.push(dateStr);
|
||||
}
|
||||
|
||||
// 각 날짜의 TBM 로드
|
||||
this.state.dateGroupedSessions = {};
|
||||
this.state.allLoadedSessions = [];
|
||||
|
||||
const promises = dates.map(date => window.apiCall(`/tbm/sessions/date/${date}`));
|
||||
const results = await Promise.all(promises);
|
||||
|
||||
results.forEach((response, index) => {
|
||||
const date = dates[index];
|
||||
if (response && response.success && response.data && response.data.length > 0) {
|
||||
let sessions = response.data;
|
||||
|
||||
// admin이 아니면 본인이 작성한 TBM만 필터링
|
||||
if (!this.state.isAdminUser()) {
|
||||
const userId = this.state.currentUser?.user_id;
|
||||
const workerId = this.state.currentUser?.worker_id;
|
||||
sessions = sessions.filter(s => {
|
||||
return s.created_by === userId ||
|
||||
s.leader_id === workerId ||
|
||||
s.created_by_name === this.state.currentUser?.name;
|
||||
});
|
||||
}
|
||||
|
||||
if (sessions.length > 0) {
|
||||
this.state.dateGroupedSessions[date] = sessions;
|
||||
this.state.allLoadedSessions = this.state.allLoadedSessions.concat(sessions);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('✅ 날짜별 TBM 로드 완료:', this.state.allLoadedSessions.length + '건');
|
||||
return this.state.dateGroupedSessions;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 날짜별 로드 오류:', error);
|
||||
window.showToast?.('TBM을 불러오는 중 오류가 발생했습니다.', 'error');
|
||||
this.state.dateGroupedSessions = {};
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 날짜의 TBM 세션 목록 로드
|
||||
*/
|
||||
async loadTbmSessionsByDate(date) {
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/date/${date}`);
|
||||
|
||||
if (response && response.success) {
|
||||
this.state.allSessions = response.data || [];
|
||||
} else {
|
||||
this.state.allSessions = [];
|
||||
}
|
||||
return this.state.allSessions;
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 세션 조회 오류:', error);
|
||||
window.showToast?.('TBM 세션을 불러오는 중 오류가 발생했습니다.', 'error');
|
||||
this.state.allSessions = [];
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 세션 생성
|
||||
*/
|
||||
async createTbmSession(sessionData) {
|
||||
try {
|
||||
const response = await window.apiCall('/tbm/sessions', 'POST', sessionData);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '세션 생성 실패');
|
||||
}
|
||||
console.log('✅ TBM 세션 생성 완료:', response.data?.session_id);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 세션 생성 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 세션 정보 조회
|
||||
*/
|
||||
async getSession(sessionId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/${sessionId}`);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '세션 조회 실패');
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 세션 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 팀원 조회
|
||||
*/
|
||||
async getTeamMembers(sessionId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/${sessionId}/team`);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '팀원 조회 실패');
|
||||
}
|
||||
return response.data || [];
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 팀원 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 팀원 일괄 추가
|
||||
*/
|
||||
async addTeamMembers(sessionId, members) {
|
||||
try {
|
||||
const response = await window.apiCall(
|
||||
`/tbm/sessions/${sessionId}/team/batch`,
|
||||
'POST',
|
||||
{ members }
|
||||
);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '팀원 추가 실패');
|
||||
}
|
||||
console.log('✅ TBM 팀원 추가 완료:', members.length + '명');
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 팀원 추가 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 팀원 전체 삭제
|
||||
*/
|
||||
async clearTeamMembers(sessionId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/${sessionId}/team/clear`, 'DELETE');
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 팀원 삭제 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 안전 체크 조회
|
||||
*/
|
||||
async getSafetyChecks(sessionId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/${sessionId}/safety`);
|
||||
return response?.data || [];
|
||||
} catch (error) {
|
||||
console.error('❌ 안전 체크 조회 오류:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 안전 체크 (필터링된) 조회
|
||||
*/
|
||||
async getFilteredSafetyChecks(sessionId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/tbm/sessions/${sessionId}/safety-checks/filtered`);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '체크리스트를 불러올 수 없습니다.');
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('❌ 필터링된 안전 체크 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 안전 체크 저장
|
||||
*/
|
||||
async saveSafetyChecks(sessionId, records) {
|
||||
try {
|
||||
const response = await window.apiCall(
|
||||
`/tbm/sessions/${sessionId}/safety`,
|
||||
'POST',
|
||||
{ records }
|
||||
);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '저장 실패');
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ 안전 체크 저장 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBM 세션 완료 처리
|
||||
*/
|
||||
async completeTbmSession(sessionId, endTime) {
|
||||
try {
|
||||
const response = await window.apiCall(
|
||||
`/tbm/sessions/${sessionId}/complete`,
|
||||
'POST',
|
||||
{ end_time: endTime }
|
||||
);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '완료 처리 실패');
|
||||
}
|
||||
console.log('✅ TBM 완료 처리:', sessionId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ TBM 완료 처리 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업 인계 저장
|
||||
*/
|
||||
async saveHandover(handoverData) {
|
||||
try {
|
||||
const response = await window.apiCall('/tbm/handovers', 'POST', handoverData);
|
||||
if (!response || !response.success) {
|
||||
throw new Error(response?.message || '인계 요청 실패');
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ 작업 인계 저장 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리별 작업장 로드
|
||||
*/
|
||||
async loadWorkplacesByCategory(categoryId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/workplaces?category_id=${categoryId}`);
|
||||
if (!response || !response.success || !response.data) {
|
||||
return [];
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('❌ 작업장 로드 오류:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업장 지도 영역 로드
|
||||
*/
|
||||
async loadMapRegions(categoryId) {
|
||||
try {
|
||||
const response = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`);
|
||||
if (response && response.success) {
|
||||
this.state.mapRegions = response.data || [];
|
||||
return this.state.mapRegions;
|
||||
}
|
||||
return [];
|
||||
} catch (error) {
|
||||
console.error('❌ 지도 영역 로드 오류:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 전역 인스턴스 생성
|
||||
window.TbmAPI = new TbmAPI();
|
||||
|
||||
// 하위 호환성: 기존 함수들
|
||||
window.loadInitialData = () => window.TbmAPI.loadInitialData();
|
||||
window.loadTodayOnlyTbm = () => window.TbmAPI.loadTodayOnlyTbm();
|
||||
window.loadTodayTbm = () => window.TbmAPI.loadRecentTbmGroupedByDate();
|
||||
window.loadAllTbm = () => {
|
||||
window.TbmState.loadedDaysCount = 30;
|
||||
return window.TbmAPI.loadRecentTbmGroupedByDate();
|
||||
};
|
||||
window.loadRecentTbmGroupedByDate = () => window.TbmAPI.loadRecentTbmGroupedByDate();
|
||||
window.loadTbmSessionsByDate = (date) => window.TbmAPI.loadTbmSessionsByDate(date);
|
||||
window.loadWorkplaceCategories = () => window.TbmAPI.loadWorkplaceCategories();
|
||||
window.loadWorkplacesByCategory = (categoryId) => window.TbmAPI.loadWorkplacesByCategory(categoryId);
|
||||
|
||||
// 더 많은 날짜 로드
|
||||
window.loadMoreTbmDays = async function() {
|
||||
window.TbmState.loadedDaysCount += 7;
|
||||
await window.TbmAPI.loadRecentTbmGroupedByDate();
|
||||
window.showToast?.(`최근 ${window.TbmState.loadedDaysCount}일의 TBM을 로드했습니다.`, 'success');
|
||||
};
|
||||
|
||||
console.log('[Module] tbm/api.js 로드 완료');
|
||||
Reference in New Issue
Block a user