Files
tk-factory-services/system1-factory/web/js/daily-work-report/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

301 lines
7.8 KiB
JavaScript

/**
* Daily Work Report - State Manager
* 작업보고서 페이지의 전역 상태 관리 (BaseState 상속)
*/
class DailyWorkReportState extends BaseState {
constructor() {
super();
// 마스터 데이터
this.workTypes = [];
this.workStatusTypes = [];
this.errorTypes = []; // 레거시 호환용
this.issueCategories = []; // 신고 카테고리 (nonconformity)
this.issueItems = []; // 신고 아이템
this.workers = [];
this.projects = [];
// UI 상태
this.selectedWorkers = new Set();
this.workEntryCounter = 0;
this.currentStep = 1;
this.editingWorkId = null;
this.currentTab = 'tbm';
// TBM 관련
this.incompleteTbms = [];
// 부적합 원인 관리
this.currentDefectIndex = null;
this.tempDefects = {}; // { index: [{ error_type_id, defect_hours, note }] }
// 작업장소 지도 관련
this.mapCanvas = null;
this.mapCtx = null;
this.mapImage = null;
this.mapRegions = [];
this.selectedWorkplace = null;
this.selectedWorkplaceName = null;
this.selectedWorkplaceCategory = null;
this.selectedWorkplaceCategoryName = null;
// 시간 선택 관련
this.currentEditingField = null; // { index, type: 'total' | 'error' }
this.currentTimeValue = 0;
// 캐시
this.dailyIssuesCache = {}; // { 'YYYY-MM-DD': [issues] }
console.log('[State] DailyWorkReportState 초기화 완료');
}
/**
* 토큰에서 사용자 정보 추출
*/
getCurrentUser() {
try {
const token = localStorage.getItem('sso_token');
if (!token) return null;
const payloadBase64 = token.split('.')[1];
if (payloadBase64) {
const payload = JSON.parse(atob(payloadBase64));
return payload;
}
} catch (error) {
console.log('[State] 토큰에서 사용자 정보 추출 실패:', error);
}
try {
const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser');
if (userInfo) {
return JSON.parse(userInfo);
}
} catch (error) {
console.log('[State] localStorage에서 사용자 정보 가져오기 실패:', error);
}
return null;
}
/**
* 선택된 작업자 토글
*/
toggleWorkerSelection(workerId) {
if (this.selectedWorkers.has(workerId)) {
this.selectedWorkers.delete(workerId);
} else {
this.selectedWorkers.add(workerId);
}
this.notifyListeners('selectedWorkers', this.selectedWorkers, null);
}
/**
* 작업자 전체 선택/해제
*/
selectAllWorkers(select = true) {
if (select) {
this.workers.forEach(w => this.selectedWorkers.add(w.worker_id));
} else {
this.selectedWorkers.clear();
}
this.notifyListeners('selectedWorkers', this.selectedWorkers, null);
}
/**
* 작업 항목 카운터 증가
*/
incrementWorkEntryCounter() {
this.workEntryCounter++;
return this.workEntryCounter;
}
/**
* 탭 변경
*/
setCurrentTab(tab) {
const prevTab = this.currentTab;
this.currentTab = tab;
this.notifyListeners('currentTab', tab, prevTab);
}
/**
* 부적합 임시 저장소 초기화
*/
initTempDefects(index) {
if (!this.tempDefects[index]) {
this.tempDefects[index] = [];
}
}
/**
* 부적합 추가
*/
addTempDefect(index, defect) {
this.initTempDefects(index);
this.tempDefects[index].push(defect);
this.notifyListeners('tempDefects', this.tempDefects, null);
}
/**
* 부적합 업데이트
*/
updateTempDefect(index, defectIndex, field, value) {
if (this.tempDefects[index] && this.tempDefects[index][defectIndex]) {
this.tempDefects[index][defectIndex][field] = value;
this.notifyListeners('tempDefects', this.tempDefects, null);
}
}
/**
* 부적합 삭제
*/
removeTempDefect(index, defectIndex) {
if (this.tempDefects[index]) {
this.tempDefects[index].splice(defectIndex, 1);
this.notifyListeners('tempDefects', this.tempDefects, null);
}
}
/**
* 일일 이슈 캐시 설정
*/
setDailyIssuesCache(dateStr, issues) {
this.dailyIssuesCache[dateStr] = issues;
}
/**
* 일일 이슈 캐시 조회
*/
getDailyIssuesCache(dateStr) {
return this.dailyIssuesCache[dateStr] || [];
}
/**
* 상태 초기화
*/
reset() {
this.selectedWorkers.clear();
this.workEntryCounter = 0;
this.currentStep = 1;
this.editingWorkId = null;
this.tempDefects = {};
this.currentDefectIndex = null;
this.dailyIssuesCache = {};
}
/**
* 디버그 출력
*/
debug() {
console.log('[State] 현재 상태:', {
workTypes: this.workTypes.length,
workers: this.workers.length,
projects: this.projects.length,
selectedWorkers: this.selectedWorkers.size,
currentTab: this.currentTab,
incompleteTbms: this.incompleteTbms.length,
tempDefects: Object.keys(this.tempDefects).length
});
}
}
// 전역 인스턴스 생성
window.DailyWorkReportState = new DailyWorkReportState();
// 하위 호환성을 위한 전역 변수 프록시
const stateProxy = window.DailyWorkReportState;
// 기존 전역 변수들과 호환
Object.defineProperties(window, {
workTypes: {
get: () => stateProxy.workTypes,
set: (v) => { stateProxy.workTypes = v; }
},
workStatusTypes: {
get: () => stateProxy.workStatusTypes,
set: (v) => { stateProxy.workStatusTypes = v; }
},
errorTypes: {
get: () => stateProxy.errorTypes,
set: (v) => { stateProxy.errorTypes = v; }
},
issueCategories: {
get: () => stateProxy.issueCategories,
set: (v) => { stateProxy.issueCategories = v; }
},
issueItems: {
get: () => stateProxy.issueItems,
set: (v) => { stateProxy.issueItems = v; }
},
workers: {
get: () => stateProxy.workers,
set: (v) => { stateProxy.workers = v; }
},
projects: {
get: () => stateProxy.projects,
set: (v) => { stateProxy.projects = v; }
},
selectedWorkers: {
get: () => stateProxy.selectedWorkers,
set: (v) => { stateProxy.selectedWorkers = v; }
},
incompleteTbms: {
get: () => stateProxy.incompleteTbms,
set: (v) => { stateProxy.incompleteTbms = v; }
},
tempDefects: {
get: () => stateProxy.tempDefects,
set: (v) => { stateProxy.tempDefects = v; }
},
dailyIssuesCache: {
get: () => stateProxy.dailyIssuesCache,
set: (v) => { stateProxy.dailyIssuesCache = v; }
},
currentTab: {
get: () => stateProxy.currentTab,
set: (v) => { stateProxy.currentTab = v; }
},
currentStep: {
get: () => stateProxy.currentStep,
set: (v) => { stateProxy.currentStep = v; }
},
editingWorkId: {
get: () => stateProxy.editingWorkId,
set: (v) => { stateProxy.editingWorkId = v; }
},
workEntryCounter: {
get: () => stateProxy.workEntryCounter,
set: (v) => { stateProxy.workEntryCounter = v; }
},
currentDefectIndex: {
get: () => stateProxy.currentDefectIndex,
set: (v) => { stateProxy.currentDefectIndex = v; }
},
currentEditingField: {
get: () => stateProxy.currentEditingField,
set: (v) => { stateProxy.currentEditingField = v; }
},
currentTimeValue: {
get: () => stateProxy.currentTimeValue,
set: (v) => { stateProxy.currentTimeValue = v; }
},
selectedWorkplace: {
get: () => stateProxy.selectedWorkplace,
set: (v) => { stateProxy.selectedWorkplace = v; }
},
selectedWorkplaceName: {
get: () => stateProxy.selectedWorkplaceName,
set: (v) => { stateProxy.selectedWorkplaceName = v; }
},
selectedWorkplaceCategory: {
get: () => stateProxy.selectedWorkplaceCategory,
set: (v) => { stateProxy.selectedWorkplaceCategory = v; }
},
selectedWorkplaceCategoryName: {
get: () => stateProxy.selectedWorkplaceCategoryName,
set: (v) => { stateProxy.selectedWorkplaceCategoryName = v; }
}
});