Files
tk-factory-services/system1-factory/web/js/tbm/state.js
Hyungi Ahn 4388628788 refactor: TBM/작업보고 코드 통합 및 API 쿼리 버그 수정
- 공통 유틸리티 추출 (common/utils.js, common/base-state.js)
- TBM 모바일 인라인 JS/CSS 외부 파일로 분리 (tbm-mobile.js, tbm-mobile.css)
- 미사용 코드 삭제 (index.js, work-report-*.js 등 5개 파일)
- TBM/작업보고 state.js, utils.js를 공통 모듈 기반으로 전환
- 작업보고서 SSO 인증 호환 수정 (token/user 함수)
- tbmModel.js: incomplete-reports 쿼리에서 users→sso_users 조인 수정, leader_name 조인 추가
- docker-compose.yml: system1-web 볼륨 마운트 추가
- 모바일 인계(handover) 기능 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 07:51:24 +09:00

323 lines
8.4 KiB
JavaScript

/**
* TBM - State Manager
* TBM 페이지의 전역 상태 관리 (BaseState 상속)
*/
class TbmState extends BaseState {
constructor() {
super();
// 세션 데이터
this.allSessions = [];
this.todaySessions = [];
this.dateGroupedSessions = {};
this.allLoadedSessions = [];
this.loadedDaysCount = 7;
// 마스터 데이터
this.allWorkers = [];
this.allProjects = [];
this.allWorkTypes = [];
this.allTasks = [];
this.allSafetyChecks = [];
this.allWorkplaces = [];
this.allWorkplaceCategories = [];
// 현재 상태
this.currentUser = null;
this.currentSessionId = null;
this.currentTab = 'tbm-input';
// 작업자 관련
this.selectedWorkers = new Set();
this.workerTaskList = [];
this.selectedWorkersInModal = new Set();
this.currentEditingTaskLine = null;
// 작업장 선택 관련
this.selectedCategory = null;
this.selectedWorkplace = null;
this.selectedCategoryName = '';
this.selectedWorkplaceName = '';
// 일괄 설정 관련
this.isBulkMode = false;
this.bulkSelectedWorkers = new Set();
// 지도 관련
this.mapCanvas = null;
this.mapCtx = null;
this.mapImage = null;
this.mapRegions = [];
console.log('[TbmState] 초기화 완료');
}
/**
* Admin 여부 확인
*/
isAdminUser() {
const user = this.getUser();
if (!user) return false;
const role = (user.role || '').toLowerCase();
return role === 'admin' || role === 'system admin' || role === 'system';
}
/**
* 탭 변경
*/
setCurrentTab(tab) {
const prevTab = this.currentTab;
this.currentTab = tab;
this.notifyListeners('currentTab', tab, prevTab);
}
/**
* 작업자 목록에 추가
*/
addWorkerToList(worker) {
this.workerTaskList.push({
worker_id: worker.worker_id,
worker_name: worker.worker_name,
job_type: worker.job_type,
tasks: [this.createEmptyTaskLine()]
});
this.notifyListeners('workerTaskList', this.workerTaskList, null);
}
/**
* 빈 작업 라인 생성
*/
createEmptyTaskLine() {
return {
task_line_id: window.CommonUtils.generateUUID(),
project_id: null,
work_type_id: null,
task_id: null,
workplace_category_id: null,
workplace_id: null,
workplace_category_name: '',
workplace_name: '',
work_detail: null,
is_present: true
};
}
/**
* 작업자에 작업 라인 추가
*/
addTaskLineToWorker(workerIndex) {
if (this.workerTaskList[workerIndex]) {
this.workerTaskList[workerIndex].tasks.push(this.createEmptyTaskLine());
this.notifyListeners('workerTaskList', this.workerTaskList, null);
}
}
/**
* 작업 라인 제거
*/
removeTaskLine(workerIndex, taskIndex) {
if (this.workerTaskList[workerIndex]?.tasks) {
this.workerTaskList[workerIndex].tasks.splice(taskIndex, 1);
this.notifyListeners('workerTaskList', this.workerTaskList, null);
}
}
/**
* 작업자 제거
*/
removeWorkerFromList(workerIndex) {
const removed = this.workerTaskList.splice(workerIndex, 1);
this.notifyListeners('workerTaskList', this.workerTaskList, null);
return removed[0];
}
/**
* 작업장 선택 초기화
*/
resetWorkplaceSelection() {
this.selectedCategory = null;
this.selectedWorkplace = null;
this.selectedCategoryName = '';
this.selectedWorkplaceName = '';
this.mapCanvas = null;
this.mapCtx = null;
this.mapImage = null;
this.mapRegions = [];
}
/**
* 일괄 설정 초기화
*/
resetBulkSettings() {
this.isBulkMode = false;
this.bulkSelectedWorkers.clear();
}
/**
* 날짜별 세션 그룹화
*/
groupSessionsByDate(sessions) {
this.dateGroupedSessions = {};
this.allLoadedSessions = [];
sessions.forEach(session => {
const date = window.CommonUtils.formatDate(session.session_date);
if (!this.dateGroupedSessions[date]) {
this.dateGroupedSessions[date] = [];
}
this.dateGroupedSessions[date].push(session);
this.allLoadedSessions.push(session);
});
}
/**
* 상태 초기화
*/
reset() {
this.workerTaskList = [];
this.selectedWorkers.clear();
this.selectedWorkersInModal.clear();
this.currentEditingTaskLine = null;
this.resetWorkplaceSelection();
this.resetBulkSettings();
}
/**
* 디버그 출력
*/
debug() {
console.log('[TbmState] 현재 상태:', {
allSessions: this.allSessions.length,
todaySessions: this.todaySessions.length,
allWorkers: this.allWorkers.length,
allProjects: this.allProjects.length,
workerTaskList: this.workerTaskList.length,
currentTab: this.currentTab
});
}
}
// 전역 인스턴스 생성
window.TbmState = new TbmState();
// 하위 호환성을 위한 전역 변수 프록시
const tbmStateProxy = window.TbmState;
Object.defineProperties(window, {
allSessions: {
get: () => tbmStateProxy.allSessions,
set: (v) => { tbmStateProxy.allSessions = v; }
},
todaySessions: {
get: () => tbmStateProxy.todaySessions,
set: (v) => { tbmStateProxy.todaySessions = v; }
},
allWorkers: {
get: () => tbmStateProxy.allWorkers,
set: (v) => { tbmStateProxy.allWorkers = v; }
},
allProjects: {
get: () => tbmStateProxy.allProjects,
set: (v) => { tbmStateProxy.allProjects = v; }
},
allWorkTypes: {
get: () => tbmStateProxy.allWorkTypes,
set: (v) => { tbmStateProxy.allWorkTypes = v; }
},
allTasks: {
get: () => tbmStateProxy.allTasks,
set: (v) => { tbmStateProxy.allTasks = v; }
},
allSafetyChecks: {
get: () => tbmStateProxy.allSafetyChecks,
set: (v) => { tbmStateProxy.allSafetyChecks = v; }
},
allWorkplaces: {
get: () => tbmStateProxy.allWorkplaces,
set: (v) => { tbmStateProxy.allWorkplaces = v; }
},
allWorkplaceCategories: {
get: () => tbmStateProxy.allWorkplaceCategories,
set: (v) => { tbmStateProxy.allWorkplaceCategories = v; }
},
currentUser: {
get: () => tbmStateProxy.currentUser,
set: (v) => { tbmStateProxy.currentUser = v; }
},
currentSessionId: {
get: () => tbmStateProxy.currentSessionId,
set: (v) => { tbmStateProxy.currentSessionId = v; }
},
selectedWorkers: {
get: () => tbmStateProxy.selectedWorkers,
set: (v) => { tbmStateProxy.selectedWorkers = v; }
},
workerTaskList: {
get: () => tbmStateProxy.workerTaskList,
set: (v) => { tbmStateProxy.workerTaskList = v; }
},
selectedWorkersInModal: {
get: () => tbmStateProxy.selectedWorkersInModal,
set: (v) => { tbmStateProxy.selectedWorkersInModal = v; }
},
currentEditingTaskLine: {
get: () => tbmStateProxy.currentEditingTaskLine,
set: (v) => { tbmStateProxy.currentEditingTaskLine = v; }
},
selectedCategory: {
get: () => tbmStateProxy.selectedCategory,
set: (v) => { tbmStateProxy.selectedCategory = v; }
},
selectedWorkplace: {
get: () => tbmStateProxy.selectedWorkplace,
set: (v) => { tbmStateProxy.selectedWorkplace = v; }
},
selectedCategoryName: {
get: () => tbmStateProxy.selectedCategoryName,
set: (v) => { tbmStateProxy.selectedCategoryName = v; }
},
selectedWorkplaceName: {
get: () => tbmStateProxy.selectedWorkplaceName,
set: (v) => { tbmStateProxy.selectedWorkplaceName = v; }
},
isBulkMode: {
get: () => tbmStateProxy.isBulkMode,
set: (v) => { tbmStateProxy.isBulkMode = v; }
},
bulkSelectedWorkers: {
get: () => tbmStateProxy.bulkSelectedWorkers,
set: (v) => { tbmStateProxy.bulkSelectedWorkers = v; }
},
dateGroupedSessions: {
get: () => tbmStateProxy.dateGroupedSessions,
set: (v) => { tbmStateProxy.dateGroupedSessions = v; }
},
allLoadedSessions: {
get: () => tbmStateProxy.allLoadedSessions,
set: (v) => { tbmStateProxy.allLoadedSessions = v; }
},
loadedDaysCount: {
get: () => tbmStateProxy.loadedDaysCount,
set: (v) => { tbmStateProxy.loadedDaysCount = v; }
},
mapRegions: {
get: () => tbmStateProxy.mapRegions,
set: (v) => { tbmStateProxy.mapRegions = v; }
},
mapCanvas: {
get: () => tbmStateProxy.mapCanvas,
set: (v) => { tbmStateProxy.mapCanvas = v; }
},
mapCtx: {
get: () => tbmStateProxy.mapCtx,
set: (v) => { tbmStateProxy.mapCtx = v; }
},
mapImage: {
get: () => tbmStateProxy.mapImage,
set: (v) => { tbmStateProxy.mapImage = v; }
}
});
console.log('[Module] tbm/state.js 로드 완료');