Files
tk-factory-services/system1-factory/web/pages/work/report-create-mobile.html
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

199 lines
7.5 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>작업보고서 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/daily-work-report-mobile.css?v=1">
<link rel="stylesheet" href="/css/mobile.css?v=1">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=2"></script>
<script src="/js/app-init.js?v=9" defer></script>
<style>
/* 데스크탑이면 리다이렉트 */
@media (min-width: 769px) {
body::before {
content: 'redirect';
display: none;
}
}
</style>
<script>
// 데스크탑 접속 시 리다이렉트
if (window.innerWidth > 768) {
window.location.replace('/pages/work/report-create.html');
}
</script>
</head>
<body>
<!-- 네비게이션 바 (app-init에서 로드) -->
<div id="navbar-container"></div>
<div class="m-container">
<!-- Sticky 헤더 -->
<div class="m-header">
<h1 class="m-header-title">작업보고서</h1>
<div class="m-header-action">
<button class="m-btn-add" id="btnAddManual" onclick="MobileReport.addManualCard()" style="display:none;">+ 수동추가</button>
</div>
</div>
<!-- 탭바 -->
<div class="m-tab-bar">
<button class="m-tab-btn active" data-tab="tbm" onclick="MobileReport.switchTab('tbm')">
TBM 작업 <span class="m-tab-count" id="tbmCount">0</span>
</button>
<button class="m-tab-btn" data-tab="manual" onclick="MobileReport.switchTab('manual')">
수동 입력
</button>
<button class="m-tab-btn" data-tab="completed" onclick="MobileReport.switchTab('completed')">
완료
</button>
</div>
<!-- 메시지 -->
<div class="m-message" id="mMessage"></div>
<!-- TBM 탭 -->
<div class="m-tab-content active" id="tabTbm">
<div id="tbmCardList">
<div class="m-loading"></div>
</div>
</div>
<!-- 수동 입력 탭 -->
<div class="m-tab-content" id="tabManual">
<div id="manualCardList">
<div class="m-empty">
<div class="m-empty-icon">📝</div>
<div>수동으로 작업보고서를 추가하세요</div>
<button class="m-btn-add" style="margin-top:0.75rem;" onclick="MobileReport.addManualCard()">+ 수동추가</button>
</div>
</div>
</div>
<!-- 완료 탭 -->
<div class="m-tab-content" id="tabCompleted">
<div class="m-completed-header">
<input type="date" class="m-date-input" id="completedDate" onchange="MobileReport.loadCompletedReports()">
</div>
<div id="completedCardList">
<div class="m-empty">
<div class="m-empty-icon">📋</div>
<div>날짜를 선택하세요</div>
</div>
</div>
</div>
</div>
<!-- 시간 선택 오버레이 -->
<div class="m-time-overlay" id="mTimeOverlay" onclick="MobileReport.closeTimePicker()">
<div class="m-time-popup" onclick="event.stopPropagation()">
<div class="m-time-header">
<h3 class="m-time-title" id="mTimeTitle">작업시간 선택</h3>
<button class="m-time-close" onclick="MobileReport.closeTimePicker()">&times;</button>
</div>
<div class="m-quick-time-grid">
<button class="m-time-btn" onclick="MobileReport.setTime(0.5)">30분</button>
<button class="m-time-btn" onclick="MobileReport.setTime(1)">1시간</button>
<button class="m-time-btn" onclick="MobileReport.setTime(2)">2시간</button>
<button class="m-time-btn" onclick="MobileReport.setTime(4)">4시간</button>
<button class="m-time-btn" onclick="MobileReport.setTime(8)">8시간</button>
</div>
<div class="m-time-adjust">
<button class="m-time-adjust-btn" onclick="MobileReport.adjustTime(-0.5)">-</button>
<span class="m-time-current" id="mTimeCurrent">0시간</span>
<button class="m-time-adjust-btn" onclick="MobileReport.adjustTime(0.5)">+</button>
</div>
<button class="m-time-confirm" onclick="MobileReport.confirmTime()">확인</button>
</div>
</div>
<!-- 부적합 바텀시트 -->
<div class="m-overlay" id="defectOverlay" onclick="MobileReport.hideDefectSheet()"></div>
<div class="m-bottom-sheet" id="defectSheet">
<div class="m-sheet-handle"></div>
<div class="m-sheet-header">
<h3 class="m-sheet-title">부적합 입력</h3>
<button class="m-sheet-close" onclick="MobileReport.hideDefectSheet()">&times;</button>
</div>
<div class="m-sheet-body" id="defectSheetBody">
<!-- 동적 렌더링 -->
</div>
<div class="m-sheet-footer">
<button class="m-submit-btn primary" onclick="MobileReport.saveDefects()">저장</button>
</div>
</div>
<!-- 작업장소 바텀시트 -->
<div class="m-overlay" id="wpOverlay" onclick="MobileReport.hideWorkplaceSheet()"></div>
<div class="m-bottom-sheet" id="wpSheet">
<div class="m-sheet-handle"></div>
<div class="m-sheet-header">
<h3 class="m-sheet-title" id="wpSheetTitle">작업장소 선택</h3>
<button class="m-sheet-close" onclick="MobileReport.hideWorkplaceSheet()">&times;</button>
</div>
<div class="m-sheet-body" id="wpSheetBody">
<!-- 동적 렌더링 -->
</div>
</div>
<!-- 수정 바텀시트 -->
<div class="m-overlay" id="editOverlay" onclick="MobileReport.hideEditSheet()"></div>
<div class="m-bottom-sheet" id="editSheet">
<div class="m-sheet-handle"></div>
<div class="m-sheet-header">
<h3 class="m-sheet-title">보고서 수정</h3>
<button class="m-sheet-close" onclick="MobileReport.hideEditSheet()">&times;</button>
</div>
<div class="m-sheet-body m-edit-form" id="editSheetBody">
<!-- 동적 렌더링 -->
</div>
<div class="m-sheet-footer">
<button class="m-submit-btn primary" onclick="MobileReport.saveEditedReport()">저장</button>
</div>
</div>
<!-- 결과 모달 -->
<div class="m-result-overlay" id="mResultOverlay">
<div class="m-result-box">
<div class="m-result-icon" id="mResultIcon"></div>
<div class="m-result-title" id="mResultTitle"></div>
<div class="m-result-message" id="mResultMessage"></div>
<div class="m-result-details" id="mResultDetails" style="display:none;"></div>
<button class="m-result-close" onclick="MobileReport.closeResult()">확인</button>
</div>
</div>
<!-- 토스트 -->
<div class="m-toast" id="mToast"></div>
<!-- 공통 모듈 -->
<script src="/js/common/utils.js?v=1"></script>
<script src="/js/common/base-state.js?v=1"></script>
<!-- 작업보고서 모듈 (재사용) -->
<script src="/js/daily-work-report/state.js?v=2"></script>
<script src="/js/daily-work-report/utils.js?v=2"></script>
<script src="/js/daily-work-report/api.js?v=2"></script>
<!-- 모바일 전용 UI 로직 -->
<script src="/js/daily-work-report-mobile.js?v=4"></script>
<!-- 모바일 하단 네비게이션 -->
<div id="mobile-nav-container"></div>
<script>
if (window.innerWidth <= 768) {
fetch('/components/mobile-nav.html')
.then(r => r.text())
.then(html => {
document.getElementById('mobile-nav-container').innerHTML = html;
const scripts = document.getElementById('mobile-nav-container').querySelectorAll('script');
scripts.forEach(s => eval(s.textContent));
});
}
</script>
</body>
</html>