feat: 페이지 구조 재구성 및 사이드바 네비게이션 구현

- 페이지 폴더 재구성: safety/, attendance/ 폴더 신규 생성
  - work/ → safety/: 이슈 신고, 출입 신청 관련 페이지 이동
  - common/ → attendance/: 근태/휴가 관련 페이지 이동
  - admin/ 정리: safety-* 파일들을 safety/로 이동

- 사이드바 네비게이션 메뉴 구현
  - 카테고리별 메뉴: 작업관리, 안전관리, 근태관리, 시스템관리
  - 접기/펼치기 기능 및 상태 저장
  - 관리자 전용 메뉴 자동 표시/숨김

- 날씨 API 연동 (기상청 단기예보)
  - TBM 및 navbar에 현재 날씨 표시
  - weatherService.js 추가

- 안전 체크리스트 확장
  - 기본/날씨별/작업별 체크 유형 추가
  - checklist-manage.html 페이지 추가

- 이슈 신고 시스템 구현
  - workIssueController, workIssueModel, workIssueRoutes 추가

- DB 마이그레이션 파일 추가 (실행 대기)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-02-02 14:27:22 +09:00
parent b6485e3140
commit 74d3a78aa3
116 changed files with 23117 additions and 294 deletions

View File

@@ -46,12 +46,38 @@ router.delete('/sessions/:sessionId/team/:workerId', requireAuth, TbmController.
// 모든 안전 체크 항목 조회
router.get('/safety-checks', requireAuth, TbmController.getAllSafetyChecks);
// 안전 체크 항목 생성 (관리자용)
router.post('/safety-checks', requireAuth, TbmController.createSafetyCheck);
// 안전 체크 항목 수정 (관리자용)
router.put('/safety-checks/:checkId', requireAuth, TbmController.updateSafetyCheck);
// 안전 체크 항목 삭제 (관리자용)
router.delete('/safety-checks/:checkId', requireAuth, TbmController.deleteSafetyCheck);
// TBM 세션의 안전 체크 기록 조회
router.get('/sessions/:sessionId/safety', requireAuth, TbmController.getSafetyRecords);
// 안전 체크 일괄 저장
router.post('/sessions/:sessionId/safety', requireAuth, TbmController.saveSafetyRecords);
// 필터링된 안전 체크리스트 조회 (기본 + 날씨 + 작업별)
router.get('/sessions/:sessionId/safety-checks/filtered', requireAuth, TbmController.getFilteredSafetyChecks);
// ==================== 날씨 관련 ====================
// 현재 날씨 조회
router.get('/weather/current', requireAuth, TbmController.getCurrentWeather);
// 날씨 조건 목록 조회
router.get('/weather/conditions', requireAuth, TbmController.getWeatherConditions);
// 세션 날씨 정보 조회
router.get('/sessions/:sessionId/weather', requireAuth, TbmController.getSessionWeather);
// 세션 날씨 정보 저장
router.post('/sessions/:sessionId/weather', requireAuth, TbmController.saveSessionWeather);
// ==================== 작업 인계 관련 ====================
// 작업 인계 생성

View File

@@ -104,6 +104,24 @@ router.get('/me/monthly-stats', async (req, res) => {
}
});
// ========== 자신의 페이지 권한 조회 (Admin 불필요) ==========
// 📄 사용자 페이지 접근 권한 조회 (자신 또는 Admin)
router.get('/:id/page-access', (req, res, next) => {
const requestedId = parseInt(req.params.id);
const currentUserId = req.user?.user_id;
const userRole = req.user?.role?.toLowerCase();
// 자신의 권한 조회이거나 Admin인 경우 허용
if (requestedId === currentUserId || userRole === 'admin' || userRole === 'system admin') {
return userController.getUserPageAccess(req, res, next);
}
return res.status(403).json({
success: false,
message: '자신의 페이지 권한만 조회할 수 있습니다'
});
});
// ========== 관리자 전용 API ==========
/**
* 모든 라우트에 관리자 권한 적용
@@ -125,13 +143,13 @@ router.put('/:id', userController.updateUser);
// 🔄 사용자 상태 변경
router.put('/:id/status', userController.updateUserStatus);
// 🔑 사용자 비밀번호 초기화 (000000)
router.post('/:id/reset-password', userController.resetUserPassword);
// 🗑️ 사용자 삭제
router.delete('/:id', userController.deleteUser);
// 📄 사용자 페이지 접근 권한 조회
router.get('/:id/page-access', userController.getUserPageAccess);
// 🔐 사용자 페이지 접근 권한 업데이트
// 🔐 사용자 페이지 접근 권한 업데이트 (Admin만)
router.put('/:id/page-access', userController.updateUserPageAccess);
module.exports = router;

View File

@@ -0,0 +1,92 @@
/**
* 작업 중 문제 신고 라우터
*/
const express = require('express');
const router = express.Router();
const workIssueController = require('../controllers/workIssueController');
const { requireMinLevel } = require('../middlewares/auth');
// ==================== 카테고리 관리 ====================
// 모든 카테고리 조회
router.get('/categories', workIssueController.getAllCategories);
// 타입별 카테고리 조회 (nonconformity/safety)
router.get('/categories/type/:type', workIssueController.getCategoriesByType);
// 카테고리 생성 (admin 이상)
router.post('/categories', requireMinLevel('admin'), workIssueController.createCategory);
// 카테고리 수정 (admin 이상)
router.put('/categories/:id', requireMinLevel('admin'), workIssueController.updateCategory);
// 카테고리 삭제 (admin 이상)
router.delete('/categories/:id', requireMinLevel('admin'), workIssueController.deleteCategory);
// ==================== 사전 정의 항목 관리 ====================
// 모든 항목 조회
router.get('/items', workIssueController.getAllItems);
// 카테고리별 항목 조회
router.get('/items/category/:categoryId', workIssueController.getItemsByCategory);
// 항목 생성 (admin 이상)
router.post('/items', requireMinLevel('admin'), workIssueController.createItem);
// 항목 수정 (admin 이상)
router.put('/items/:id', requireMinLevel('admin'), workIssueController.updateItem);
// 항목 삭제 (admin 이상)
router.delete('/items/:id', requireMinLevel('admin'), workIssueController.deleteItem);
// ==================== 통계 ====================
// 통계 요약 (support_team 이상)
router.get('/stats/summary', requireMinLevel('support_team'), workIssueController.getStatsSummary);
// 카테고리별 통계 (support_team 이상)
router.get('/stats/by-category', requireMinLevel('support_team'), workIssueController.getStatsByCategory);
// 작업장별 통계 (support_team 이상)
router.get('/stats/by-workplace', requireMinLevel('support_team'), workIssueController.getStatsByWorkplace);
// ==================== 문제 신고 관리 ====================
// 신고 목록 조회
router.get('/', workIssueController.getAllReports);
// 신고 생성
router.post('/', workIssueController.createReport);
// 신고 상세 조회
router.get('/:id', workIssueController.getReportById);
// 신고 수정
router.put('/:id', workIssueController.updateReport);
// 신고 삭제
router.delete('/:id', workIssueController.deleteReport);
// ==================== 상태 관리 ====================
// 신고 접수 (support_team 이상)
router.put('/:id/receive', requireMinLevel('support_team'), workIssueController.receiveReport);
// 담당자 배정 (support_team 이상)
router.put('/:id/assign', requireMinLevel('support_team'), workIssueController.assignReport);
// 처리 시작
router.put('/:id/start', workIssueController.startProcessing);
// 처리 완료
router.put('/:id/complete', workIssueController.completeReport);
// 신고 종료 (admin 이상)
router.put('/:id/close', requireMinLevel('admin'), workIssueController.closeReport);
// 상태 변경 이력 조회
router.get('/:id/logs', workIssueController.getStatusLogs);
module.exports = router;

View File

@@ -23,4 +23,17 @@ router.put('/:id', workReportController.updateWorkReport);
// DELETE
router.delete('/:id', workReportController.removeWorkReport);
// ========== 부적합 원인 관리 ==========
// 작업 보고서의 부적합 원인 목록 조회
router.get('/:reportId/defects', workReportController.getReportDefects);
// 부적합 원인 저장 (전체 교체)
router.put('/:reportId/defects', workReportController.saveReportDefects);
// 부적합 원인 추가 (단일)
router.post('/:reportId/defects', workReportController.addReportDefect);
// 부적합 원인 삭제
router.delete('/defects/:defectId', workReportController.removeReportDefect);
module.exports = router;