Files
Hyungi Ahn 2b1c7bfb88 feat: 다수 기능 개선 - 순찰, 출근, 작업분석, 모바일 UI 등
- 순찰/점검 기능 개선 (zone-detail 페이지 추가)
- 출근/근태 시스템 개선 (연차 조회, 근무현황)
- 작업분석 대분류 그룹화 및 마이그레이션 스크립트
- 모바일 네비게이션 UI 추가
- NAS 배포 도구 및 문서 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:41:01 +09:00

285 lines
7.3 KiB
JavaScript

/**
* Workplace Management - State Manager
* 작업장 관리 페이지의 전역 상태 관리
*/
class WorkplaceState {
constructor() {
// 마스터 데이터
this.categories = [];
this.workplaces = [];
this.allEquipments = [];
this.existingEquipments = [];
// 현재 상태
this.currentCategoryId = '';
this.currentEditingCategory = null;
this.currentEditingWorkplace = null;
this.currentWorkplaceMapId = null;
// 작업장 지도 관련
this.workplaceCanvas = null;
this.workplaceCtx = null;
this.workplaceImage = null;
this.workplaceIsDrawing = false;
this.workplaceStartX = 0;
this.workplaceStartY = 0;
this.workplaceCurrentRect = null;
this.workplaceEquipmentRegions = [];
// 전체화면 편집기 관련
this.fsCanvas = null;
this.fsCtx = null;
this.fsImage = null;
this.fsIsDrawing = false;
this.fsStartX = 0;
this.fsStartY = 0;
this.fsCurrentRect = null;
this.fsSidebarVisible = true;
// 리스너
this.listeners = new Map();
console.log('[WorkplaceState] 초기화 완료');
}
/**
* 상태 업데이트
*/
update(key, value) {
const prevValue = this[key];
this[key] = value;
this.notifyListeners(key, value, prevValue);
}
/**
* 리스너 등록
*/
subscribe(key, callback) {
if (!this.listeners.has(key)) {
this.listeners.set(key, []);
}
this.listeners.get(key).push(callback);
}
/**
* 리스너 알림
*/
notifyListeners(key, newValue, prevValue) {
const keyListeners = this.listeners.get(key) || [];
keyListeners.forEach(callback => {
try {
callback(newValue, prevValue);
} catch (error) {
console.error(`[WorkplaceState] 리스너 오류 (${key}):`, error);
}
});
}
/**
* 현재 카테고리 변경
*/
setCurrentCategory(categoryId) {
const prevId = this.currentCategoryId;
this.currentCategoryId = categoryId === '' ? '' : categoryId;
this.notifyListeners('currentCategoryId', this.currentCategoryId, prevId);
}
/**
* 현재 카테고리 정보 가져오기
*/
getCurrentCategory() {
if (!this.currentCategoryId) return null;
return this.categories.find(c => c.category_id == this.currentCategoryId);
}
/**
* 현재 카테고리별 작업장 가져오기
*/
getFilteredWorkplaces() {
if (this.currentCategoryId === '') {
return this.workplaces;
}
return this.workplaces.filter(w => w.category_id == this.currentCategoryId);
}
/**
* 작업장 지도 상태 초기화
*/
resetWorkplaceMapState() {
this.workplaceCanvas = null;
this.workplaceCtx = null;
this.workplaceImage = null;
this.workplaceIsDrawing = false;
this.workplaceCurrentRect = null;
}
/**
* 전체화면 편집기 상태 초기화
*/
resetFullscreenState() {
this.fsCanvas = null;
this.fsCtx = null;
this.fsImage = null;
this.fsIsDrawing = false;
this.fsCurrentRect = null;
}
/**
* 통계 계산
*/
getStatistics() {
const total = this.workplaces.length;
const active = this.workplaces.filter(w =>
w.is_active === 1 || w.is_active === true
).length;
const factoryTotal = this.categories.length;
const filtered = this.getFilteredWorkplaces();
const filteredActive = filtered.filter(w =>
w.is_active === 1 || w.is_active === true
).length;
return {
total,
active,
factoryTotal,
filteredTotal: filtered.length,
filteredActive
};
}
/**
* 상태 초기화
*/
reset() {
this.currentEditingCategory = null;
this.currentEditingWorkplace = null;
this.currentWorkplaceMapId = null;
this.resetWorkplaceMapState();
this.resetFullscreenState();
}
/**
* 디버그 출력
*/
debug() {
console.log('[WorkplaceState] 현재 상태:', {
categories: this.categories.length,
workplaces: this.workplaces.length,
currentCategoryId: this.currentCategoryId,
allEquipments: this.allEquipments.length,
workplaceEquipmentRegions: this.workplaceEquipmentRegions.length
});
}
}
// 전역 인스턴스 생성
window.WorkplaceState = new WorkplaceState();
// 하위 호환성을 위한 전역 변수 프록시
const wpStateProxy = window.WorkplaceState;
Object.defineProperties(window, {
categories: {
get: () => wpStateProxy.categories,
set: (v) => { wpStateProxy.categories = v; }
},
workplaces: {
get: () => wpStateProxy.workplaces,
set: (v) => { wpStateProxy.workplaces = v; }
},
currentCategoryId: {
get: () => wpStateProxy.currentCategoryId,
set: (v) => { wpStateProxy.currentCategoryId = v; }
},
currentEditingCategory: {
get: () => wpStateProxy.currentEditingCategory,
set: (v) => { wpStateProxy.currentEditingCategory = v; }
},
currentEditingWorkplace: {
get: () => wpStateProxy.currentEditingWorkplace,
set: (v) => { wpStateProxy.currentEditingWorkplace = v; }
},
workplaceCanvas: {
get: () => wpStateProxy.workplaceCanvas,
set: (v) => { wpStateProxy.workplaceCanvas = v; }
},
workplaceCtx: {
get: () => wpStateProxy.workplaceCtx,
set: (v) => { wpStateProxy.workplaceCtx = v; }
},
workplaceImage: {
get: () => wpStateProxy.workplaceImage,
set: (v) => { wpStateProxy.workplaceImage = v; }
},
workplaceIsDrawing: {
get: () => wpStateProxy.workplaceIsDrawing,
set: (v) => { wpStateProxy.workplaceIsDrawing = v; }
},
workplaceStartX: {
get: () => wpStateProxy.workplaceStartX,
set: (v) => { wpStateProxy.workplaceStartX = v; }
},
workplaceStartY: {
get: () => wpStateProxy.workplaceStartY,
set: (v) => { wpStateProxy.workplaceStartY = v; }
},
workplaceCurrentRect: {
get: () => wpStateProxy.workplaceCurrentRect,
set: (v) => { wpStateProxy.workplaceCurrentRect = v; }
},
workplaceEquipmentRegions: {
get: () => wpStateProxy.workplaceEquipmentRegions,
set: (v) => { wpStateProxy.workplaceEquipmentRegions = v; }
},
existingEquipments: {
get: () => wpStateProxy.existingEquipments,
set: (v) => { wpStateProxy.existingEquipments = v; }
},
allEquipments: {
get: () => wpStateProxy.allEquipments,
set: (v) => { wpStateProxy.allEquipments = v; }
},
fsCanvas: {
get: () => wpStateProxy.fsCanvas,
set: (v) => { wpStateProxy.fsCanvas = v; }
},
fsCtx: {
get: () => wpStateProxy.fsCtx,
set: (v) => { wpStateProxy.fsCtx = v; }
},
fsImage: {
get: () => wpStateProxy.fsImage,
set: (v) => { wpStateProxy.fsImage = v; }
},
fsIsDrawing: {
get: () => wpStateProxy.fsIsDrawing,
set: (v) => { wpStateProxy.fsIsDrawing = v; }
},
fsStartX: {
get: () => wpStateProxy.fsStartX,
set: (v) => { wpStateProxy.fsStartX = v; }
},
fsStartY: {
get: () => wpStateProxy.fsStartY,
set: (v) => { wpStateProxy.fsStartY = v; }
},
fsCurrentRect: {
get: () => wpStateProxy.fsCurrentRect,
set: (v) => { wpStateProxy.fsCurrentRect = v; }
},
fsSidebarVisible: {
get: () => wpStateProxy.fsSidebarVisible,
set: (v) => { wpStateProxy.fsSidebarVisible = v; }
}
});
// currentWorkplaceMapId를 window에도 설정
Object.defineProperty(window, 'currentWorkplaceMapId', {
get: () => wpStateProxy.currentWorkplaceMapId,
set: (v) => { wpStateProxy.currentWorkplaceMapId = v; }
});
console.log('[Module] workplace-management/state.js 로드 완료');